Compare commits

...

166 Commits

Author SHA1 Message Date
ameba23
48d943d98e Resolve merge conflict with social-backup-poc 2022-03-04 10:13:20 +01:00
ameba23
7df10d9324 Improve existing backup fragment 2022-03-04 10:09:57 +01:00
ameba23
b7bdad4b67 Add method to get contact ids of existing custodians 2022-03-03 10:48:23 +01:00
ameba23
c0932b4df1 Improve existing backup fragment 2022-03-03 10:47:31 +01:00
ameba23
fabd8298ef Reduce text size in remote wipe display fragment 2022-03-02 17:17:56 +01:00
ameba23
3ca23652ae Success dialog for deactivate remote wipe - additional explainer 2022-03-02 17:09:01 +01:00
ameba23
55efa9dad9 Success dialog for deactivate remote wipe 2022-03-02 16:59:28 +01:00
ameba23
bf1b5c0c95 Rm unused layout file 2022-03-02 16:52:01 +01:00
ameba23
ac685a82e6 Rm unused method 2022-03-02 16:50:39 +01:00
ameba23
97c49d75f8 Revoke all wipers method 2022-03-02 16:49:47 +01:00
ameba23
088a4ee7b2 Buttons on remote wipe display fragment 2022-03-02 16:49:27 +01:00
ameba23
60d0665ad6 Rm mockups fragment 2022-03-02 16:49:06 +01:00
ameba23
9a99b24fe8 Add button to remote wipe display fragment 2022-03-02 11:28:34 +01:00
ameba23
7be5cba64a Improve remote wipe display fragment 2022-03-01 11:45:08 +01:00
ameba23
d463d69971 Add remote wipe display fragment 2022-03-01 11:44:29 +01:00
ameba23
c49ea5173e Improve strings for threshold selector screen 2022-03-01 09:30:06 +01:00
ameba23
255ce7d0a5 Improve remote wipe display fragment 2022-02-28 10:43:36 +01:00
ameba23
fcfbf8e72b Fix bug with displaying existing remote wipers 2022-02-25 09:34:37 +01:00
ameba23
90d0a772be Delete old remote wipe activate success fragment 2022-02-25 09:17:13 +01:00
ameba23
07a556c40f Popup dialog on wipe signal sent successfully 2022-02-25 08:55:54 +01:00
ameba23
5374a27bff Delete old remote wipe setup fragment 2022-02-24 13:46:03 +01:00
ameba23
f7894dd159 Add pop-up dialog on remote wipe setup success 2022-02-24 13:42:50 +01:00
ameba23
5e0f7219c5 return number of confirm messages sent 2022-02-24 13:12:03 +01:00
ameba23
f29278b436 Rm unused method 2022-02-24 13:11:30 +01:00
ameba23
5bd4ab689b return number of confirm messages sent 2022-02-24 13:11:09 +01:00
ameba23
a665179377 Confirm messages method in remote wipe manager 2022-02-24 13:01:39 +01:00
ameba23
d84d638f7c Confirm messages method in briar api 2022-02-24 13:01:23 +01:00
ameba23
a6b85e5979 Remote wipe activated activity 2022-02-24 13:00:45 +01:00
ameba23
4453d7b36d Add remote wipe activated view model 2022-02-24 13:00:27 +01:00
ameba23
9b5e10baf2 Bug with conditional when checking if confirm messages are sent 2022-02-22 10:26:21 +01:00
ameba23
24c95236f0 Add message header for confirm message. Await delivery before wiping 2022-02-22 10:03:16 +01:00
ameba23
91e5d7c70f Improve message for remote wipe confirm 2022-02-22 09:10:19 +01:00
ameba23
99ffbfd5ae Validate remote wipe confirm messages 2022-02-22 08:49:10 +01:00
ameba23
189dd6f7e5 Remote wipe notification 2022-02-22 08:48:56 +01:00
ameba23
4f60873e2a Remote wipe confirm message notifiction 2022-02-21 10:09:20 +01:00
ameba23
cf5522e7fb Rm unused dependency spongy castle from briar-android witness.gradle 2022-02-21 09:58:09 +01:00
ameba23
3f19aeb2d7 Implement CONFIRM remote wipe message 2022-02-21 09:09:10 +01:00
ameba23
bb30fe622d Add CONFIRM remote wipe message type 2022-02-21 09:08:50 +01:00
ameba23
0ae3ace1da Merge branch 'social-backup-poc' into remote-wipe-poc
* social-backup-poc:
  Improve setup password explanation string
  Improve choose password info dialog
  Improve threshold selector screen
  Basic strength meter when choosing threshold
2022-02-21 08:34:34 +01:00
ameba23
7a9794e62a Improve setup password explanation string 2022-02-21 08:25:48 +01:00
ameba23
8ad7ec3a66 Improve choose password info dialog 2022-02-18 09:00:21 +01:00
ameba23
32f1676e55 Improve threshold selector screen 2022-02-15 08:44:36 +01:00
ameba23
ae7a553aa3 Basic strength meter when choosing threshold 2022-02-11 12:02:39 +01:00
ameba23
f1d803820c Fix merge conflicts 2022-02-10 10:53:09 +01:00
ameba23
2c235947b2 Layout of social backup setup explainer 2022-02-10 10:37:27 +01:00
ameba23
c7809add20 Improve social backup setup explainer screen, and add image 2022-02-10 10:18:39 +01:00
ameba23
09823c4402 Add material tap target prompt for social backup feature 2022-02-10 10:03:58 +01:00
ameba23
33cbf2218e Improve social backup setup explainer screen 2022-02-09 12:19:10 +01:00
ameba23
1edfdaeaf0 Remove original custodian return shard success fragment 2022-02-09 11:57:06 +01:00
ameba23
456fd7d2e4 Popup dialog on shards sent for custodian 2022-02-09 11:40:18 +01:00
ameba23
3e7f3fcf5d If we have more than 6 custodians, display on 2 lines 2022-02-08 15:25:49 +01:00
ameba23
62988e7769 Set maximum amount of custodians in UI 2022-02-08 15:06:50 +01:00
ameba23
386658735c Increase size of custodian icons 2022-02-08 11:42:01 +01:00
ameba23
2f2edc3161 Improve visual feedback for threshold selector 2022-02-08 11:19:52 +01:00
ameba23
705de81429 Delete old shards sent fragment 2022-02-08 09:54:38 +01:00
ameba23
d359b1fb9c Popup dialog on shards sent 2022-02-08 09:50:21 +01:00
ameba23
b9867ddc4b Fix styling on disabled recover button 2022-02-07 11:22:17 +01:00
ameba23
67febd4e57 Disable recover button when name is entered 2022-02-04 11:56:16 +01:00
ameba23
c59504b38f Move recover button to author name fragment 2022-02-04 11:40:08 +01:00
ameba23
5b63aa28d3 Fix explainer fragment 2022-02-04 09:08:13 +01:00
ameba23
c9140195cc Rename social backup setup activity 2022-02-04 09:01:53 +01:00
ameba23
5a116f08c5 Add string for explainer button 2022-02-02 11:17:07 +01:00
ameba23
daf233ccd7 Add module, tidy 2022-02-02 11:12:56 +01:00
ameba23
43e8d06493 Add view model for setup process, add setup explainer fragment 2022-02-02 10:30:50 +01:00
ameba23
6d6cbaf769 Remove only invalid pluralisation rules in Indonesian language 2022-01-13 08:54:52 +01:00
ameba23
02743867df Comment out plural strings to avoid formatting problems in Indonesian 2022-01-12 14:56:36 +01:00
ameba23
36d83c8974 Disable expiring warning as a workaround for i18n issue 2022-01-12 14:21:58 +01:00
ameba23
c9ddcf50f1 Use in language code rather than id 2022-01-10 09:41:20 +01:00
ameba23
12148201e4 Rm untranslatable strings 2022-01-10 09:27:34 +01:00
ameba23
2ec7c2d6fc Add language code to arrays.xml 2022-01-10 09:02:41 +01:00
ameba23
deaadd6505 Add Bahasa Indonesian translation strings 2022-01-10 08:54:04 +01:00
ameba23
fa639ec45d Improve activate remote wipe explainer 2021-10-12 11:06:54 +02:00
ameba23
b9363b16b7 Add explainer screen when setting up remote wipe 2021-10-12 09:26:27 +02:00
ameba23
ba9661f7c8 Fix bug with remote wipe activated success button 2021-10-08 12:21:53 +02:00
ameba23
b2341e6392 Resolve merge conflict with social-backup-poc 2021-10-06 11:32:11 +02:00
ameba23
01fd193686 Fix setting default threshold slider position 2021-10-06 10:26:32 +02:00
ameba23
f1b8edd8cf Rm danger of loss message with 2 custodians 2021-10-06 10:19:25 +02:00
ameba23
b9c614acfb Add button when displaying remote wipers allowing the list of wipers to be modified 2021-09-07 13:20:01 +02:00
ameba23
336866da51 Revoke existing wipers that are not in the updated set of wipers 2021-09-07 12:44:41 +02:00
ameba23
342cfeab08 Make it possible to amend list of wipers 2021-09-07 11:54:36 +02:00
ameba23
5895bc3427 Change spongy to bouncy for briar-headless 2021-09-07 09:58:59 +02:00
akwizgran
bb775901e3 Resolve conflict on cherry pick commit to use ByteBuddyClassImposteriser 2021-09-07 09:58:27 +02:00
ameba23
c76d419ecb Tell animal sniffer gradle plugin to ignore java.util.Objects 2021-09-06 12:27:57 +02:00
ameba23
581ecc9aaa Fix header problem with revoke remote wipe messages 2021-09-01 11:59:12 +02:00
ameba23
18d1dd041d Fix type when sending revoke messages 2021-08-31 13:03:58 +02:00
ameba23
03a624ab8f Add revoke remote wipe conversation notification on revoke received 2021-08-31 12:59:39 +02:00
ameba23
9a28203437 Add revoke remote wipe conversation notification 2021-08-31 12:55:48 +02:00
ameba23
d81964844f Fix success fragment 2021-08-31 12:55:18 +02:00
ameba23
a26df1d11a Add revoke remote wipe activity to remote wipe module 2021-08-31 12:44:20 +02:00
ameba23
1ae5de8b2f Downgrade bouncy castle 2021-08-31 12:40:44 +02:00
ameba23
7119771c6e Add revoke remote wipe method 2021-08-31 12:40:24 +02:00
ameba23
6e67c1dfbf Add revoke remote wipe status option to conversation actions menu 2021-08-31 12:39:52 +02:00
ameba23
25029e1fca Add a test to check revoke functionality 2021-08-30 12:20:06 +02:00
ameba23
0c4ad98839 Validate revoke messages 2021-08-30 12:19:37 +02:00
ameba23
8605ead547 Rm unused assertions from witness gradle 2021-08-30 12:12:54 +02:00
ameba23
6c6d41e2cb Upgrade gradle to 4.2.2 2021-08-30 12:11:44 +02:00
ameba23
29bc2a5ee9 Switch from spongycastle to bouncy castle 2021-08-30 11:15:28 +02:00
ameba23
f8f573e150 Add revoke wipe method to RemoteWipeManager 2021-08-30 10:48:45 +02:00
ameba23
c6af32650d Add revoke remote wipe back end functionality 2021-08-30 10:47:13 +02:00
ameba23
2d5e0ee840 Add an additional message type for revoking remote wipe status 2021-08-30 10:46:40 +02:00
ameba23
c64815ca16 Merge branch 'social-backup-poc' into remote-wipe-poc
* social-backup-poc:
  Dont accept shards from mismatched sets - all muss match the first shard received
  Change wording on shard notification messages
  Change message on success fragments
2021-06-22 16:27:08 +02:00
ameba23
5d6a76d64a Implement deleteMessages in RemoteWipeManagerImpl 2021-06-21 13:14:04 +02:00
ameba23
7ff6a72ca1 Merge branch 'social-backup-poc' into remote-wipe-poc
* social-backup-poc:
  Catch NoSuchGroupException when deleting contacts
  Implement deleteMessages in SocialBackupManagerImpl
  Implement deleteAllMessages in SocialBackupManagerImpl
  Add delete all messages to integration test
2021-06-21 13:03:19 +02:00
ameba23
68c880b257 Merge branch 'social-backup-poc' into remote-wipe-poc
* social-backup-poc:
  SecretOwnerTask also passes a provider of AuthenticatedCipher
2021-06-16 08:35:05 +02:00
ameba23
04e18a79bd Merge branch 'social-backup-poc' into remote-wipe-poc
* social-backup-poc:
  Use a provider to instantiate AuthenticatedCipher on each use, to prevent concurrency problems
2021-06-15 21:11:01 +02:00
ameba23
1217c2affb Merge branch 'social-backup-poc' into remote-wipe-poc
* social-backup-poc:
  Fix bug with qrCodeRead flag
  Fix bug with qrCodeRead flag
2021-06-15 16:32:24 +02:00
ameba23
736651051d Update remote wipe explainer drawable 2021-06-03 10:46:31 +02:00
ameba23
2177036044 Display expiration date on outgoing remote wipe message notification 2021-06-03 09:37:15 +02:00
ameba23
ab136d3167 Move RemoteWipeConstants to briar-api 2021-06-03 09:36:26 +02:00
ameba23
61bae55d7c Replace println with LOG in RemoteWipeManagerImpl 2021-06-01 11:15:18 +02:00
ameba23
aa9216a21e Update integration test to account for wipe messages not having headers on the remote side 2021-06-01 11:02:29 +02:00
ameba23
6bdfeb68a6 Only add remote wipe message headers to local messages 2021-05-31 14:56:36 +02:00
ameba23
985779c633 Assume remote wipe message headers are local 2021-05-31 14:56:07 +02:00
ameba23
9c0a58e3ac Merge branch social-backup-poc 2021-05-31 13:43:43 +02:00
ameba23
a448211549 Remote notification message on receiving wipe signal 2021-05-31 13:40:40 +02:00
ameba23
b4de33c58d Put the listener for remote wipe activated event in BriarService rather than AndroidNotificationManager 2021-05-28 10:04:21 +02:00
ameba23
6b10c88858 Add a RemoteWipeActivatedActivity, and listen for the event in AndroidNotificationManager 2021-05-27 12:26:27 +02:00
ameba23
b453f9b33a Add success fragment after sending an activate remote wipe signal 2021-05-26 09:12:16 +02:00
ameba23
ec21df55f8 Update message encoder and RemoteWipeManager for the new api for RemoteWipeMessageHeader 2021-05-25 12:56:51 +02:00
ameba23
a8bef40fee Display message when getting or sending a remote wipe wipe message 2021-05-25 12:55:46 +02:00
ameba23
d42c25ebf7 Move remote wipe MessageType enum to briar-api 2021-05-25 12:55:26 +02:00
ameba23
76c37431ba Shorten explainer string to fit on screen 2021-05-25 11:31:59 +02:00
ameba23
a183f16a3d Set activity view 2021-05-25 11:31:17 +02:00
ameba23
cc37529f9f Add activate remote wipe activity to manifest 2021-05-25 11:21:21 +02:00
ameba23
7eea532a81 Add explainer fragment for activating a remote wipe 2021-05-25 11:18:22 +02:00
ameba23
4d5bad13ca Only show remote wipe menu item if we are a remote wiper for that contact 2021-05-25 09:52:13 +02:00
ameba23
ef7d182a74 Error message on failure to set up remote wipe 2021-05-21 11:34:54 +02:00
ameba23
0fe699c9b5 RemoteWipeSetupSuccess fragment 2021-05-21 11:22:44 +02:00
ameba23
29ef603122 Add RemoteWipeActivatedEvent to activate wipe 2021-05-18 11:02:02 +02:00
ameba23
67015d7294 Improve wording for received setup message notification 2021-05-17 17:39:01 +02:00
ameba23
78a91d43b2 Update RemoteWipeMessageHeader 2021-05-17 17:16:57 +02:00
ameba23
d8a0b6f877 Add remote wipe menu item to ConversationActivity 2021-05-17 17:14:58 +02:00
ameba23
7d86ec5510 Add to BriarCoreEagerSingletons 2021-05-17 17:14:11 +02:00
ameba23
6f8f9eaf9f ActivateRemoteWipe activity and view model 2021-05-17 17:13:36 +02:00
ameba23
60065fe38f Format test for displaying existing wipers 2021-05-17 12:17:28 +02:00
ameba23
ff493273c1 Add remote wipe display fragment to show details of an existing setup 2021-05-17 11:52:04 +02:00
ameba23
308b9b3ec1 Add a MutableLiveData to RemoteWipeSetupState 2021-05-15 18:43:39 +02:00
ameba23
31950aef9a Create RemoteWipeSetupModule which binds the view model 2021-05-15 16:24:00 +02:00
ameba23
f0d42e0d4f Add RemoteWipeSetupActivity to manifest and settings menu 2021-05-14 12:49:37 +02:00
ameba23
f2f70fa110 Rm unused class 2021-05-14 12:40:00 +02:00
ameba23
024511aefc RemoteWipeSetup activity and view model, wiper selector fragment 2021-05-14 12:39:37 +02:00
ameba23
2de10e6f1b Sleep between messages in test 2021-05-11 12:43:48 +02:00
ameba23
92d31aa106 Add an event for received setup messages 2021-05-11 11:37:36 +02:00
ameba23
71c502df52 Create RemoteWipeReceivedEvent 2021-05-11 11:07:15 +02:00
ameba23
fd015d4992 Tidy 2021-05-11 11:04:12 +02:00
ameba23
5f3ec0846e Ignore old wipe messages when receiving 2021-05-11 11:03:08 +02:00
ameba23
892943ddf9 Ignore old wipe messages 2021-05-11 10:59:05 +02:00
ameba23
ad14a0cef8 Additional test for duplicate wipe messages 2021-05-11 09:57:36 +02:00
ameba23
3404a7d02a Check metadata for wipers in test 2021-05-10 10:31:23 +02:00
ameba23
c8c28eb6a0 Add method to get the local list of wipers 2021-05-10 10:31:04 +02:00
ameba23
d45b4be453 Update implementation and test for panic observer 2021-05-10 10:07:26 +02:00
ameba23
f998482e93 Add a panic observer 2021-05-10 10:07:02 +02:00
ameba23
7fb986ea9a Store threshold as constant 2021-05-07 17:24:11 +02:00
ameba23
d9fe8d962f Store incoming valid remote wipe messages in metadata, update test 2021-05-07 17:21:12 +02:00
ameba23
cfc705ca41 Update test 2021-05-07 11:01:35 +02:00
ameba23
e97114e322 Add method to know if you are a wiper for a given contact 2021-05-07 11:01:24 +02:00
ameba23
eb4146b175 Update MessagingController for briar-headless 2021-05-06 18:31:51 +02:00
ameba23
7659b9decb Display message when getting or sending a remote wipe setup message 2021-05-06 18:30:51 +02:00
ameba23
a93cbf852b RemoteWipeManager builds messages using the message encoder 2021-05-06 17:48:56 +02:00
ameba23
fe79a18061 Create Message encoder, parser and validator for remote wipe 2021-05-06 17:48:10 +02:00
ameba23
ae1ad4be24 RemoteWipeModule should register with ClientVersioningManager, add contact hook 2021-05-06 13:48:53 +02:00
ameba23
014db8d45f Update RemoteWipeManager 2021-05-06 11:53:22 +02:00
ameba23
f089c0da3e Add a RemoteWipeMessageHeader 2021-05-06 11:53:03 +02:00
ameba23
7b9d2621b7 Add RemoteWipeModule to BriarCoreModule 2021-05-05 19:13:27 +02:00
ameba23
0aea84a1b5 RemoteWipeModule and beginnings of integration test 2021-05-05 19:03:43 +02:00
ameba23
0224733b10 RemoteWipeManager WIP 2021-05-05 14:35:30 +02:00
121 changed files with 4558 additions and 1034 deletions

View File

@@ -1,39 +1,39 @@
dependencyVerification {
verify = [
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'com.android.tools.analytics-library:protos:27.1.1:protos-27.1.1.jar:13f77e73762e58ab372d140b3a6be6903aea9775b62dd14fbc62d4cc7069c9a4',
'com.android.tools.analytics-library:shared:27.1.1:shared-27.1.1.jar:82930a52001410e97d809930b670f4de3002286975f046b9de5f6b777b06d366',
'com.android.tools.analytics-library:tracker:27.1.1:tracker-27.1.1.jar:31bc5a00be0055bac89c9b2f34751883e987cd89e3ac1783720645c164f591d9',
'com.android.tools.analytics-library:protos:27.2.2:protos-27.2.2.jar:02482564443c294dfe87c5f2b25387f724a698a09ed58e0cf0127400caa35a19',
'com.android.tools.analytics-library:shared:27.2.2:shared-27.2.2.jar:0efe017ca17ee775c5af386475a09799a1282faa04821d54810c1a34f6348d9c',
'com.android.tools.analytics-library:tracker:27.2.2:tracker-27.2.2.jar:62489d84192dc06219664945c43201654ff85c3b715f46550751512a880d0e39',
'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca',
'com.android.tools.build:apksig:4.1.1:apksig-4.1.1.jar:e0a69da9e5a03986d608b45bbf954ef0e6a0b3f58c1b8315bd169ec08b279e72',
'com.android.tools.build:apkzlib:4.1.1:apkzlib-4.1.1.jar:ba4b5e419b6be0130eae7f8301c3a551ad3976f487d2e0c6852ebb175ac41127',
'com.android.tools.build:builder-model:4.1.1:builder-model-4.1.1.jar:e95c99cc298ad67b8deb6ced99c51abc8f59afebedad044b1a10dde14646a4dd',
'com.android.tools.build:builder-test-api:4.1.1:builder-test-api-4.1.1.jar:464f596ab261c051c3847406748e843770dea123f6fa5fee8a9390644e709b7a',
'com.android.tools.build:builder:4.1.1:builder-4.1.1.jar:0f78d4759d2f7b57b95865522ec34596ba419b9982f3b25e3449213f9c98b80d',
'com.android.tools.build:gradle-api:4.1.1:gradle-api-4.1.1.jar:d42e6b539e4c1353ad3546e75ec8ce11a017b97481023e8ea18577eefe374358',
'com.android.tools.build:manifest-merger:27.1.1:manifest-merger-27.1.1.jar:7a45fa143687859bb2e5a961dcf6ee88094d3853de0cb543dc03dbcb0f4b554b',
'com.android.tools.ddms:ddmlib:27.1.1:ddmlib-27.1.1.jar:da6e4bd834b6a85dae8019039849d8bd96933347dfbf460df74913ddade6e40a',
'com.android.tools.external.com-intellij:intellij-core:27.1.1:intellij-core-27.1.1.jar:2591a7363c4443c59bf9f793730acafce9d6ec3076e2f46716edaf53a41b6fb6',
'com.android.tools.external.com-intellij:kotlin-compiler:27.1.1:kotlin-compiler-27.1.1.jar:5054ae770ba788f110303c65abd6b1fa28eccf52dee1274510e201b2b81885c8',
'com.android.tools.external.org-jetbrains:uast:27.1.1:uast-27.1.1.jar:54cd8f6886a9d2f5641659dd5c91f626629672cd48301f7f0bd6aad9bd448714',
'com.android.tools.layoutlib:layoutlib-api:27.1.1:layoutlib-api-27.1.1.jar:8a9a22e3b309521ea83b724e5a89cfdac6076f52d675c0e17d77b05527bc0f8c',
'com.android.tools.lint:lint-api:27.1.1:lint-api-27.1.1.jar:c1d8176094cb0478786070d40533efb578ebc53529a82f6ef5bee879bdca418b',
'com.android.tools.lint:lint-checks:27.1.1:lint-checks-27.1.1.jar:3899c91e00bd059b40c31a9ca00cd0f8303191947608735ae1b657323693fb61',
'com.android.tools.lint:lint-gradle-api:27.1.1:lint-gradle-api-27.1.1.jar:26aa89d38b9825cc73229daa82a68875801c8b8491f30497ce62aff1f206eb0d',
'com.android.tools.lint:lint-gradle:27.1.1:lint-gradle-27.1.1.jar:f7355823ead869f4d28184ba28b7a0c693b507519a2d3705bb9848a0f35b3756',
'com.android.tools.lint:lint-model:27.1.1:lint-model-27.1.1.jar:bc23c0c413bdfca59dac2cd56b870d8360d009e9ec0d365e71f774bcf127971d',
'com.android.tools.lint:lint:27.1.1:lint-27.1.1.jar:2f6038a5398a42bd591883c3f5e5894f4ec52ca1c3683bf94fa8553c1700af81',
'com.android.tools:annotations:27.1.1:annotations-27.1.1.jar:ff28c504d2acb9fd1a5ffbd97ae85cf59ee18c76927525aad250509bccf2cab1',
'com.android.tools:common:27.1.1:common-27.1.1.jar:63d9a2a9ad6d278db319f3749b9f50bdf5457ef7020074a1bebe124e714b535c',
'com.android.tools:dvlib:27.1.1:dvlib-27.1.1.jar:998a54201fc1cefee5f2399215e95c42b1f64f9e1d8f4452eb8255c68ba5440f',
'com.android.tools:repository:27.1.1:repository-27.1.1.jar:d25b74ccabf4d876903efb375e9af6fb380d8ae0445bb74bbdcc225c1e37fa1d',
'com.android.tools:sdk-common:27.1.1:sdk-common-27.1.1.jar:4473ae97d0ef7061ee1de61041d5aa97405ae08e44c09cf7bb278b42e4b97c7c',
'com.android.tools:sdklib:27.1.1:sdklib-27.1.1.jar:08e6b83961ac9724b3c1e3d0eff971f13be6701292c77914b8794480f3391250',
'com.android:signflinger:4.1.1:signflinger-4.1.1.jar:0c66825988873ec2d51057fa463f54a8f18fc7326ff4530b9da363b71e97ce60',
'com.android:zipflinger:4.1.1:zipflinger-4.1.1.jar:0a8c3e52ac13dd031236f9fb5ba4408b1d5dcd12325a05440b36da09d8881446',
'com.android.tools.build:apksig:4.2.2:apksig-4.2.2.jar:632690bf641b429dcb31650e6b2f6a2e87c4ac8afd45a6ba3cbc99fb1612178f',
'com.android.tools.build:apkzlib:4.2.2:apkzlib-4.2.2.jar:3b5167c1265e97f65201c4d2be6a6f72165a3aa2fe9e0594a59b67af9e9e97b9',
'com.android.tools.build:builder-model:4.2.2:builder-model-4.2.2.jar:41868de0cb88ae70b828eee4191c13e0233f433abb1becdf6a2bd391bd446bc0',
'com.android.tools.build:builder-test-api:4.2.2:builder-test-api-4.2.2.jar:2f305c6d3a7b637d736b821bad372dcabd959e979f2065a9f65bac1e7b4d1875',
'com.android.tools.build:builder:4.2.2:builder-4.2.2.jar:40fedd0d16db8f34ddb4eaf812d966b90ef1764f65cf119030442823bcf995cd',
'com.android.tools.build:gradle-api:4.2.2:gradle-api-4.2.2.jar:dd4ef35bbbfb8fc2d20e3311c76b516bc1672e82b61cb3a59fc877da0f9b4f61',
'com.android.tools.build:manifest-merger:27.2.2:manifest-merger-27.2.2.jar:971974756f32d9e94c857d92772b1499b0b0f5d9c70cb8ebbd20d9bbf804a923',
'com.android.tools.ddms:ddmlib:27.2.2:ddmlib-27.2.2.jar:9ab0f9b58737c316af454184705854c75936ca3531f21acc29bd68a3343334d1',
'com.android.tools.external.com-intellij:intellij-core:27.2.2:intellij-core-27.2.2.jar:01619d5dc28ec909cbdee699f1f13056e84462faf6dccf4817561293fb28bef0',
'com.android.tools.external.com-intellij:kotlin-compiler:27.2.2:kotlin-compiler-27.2.2.jar:71bd460199ce7293ecc54b91a115319c1e4b585eca5a5b3699f6a406f29e626c',
'com.android.tools.external.org-jetbrains:uast:27.2.2:uast-27.2.2.jar:efa59302fd433015e993143530cecb456b63d10d0b89bd1d3b1a016904338a65',
'com.android.tools.layoutlib:layoutlib-api:27.2.2:layoutlib-api-27.2.2.jar:f0901f2295d814e82ad95850ea2103dd89d8489e01727fafa55ccccc0dccd163',
'com.android.tools.lint:lint-api:27.2.2:lint-api-27.2.2.jar:1ecb5959c8e624ee49cdf9178de67bb0e823b4382ed253410eb36afe5c458b05',
'com.android.tools.lint:lint-checks:27.2.2:lint-checks-27.2.2.jar:989e545a6b5e398e63a9f3608da02d6111f2241faec1baa0a3b4492cb03aeaf2',
'com.android.tools.lint:lint-gradle-api:27.2.2:lint-gradle-api-27.2.2.jar:2be9c69d6fbbfb012ff6521fdfcb22eb7cfaa57d108e07bb1d4143dae9c1b433',
'com.android.tools.lint:lint-gradle:27.2.2:lint-gradle-27.2.2.jar:742dedd5ccb459a245a35bf4fa16dfecc762da1a6b1741332cfe5228e812301a',
'com.android.tools.lint:lint-model:27.2.2:lint-model-27.2.2.jar:ee31012586462bea2d591b6175934e5f29b6f781a78fda50f79387972364b9ab',
'com.android.tools.lint:lint:27.2.2:lint-27.2.2.jar:7247016af7fba8cabee6ae887515b144f5a2ff7823422654daf23be9202f8fb1',
'com.android.tools:annotations:27.2.2:annotations-27.2.2.jar:9375fb2df5c0cf1b46fef9e65b3a27ac88925ccf90054b19ae0ca0adc7036fe1',
'com.android.tools:common:27.2.2:common-27.2.2.jar:a76f4e10cad39bed317be031fee915d280aa8bc11616c58ab94e051b1e38769d',
'com.android.tools:dvlib:27.2.2:dvlib-27.2.2.jar:9931c6b57460b5f8cc2613ca5ff8596aa089a67655ace13d173f90538ecb4301',
'com.android.tools:repository:27.2.2:repository-27.2.2.jar:ac5f9b19dc5d9d08e80b57da76059f5760ca76c221e40ffd4bf43d7b13991674',
'com.android.tools:sdk-common:27.2.2:sdk-common-27.2.2.jar:b147acc13850808d61fc391ccfeeebdf90841b461a7042acb2d92e466da8e674',
'com.android.tools:sdklib:27.2.2:sdklib-27.2.2.jar:fae0bafbe8b4f546cf64986a22b7d8ed108d45519366ff22f0170a9cf3ea7f34',
'com.android:signflinger:4.2.2:signflinger-4.2.2.jar:4d7aafd9666707b483b1ad2c466824287cf2e379dda1d204dd3b7e453ffcf760',
'com.android:zipflinger:4.2.2:zipflinger-4.2.2.jar:8e4677086c9a8f4a67374a4edc31db7e481f0d9b85907263c51ca72452c23a93',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.gson:gson:2.8.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f',
'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
'com.google.dagger:dagger-spi:2.24:dagger-spi-2.24.jar:c038445d14dbcb4054e61bf49e05009edf26fce4fdc7ec1a9db544784f68e718',
@@ -54,17 +54,19 @@ dependencyVerification {
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
'com.sun.istack:istack-commons-runtime:3.0.7:istack-commons-runtime-3.0.7.jar:6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf',
'com.sun.xml.fastinfoset:FastInfoset:1.2.15:FastInfoset-1.2.15.jar:785861db11ca1bd0d1956682b974ad73eb19cd3e01a4b3fa82d62eca97210aec',
'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef',
'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511',
'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
'commons-logging:commons-logging:1.2:commons-logging-1.2.jar:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636',
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'javax.activation:javax.activation-api:1.2.0:javax.activation-api-1.2.0.jar:43fdef0b5b6ceb31b0424b208b930c74ab58fac2ceeb7b3f6fd3aeb8b5ca4393',
'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071',
'jakarta.activation:jakarta.activation-api:1.2.1:jakarta.activation-api-1.2.1.jar:8b0a0f52fa8b05c5431921a063ed866efaa41dadf2e3a7ee3e1961f2b0d9645b',
'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2:jakarta.xml.bind-api-2.3.2.jar:69156304079bdeed9fc0ae3b39389f19b3cc4ba4443bc80508995394ead742ea',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'javax.xml.bind:jaxb-api:2.3.1:jaxb-api-2.3.1.jar:88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'net.bytebuddy:byte-buddy:1.9.12:byte-buddy-1.9.12.jar:3688c3d434bebc3edc5516296a2ed0f47b65e451071b4afecad84f902f0efc11',
'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
@@ -84,24 +86,24 @@ dependencyVerification {
'org.codehaus.groovy:groovy-all:2.4.15:groovy-all-2.4.15.jar:51d6c4e71782e85674239189499854359d380fb75e1a703756e3aaa5b98a5af0',
'org.codehaus.mojo:animal-sniffer-annotations:1.17:animal-sniffer-annotations-1.17.jar:92654f493ecfec52082e76354f0ebf87648dc3d5cec2e3c3cdb947c016747a53',
'org.codehaus.mojo:animal-sniffer-annotations:1.18:animal-sniffer-annotations-1.18.jar:47f05852b48ee9baefef80fa3d8cea60efa4753c0013121dd7fe5eef2e5c729d',
'org.glassfish.jaxb:jaxb-runtime:2.3.1:jaxb-runtime-2.3.1.jar:45fecfa5c8217ce1f3652ab95179790ec8cc0dec0384bca51cbeb94a293d9f2f',
'org.glassfish.jaxb:txw2:2.3.1:txw2-2.3.1.jar:34975dde1c6920f1a39791142235689bc3cd357e24d05edd8ff93b885bd68d60',
'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b',
'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jetbrains.kotlin:kotlin-reflect:1.3.72:kotlin-reflect-1.3.72.jar:a188d9367de1c4ee9479db630985c0597b20709c83161b1430d24edb27e38c40',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72:kotlin-stdlib-common-1.3.72.jar:5e7d1552863e480c1628b1cc39ce230ef829f5b7230106215a05acda5172203a',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72:kotlin-stdlib-jdk7-1.3.72.jar:40566c0c08d414b9413ba556ff7f8a0b04b98b9f0f424d122dd2088510efccc4',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72:kotlin-stdlib-jdk8-1.3.72.jar:133da70cfc07b56094282eac5c59bccd59f167ee2ead22e5282876d8bc10bf95',
'org.jetbrains.kotlin:kotlin-stdlib:1.3.72:kotlin-stdlib-1.3.72.jar:3856a7349ebacd6d1be6802b2fed9c4dc2c5a564ea92b6b945ac988243d4b16b',
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains.intellij.deps:trove4j:1.0.20181211:trove4j-1.0.20181211.jar:affb7c85a3c87bdcf69ff1dbb84de11f63dc931293934bc08cd7ab18de083601',
'org.jetbrains.kotlin:kotlin-reflect:1.4.31:kotlin-reflect-1.4.31.jar:91fad0b42974a7d5811e30a61f05706e176b144235717c6de7e81e3a781028f2',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.31:kotlin-stdlib-common-1.4.31.jar:57962f44371a746b678218a0802a8712c6255206de9a69ede215e3aa4b044708',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.31:kotlin-stdlib-jdk7-1.4.31.jar:1f966e54e86cf4b7d7014afdce04e0f3ee4625084cda3494edccc7b84af52664',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.31:kotlin-stdlib-jdk8-1.4.31.jar:b2f8364435ebcb0106ff9d4415a11ffdef8ec7786ee6e5ed465a01556cbd1683',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.31:kotlin-stdlib-1.4.31.jar:76a599d88b167e8ac90879b6daa722c6ad3452ba714c9aba19bd196544b97f1c',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.jvnet.staxex:stax-ex:1.8:stax-ex-1.8.jar:95b05d9590af4154c6513b9c5dc1fb2e55b539972ba0a9ef28e9a0c01d83ad77',
'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a',
'org.objenesis:objenesis:3.0.1:objenesis-3.0.1.jar:7a8ff780b9ff48415d7c705f60030b0acaa616e7f823c98eede3b63508d4e984',
'org.ow2.asm:asm-analysis:7.0:asm-analysis-7.0.jar:e981f8f650c4d900bb033650b18e122fa6b161eadd5f88978d08751f72ee8474',
'org.ow2.asm:asm-commons:7.0:asm-commons-7.0.jar:fed348ef05958e3e846a3ac074a12af5f7936ef3d21ce44a62c4fa08a771927d',
@@ -109,5 +111,7 @@ dependencyVerification {
'org.ow2.asm:asm-util:7.0:asm-util-7.0.jar:75fbbca440ef463f41c2b0ab1a80abe67e910ac486da60a7863cbcb5bae7e145',
'org.ow2.asm:asm:7.0:asm-7.0.jar:b88ef66468b3c978ad0c97fd6e90979e56155b4ac69089ba7a44e9aa7ffe9acf',
'org.ow2.asm:asm:7.1:asm-7.1.jar:4ab2fa2b6d2cc9ccb1eaa05ea329c407b47b13ed2915f62f8c4b8cc96258d4de',
'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
]
}

View File

@@ -10,7 +10,7 @@ apply from: '../dagger.gradle'
dependencies {
implementation project(path: ':bramble-api', configuration: 'default')
implementation 'com.madgag.spongycastle:core:1.58.0.0'
implementation 'org.bouncycastle:bcprov-jdk15on:1.65'
implementation 'com.h2database:h2:1.4.192' // The last version that supports Java 1.6
implementation 'org.bitlet:weupnp:0.1.4'
implementation 'net.i2p.crypto:eddsa:0.2.0'

View File

@@ -21,9 +21,9 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.SecureRandomProvider;
import org.briarproject.bramble.util.ByteUtils;
import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.crypto.CryptoException;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.whispersystems.curve25519.Curve25519;
import org.whispersystems.curve25519.Curve25519KeyPair;

View File

@@ -6,33 +6,33 @@ import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.spongycastle.crypto.BasicAgreement;
import org.spongycastle.crypto.BlockCipher;
import org.spongycastle.crypto.CipherParameters;
import org.spongycastle.crypto.CryptoException;
import org.spongycastle.crypto.DerivationFunction;
import org.spongycastle.crypto.KeyEncoder;
import org.spongycastle.crypto.Mac;
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.spongycastle.crypto.digests.SHA256Digest;
import org.spongycastle.crypto.engines.AESLightEngine;
import org.spongycastle.crypto.engines.IESEngine;
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.spongycastle.crypto.generators.EphemeralKeyPairGenerator;
import org.spongycastle.crypto.generators.KDF2BytesGenerator;
import org.spongycastle.crypto.macs.HMac;
import org.spongycastle.crypto.modes.CBCBlockCipher;
import org.spongycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.spongycastle.crypto.params.AsymmetricKeyParameter;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.crypto.params.IESWithCipherParameters;
import org.spongycastle.crypto.parsers.ECIESPublicKeyParser;
import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.CryptoException;
import org.bouncycastle.crypto.DerivationFunction;
import org.bouncycastle.crypto.KeyEncoder;
import org.bouncycastle.crypto.Mac;
import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
import org.bouncycastle.crypto.digests.SHA256Digest;
import org.bouncycastle.crypto.engines.AESLightEngine;
import org.bouncycastle.crypto.engines.IESEngine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.generators.EphemeralKeyPairGenerator;
import org.bouncycastle.crypto.generators.KDF2BytesGenerator;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.IESWithCipherParameters;
import org.bouncycastle.crypto.parsers.ECIESPublicKeyParser;
import java.io.FileInputStream;
import java.io.FileOutputStream;

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.util.StringUtils;
import org.spongycastle.crypto.generators.SCrypt;
import org.bouncycastle.crypto.generators.SCrypt;
import java.util.logging.Logger;

View File

@@ -4,11 +4,11 @@ import org.briarproject.bramble.api.crypto.KeyParser;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECPoint;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint;
import java.math.BigInteger;
import java.security.GeneralSecurityException;

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import javax.annotation.concurrent.Immutable;

View File

@@ -2,7 +2,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import javax.annotation.concurrent.Immutable;

View File

@@ -9,8 +9,8 @@ import org.briarproject.bramble.api.plugin.TransportId;
import org.briarproject.bramble.api.transport.IncomingKeys;
import org.briarproject.bramble.api.transport.OutgoingKeys;
import org.briarproject.bramble.api.transport.TransportKeys;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import java.security.GeneralSecurityException;

View File

@@ -3,12 +3,12 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.crypto.AuthenticatedCipher;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.spongycastle.crypto.DataLengthException;
import org.spongycastle.crypto.engines.XSalsa20Engine;
import org.spongycastle.crypto.generators.Poly1305KeyGenerator;
import org.spongycastle.crypto.macs.Poly1305;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.engines.XSalsa20Engine;
import org.bouncycastle.crypto.generators.Poly1305KeyGenerator;
import org.bouncycastle.crypto.macs.Poly1305;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import java.security.GeneralSecurityException;

View File

@@ -5,9 +5,9 @@ import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import org.briarproject.bramble.util.Base32;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.SHA3Digest;
import org.spongycastle.util.encoders.Base64;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA3Digest;
import org.bouncycastle.util.encoders.Base64;
import java.nio.charset.Charset;

View File

@@ -3,9 +3,9 @@ package org.briarproject.bramble.rendezvous;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.rendezvous.KeyMaterialSource;
import org.spongycastle.crypto.engines.Salsa20Engine;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.engines.Salsa20Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;

View File

@@ -3,7 +3,7 @@ package org.briarproject.bramble.crypto;
import org.briarproject.bramble.test.BrambleTestCase;
import org.briarproject.bramble.util.StringUtils;
import org.junit.Test;
import org.spongycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import java.util.Random;

View File

@@ -1,115 +0,0 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
import org.spongycastle.crypto.params.ECPublicKeyParameters;
import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
import java.math.BigInteger;
import java.security.SecureRandom;
import static org.junit.Assert.assertEquals;
public class EllipticCurveMultiplicationTest extends BrambleTestCase {
@Test
public void testMultiplierProducesSameResultsAsDefault() throws Exception {
// Instantiate the default implementation of the curve
X9ECParameters defaultX9Parameters =
TeleTrusTNamedCurves.getByName("brainpoolp256r1");
ECCurve defaultCurve = defaultX9Parameters.getCurve();
ECPoint defaultG = defaultX9Parameters.getG();
BigInteger defaultN = defaultX9Parameters.getN();
BigInteger defaultH = defaultX9Parameters.getH();
ECDomainParameters defaultParameters = new ECDomainParameters(
defaultCurve, defaultG, defaultN, defaultH);
// Instantiate an implementation using the Montgomery ladder multiplier
ECDomainParameters montgomeryParameters =
constantTime(defaultParameters);
// Generate two key pairs with each set of parameters, using the same
// deterministic PRNG for both sets of parameters
byte[] seed = new byte[32];
new SecureRandom().nextBytes(seed);
// Montgomery ladder multiplier
SecureRandom random = new PseudoSecureRandom(seed);
ECKeyGenerationParameters montgomeryGeneratorParams =
new ECKeyGenerationParameters(montgomeryParameters, random);
ECKeyPairGenerator montgomeryGenerator = new ECKeyPairGenerator();
montgomeryGenerator.init(montgomeryGeneratorParams);
AsymmetricCipherKeyPair montgomeryKeyPair1 =
montgomeryGenerator.generateKeyPair();
ECPrivateKeyParameters montgomeryPrivate1 =
(ECPrivateKeyParameters) montgomeryKeyPair1.getPrivate();
ECPublicKeyParameters montgomeryPublic1 =
(ECPublicKeyParameters) montgomeryKeyPair1.getPublic();
AsymmetricCipherKeyPair montgomeryKeyPair2 =
montgomeryGenerator.generateKeyPair();
ECPrivateKeyParameters montgomeryPrivate2 =
(ECPrivateKeyParameters) montgomeryKeyPair2.getPrivate();
ECPublicKeyParameters montgomeryPublic2 =
(ECPublicKeyParameters) montgomeryKeyPair2.getPublic();
// Default multiplier
random = new PseudoSecureRandom(seed);
ECKeyGenerationParameters defaultGeneratorParams =
new ECKeyGenerationParameters(defaultParameters, random);
ECKeyPairGenerator defaultGenerator = new ECKeyPairGenerator();
defaultGenerator.init(defaultGeneratorParams);
AsymmetricCipherKeyPair defaultKeyPair1 =
defaultGenerator.generateKeyPair();
ECPrivateKeyParameters defaultPrivate1 =
(ECPrivateKeyParameters) defaultKeyPair1.getPrivate();
ECPublicKeyParameters defaultPublic1 =
(ECPublicKeyParameters) defaultKeyPair1.getPublic();
AsymmetricCipherKeyPair defaultKeyPair2 =
defaultGenerator.generateKeyPair();
ECPrivateKeyParameters defaultPrivate2 =
(ECPrivateKeyParameters) defaultKeyPair2.getPrivate();
ECPublicKeyParameters defaultPublic2 =
(ECPublicKeyParameters) defaultKeyPair2.getPublic();
// The key pairs generated with both sets of parameters should be equal
assertEquals(montgomeryPrivate1.getD(), defaultPrivate1.getD());
assertEquals(montgomeryPublic1.getQ(), defaultPublic1.getQ());
assertEquals(montgomeryPrivate2.getD(), defaultPrivate2.getD());
assertEquals(montgomeryPublic2.getQ(), defaultPublic2.getQ());
// OK, all of the above was just sanity checks - now for the test!
ECDHCBasicAgreement agreement = new ECDHCBasicAgreement();
agreement.init(montgomeryPrivate1);
BigInteger sharedSecretMontgomeryMontgomery =
agreement.calculateAgreement(montgomeryPublic2);
agreement.init(montgomeryPrivate1);
BigInteger sharedSecretMontgomeryDefault =
agreement.calculateAgreement(defaultPublic2);
agreement.init(defaultPrivate1);
BigInteger sharedSecretDefaultMontgomery =
agreement.calculateAgreement(montgomeryPublic2);
agreement.init(defaultPrivate1);
BigInteger sharedSecretDefaultDefault =
agreement.calculateAgreement(defaultPublic2);
// Shared secrets calculated with different multipliers should be equal
assertEquals(sharedSecretMontgomeryMontgomery,
sharedSecretMontgomeryDefault);
assertEquals(sharedSecretMontgomeryMontgomery,
sharedSecretDefaultMontgomery);
assertEquals(sharedSecretMontgomeryMontgomery,
sharedSecretDefaultDefault);
}
private static ECDomainParameters constantTime(ECDomainParameters in) {
ECCurve curve = in.getCurve().configure().setMultiplier(
new MontgomeryLadderMultiplier()).create();
BigInteger x = in.getG().getAffineXCoord().toBigInteger();
BigInteger y = in.getG().getAffineYCoord().toBigInteger();
ECPoint g = curve.createPoint(x, y);
return new ECDomainParameters(curve, g, in.getN(), in.getH());
}
}

View File

@@ -3,30 +3,26 @@ package org.briarproject.bramble.crypto;
import net.i2p.crypto.eddsa.EdDSASecurityProvider;
import net.i2p.crypto.eddsa.KeyPairGenerator;
import org.spongycastle.asn1.sec.SECNamedCurves;
import org.spongycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.spongycastle.asn1.x9.X9ECParameters;
import org.spongycastle.crypto.AsymmetricCipherKeyPair;
import org.spongycastle.crypto.BasicAgreement;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.agreement.ECDHBasicAgreement;
import org.spongycastle.crypto.agreement.ECDHCBasicAgreement;
import org.spongycastle.crypto.digests.Blake2bDigest;
import org.spongycastle.crypto.generators.ECKeyPairGenerator;
import org.spongycastle.crypto.params.ECDomainParameters;
import org.spongycastle.crypto.params.ECKeyGenerationParameters;
import org.spongycastle.crypto.params.ParametersWithRandom;
import org.spongycastle.crypto.signers.DSADigestSigner;
import org.spongycastle.crypto.signers.DSAKCalculator;
import org.spongycastle.crypto.signers.ECDSASigner;
import org.spongycastle.crypto.signers.HMacDSAKCalculator;
import org.spongycastle.math.ec.ECCurve;
import org.spongycastle.math.ec.ECPoint;
import org.spongycastle.math.ec.MontgomeryLadderMultiplier;
import org.bouncycastle.asn1.sec.SECNamedCurves;
import org.bouncycastle.asn1.teletrust.TeleTrusTNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.DSADigestSigner;
import org.bouncycastle.crypto.signers.DSAKCalculator;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
import org.whispersystems.curve25519.Curve25519;
import org.whispersystems.curve25519.Curve25519KeyPair;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.Provider;
@@ -55,14 +51,12 @@ public class EllipticCurvePerformanceTest {
for (String name : SEC_NAMES) {
ECDomainParameters params =
convertParams(SECNamedCurves.getByName(name));
runTest(name + " default", params);
runTest(name + " constant", constantTime(params));
runTest(name, params);
}
for (String name : BRAINPOOL_NAMES) {
ECDomainParameters params =
convertParams(TeleTrusTNamedCurves.getByName(name));
runTest(name + " default", params);
runTest(name + " constant", constantTime(params));
runTest(name, params);
}
runCurve25519Test();
runEd25519Test();
@@ -193,13 +187,4 @@ public class EllipticCurvePerformanceTest {
return new ECDomainParameters(in.getCurve(), in.getG(), in.getN(),
in.getH());
}
private static ECDomainParameters constantTime(ECDomainParameters in) {
ECCurve curve = in.getCurve().configure().setMultiplier(
new MontgomeryLadderMultiplier()).create();
BigInteger x = in.getG().getAffineXCoord().toBigInteger();
BigInteger y = in.getG().getAffineYCoord().toBigInteger();
ECPoint g = curve.createPoint(x, y);
return new ECDomainParameters(curve, g, in.getN(), in.getH());
}
}

View File

@@ -5,7 +5,7 @@ import org.briarproject.bramble.api.crypto.PrivateKey;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.test.BrambleTestCase;
import org.junit.Test;
import org.spongycastle.crypto.CryptoException;
import org.bouncycastle.crypto.CryptoException;
import java.security.SecureRandom;

View File

@@ -1,11 +1,11 @@
package org.briarproject.bramble.crypto;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.spongycastle.crypto.Digest;
import org.spongycastle.crypto.digests.Blake2bDigest;
import org.spongycastle.crypto.engines.Salsa20Engine;
import org.spongycastle.crypto.params.KeyParameter;
import org.spongycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.Blake2bDigest;
import org.bouncycastle.crypto.engines.Salsa20Engine;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import javax.annotation.concurrent.NotThreadSafe;

View File

@@ -15,7 +15,6 @@ dependencyVerification {
'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava:listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar:b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99',
'com.google.j2objc:j2objc-annotations:1.1:j2objc-annotations-1.1.jar:2994a7eb78f2710bd3d3bfb639b2c94e219cedac0d4d084d516e78c16dddecf6',
'com.h2database:h2:1.4.192:h2-1.4.192.jar:225b22e9857235c46c93861410b60b8c81c10dc8985f4faf188985ba5445126c',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
@@ -27,6 +26,7 @@ dependencyVerification {
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'org.apache-extras.beanshell:bsh:2.0b6:bsh-2.0b6.jar:a17955976070c0573235ee662f2794a78082758b61accffce8d3f8aedcd91047',
'org.bitlet:weupnp:0.1.4:weupnp-0.1.4.jar:88df7e6504929d00bdb832863761385c68ab92af945b04f0770b126270a444fb',
'org.bouncycastle:bcprov-jdk15on:1.65:bcprov-jdk15on-1.65.jar:e78f96eb59066c94c94fb2d6b5eb80f52feac6f5f9776898634f8addec6e2137',
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',

View File

@@ -139,16 +139,7 @@
</activity>
<activity
android:name="org.briarproject.briar.android.account.NewOrRecoverActivity"
android:label="@string/activity_name_new_or_recover_account"
android:parentActivityName="org.briarproject.briar.android.login.StartupActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.briarproject.briar.android.login.StartupActivity" />
</activity>
<activity
android:name="org.briarproject.briar.android.socialbackup.DistributedBackupActivity"
android:name="org.briarproject.briar.android.socialbackup.SocialBackupSetupActivity"
android:label="@string/activity_name_distributed_backup"
android:parentActivityName="org.briarproject.briar.android.settings.SettingsActivity">
<meta-data
@@ -168,10 +159,11 @@
<activity
android:name="org.briarproject.briar.android.socialbackup.recover.OwnerReturnShardActivity"
android:label="@string/activity_name_recovery"
android:parentActivityName="org.briarproject.briar.android.account.NewOrRecoverActivity">
android:parentActivityName="org.briarproject.briar.android.account.SetupActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.briarproject.briar.android.account.NewOrRecoverActivity" />
android:value="org.briarproject.briar.android.account.SetupActivity" />
</activity>
<activity
@@ -472,6 +464,42 @@
</intent-filter>
</activity>
<activity
android:name="org.briarproject.briar.android.remotewipe.RemoteWipeActivatedActivity"
android:noHistory="true"
android:theme="@style/TranslucentTheme">
<intent-filter>
<action android:name="org.briarproject.briar.android.AndroidNotifiactionManager" />
</intent-filter>
</activity>
<activity
android:name="org.briarproject.briar.android.remotewipe.RemoteWipeSetupActivity"
android:label="@string/activity_name_remote_wipe"
android:parentActivityName="org.briarproject.briar.android.settings.SettingsActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.briarproject.briar.android.settings.SettingsActivity" />
</activity>
<activity
android:name="org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeActivity"
android:label="@string/activity_name_activate_remote_wipe"
android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.briarproject.briar.android.conversation.ConversationActivity" />
</activity>
<activity
android:name="org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeActivity"
android:label="@string/activity_name_revoke_remote_wipe"
android:parentActivityName="org.briarproject.briar.android.conversation.ConversationActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="org.briarproject.briar.android.conversation.ConversationActivity" />
</activity>
<activity
android:name="org.briarproject.briar.android.logout.ExitActivity"
android:theme="@android:style/Theme.NoDisplay" />

View File

@@ -33,6 +33,7 @@ import org.briarproject.briar.android.forum.ForumActivity;
import org.briarproject.briar.android.login.SignInReminderReceiver;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
import org.briarproject.briar.android.remotewipe.RemoteWipeActivatedActivity;
import org.briarproject.briar.android.splash.SplashScreenActivity;
import org.briarproject.briar.android.util.BriarNotificationBuilder;
import org.briarproject.briar.api.android.AndroidNotificationManager;

View File

@@ -39,9 +39,11 @@ import org.briarproject.briar.android.login.LoginModule;
import org.briarproject.briar.android.navdrawer.NavDrawerModule;
import org.briarproject.briar.android.privategroup.conversation.GroupConversationModule;
import org.briarproject.briar.android.privategroup.list.GroupListModule;
import org.briarproject.briar.android.remotewipe.RemoteWipeModule;
import org.briarproject.briar.android.reporting.DevReportModule;
import org.briarproject.briar.android.settings.SettingsModule;
import org.briarproject.briar.android.sharing.SharingModule;
import org.briarproject.briar.android.socialbackup.SocialBackupSetupModule;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardModule;
import org.briarproject.briar.android.socialbackup.recover.OwnerReturnShardModule;
import org.briarproject.briar.android.test.TestAvatarCreatorImpl;
@@ -94,7 +96,9 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD;
GroupConversationModule.class,
SharingModule.class,
OwnerReturnShardModule.class,
CustodianReturnShardModule.class
CustodianReturnShardModule.class,
RemoteWipeModule.class,
SocialBackupSetupModule.class
})
public class AppModule {

View File

@@ -18,14 +18,19 @@ import com.bumptech.glide.Glide;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.bramble.api.system.AndroidWakeLockManager;
import org.briarproject.briar.R;
import org.briarproject.briar.android.logout.HideUiActivity;
import org.briarproject.briar.android.remotewipe.RemoteWipeActivatedActivity;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.LockManager;
import org.briarproject.briar.api.remotewipe.RemoteWipeActivatedEvent;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -62,7 +67,7 @@ import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGO
import static org.briarproject.briar.api.android.LockManager.ACTION_LOCK;
import static org.briarproject.briar.api.android.LockManager.EXTRA_PID;
public class BriarService extends Service {
public class BriarService extends Service implements EventListener {
public static String EXTRA_START_RESULT =
"org.briarproject.briar.START_RESULT";
@@ -96,6 +101,8 @@ public class BriarService extends Service {
@Inject
volatile AndroidExecutor androidExecutor;
private volatile boolean started = false;
@Inject
volatile EventBus eventBus;
@Override
public void onCreate() {
@@ -173,6 +180,8 @@ public class BriarService extends Service {
filter.addAction("android.intent.action.QUICKBOOT_POWEROFF");
filter.addAction("com.htc.intent.action.QUICKBOOT_POWEROFF");
registerReceiver(receiver, filter);
eventBus.addListener(this);
}, "LifecycleStartup");
}
@@ -239,6 +248,7 @@ public class BriarService extends Service {
wakeLockManager.executeWakefully(() -> {
if (started) lifecycleManager.stopServices();
}, "LifecycleShutdown");
eventBus.removeListener(this);
}, "LifecycleShutdown");
}
@@ -327,6 +337,19 @@ public class BriarService extends Service {
stopSelf(); // This will call onDestroy()
}
/**
* Listens for the remote wipe event
*/
@Override
public void eventOccurred(Event e) {
if (e instanceof RemoteWipeActivatedEvent) {
Intent i = new Intent(this, RemoteWipeActivatedActivity.class);
i.addFlags(FLAG_ACTIVITY_NEW_TASK
| FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
}
}
public class BriarBinder extends Binder {
/**

View File

@@ -30,6 +30,7 @@ public class AuthorNameFragment extends SetupFragment {
private TextInputLayout authorNameWrapper;
private TextInputEditText authorNameInput;
private Button nextButton;
private Button recoverButton;
public static AuthorNameFragment newInstance() {
return new AuthorNameFragment();
@@ -54,6 +55,9 @@ public class AuthorNameFragment extends SetupFragment {
authorNameInput.addTextChangedListener(this);
nextButton.setOnClickListener(this);
recoverButton = v.findViewById(R.id.buttonRestoreAccount);
recoverButton.setOnClickListener(e -> viewModel.recoverClicked());
return v;
}
@@ -75,6 +79,8 @@ public class AuthorNameFragment extends SetupFragment {
boolean enabled = authorNameLength > 0 && !error;
authorNameInput.setOnEditorActionListener(enabled ? this : null);
nextButton.setEnabled(enabled);
recoverButton.setEnabled(!enabled);
// recoverButton.setVisibility(enabled ? View.INVISIBLE : View.VISIBLE);
}
@Override

View File

@@ -1,60 +0,0 @@
package org.briarproject.briar.android.account;
import android.content.Intent;
import android.os.Bundle;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.socialbackup.recover.OwnerReturnShardActivity;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
public class NewOrRecoverActivity extends BaseActivity implements
BaseFragment.BaseFragmentListener, SetupNewAccountChosenListener,
RecoverAccountListener {
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
// fade-in after splash screen instead of default animation
// TODO the fade in is not working
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
setContentView(R.layout.activity_fragment_container);
NewOrRecoverFragment fragment = NewOrRecoverFragment.newInstance();
showInitialFragment(fragment);
}
@Override
public void setupNewAccountChosen() {
finish();
Intent i = new Intent(this, SetupActivity.class);
i.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP |
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_TASK_ON_HOME);
startActivity(i);
}
@Override
public void recoverAccountChosen() {
finish();
Intent i = new Intent(this, OwnerReturnShardActivity.class);
i.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP |
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_TASK_ON_HOME);
startActivity(i);
}
@Override
@Deprecated
public void runOnDbThread(Runnable runnable) {
throw new RuntimeException("Don't use this deprecated method here.");
}
}

View File

@@ -1,70 +0,0 @@
package org.briarproject.briar.android.account;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class NewOrRecoverFragment extends BaseFragment {
public static final String TAG = NewOrRecoverFragment.class.getName();
protected SetupNewAccountChosenListener setupNewAccountListener;
protected RecoverAccountListener recoverAccountListener;
public static NewOrRecoverFragment newInstance() {
Bundle bundle = new Bundle();
NewOrRecoverFragment fragment = new NewOrRecoverFragment();
fragment.setArguments(bundle);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requireActivity().setTitle(R.string.setup_title);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable
ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_new_or_recover,
container, false);
Button newAccountButton = view.findViewById(R.id.buttonSetupNewAccount);
newAccountButton.setOnClickListener(e -> {
setupNewAccountListener.setupNewAccountChosen();
});
Button recoverAccountButton = view.findViewById(R.id.buttonRestoreAccount);
recoverAccountButton.setOnClickListener(e -> {
recoverAccountListener.recoverAccountChosen();
});
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
setupNewAccountListener = (SetupNewAccountChosenListener) context;
recoverAccountListener = (RecoverAccountListener) context;
}
@Override
public String getUniqueTag() {
return TAG;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
}

View File

@@ -10,6 +10,7 @@ import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import org.briarproject.briar.android.socialbackup.recover.OwnerReturnShardActivity;
import javax.annotation.Nullable;
import javax.inject.Inject;
@@ -25,6 +26,7 @@ import static org.briarproject.briar.android.account.SetupViewModel.State.AUTHOR
import static org.briarproject.briar.android.account.SetupViewModel.State.CREATED;
import static org.briarproject.briar.android.account.SetupViewModel.State.DOZE;
import static org.briarproject.briar.android.account.SetupViewModel.State.FAILED;
import static org.briarproject.briar.android.account.SetupViewModel.State.RECOVER;
import static org.briarproject.briar.android.account.SetupViewModel.State.SET_PASSWORD;
@MethodsNotNullByDefault
@@ -60,6 +62,8 @@ public class SetupActivity extends BaseActivity
showPasswordFragment();
} else if (state == DOZE) {
showDozeFragment();
} else if (state == RECOVER) {
recover();
} else if (state == CREATED || state == FAILED) {
// TODO: Show an error if failed
showApp();
@@ -84,6 +88,13 @@ public class SetupActivity extends BaseActivity
overridePendingTransition(R.anim.screen_new_in, R.anim.screen_old_out);
}
void recover () {
// finish();
Intent i = new Intent(this, OwnerReturnShardActivity.class);
i.addFlags(FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
@Override
@Deprecated
public void runOnDbThread(Runnable runnable) {

View File

@@ -25,13 +25,14 @@ import static org.briarproject.briar.android.account.SetupViewModel.State.AUTHOR
import static org.briarproject.briar.android.account.SetupViewModel.State.CREATED;
import static org.briarproject.briar.android.account.SetupViewModel.State.DOZE;
import static org.briarproject.briar.android.account.SetupViewModel.State.FAILED;
import static org.briarproject.briar.android.account.SetupViewModel.State.RECOVER;
import static org.briarproject.briar.android.account.SetupViewModel.State.SET_PASSWORD;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public
class SetupViewModel extends AndroidViewModel {
enum State {AUTHOR_NAME, SET_PASSWORD, DOZE, CREATED, FAILED}
enum State {AUTHOR_NAME, SET_PASSWORD, DOZE, CREATED, FAILED, RECOVER}
private static final Logger LOG =
getLogger(SetupActivity.class.getName());
@@ -117,4 +118,9 @@ class SetupViewModel extends AndroidViewModel {
}
});
}
public void recoverClicked() {
LOG.info("RECOVER CLICKED ***");
state.postEvent(RECOVER);
}
}

View File

@@ -7,8 +7,6 @@ import org.briarproject.briar.android.AndroidComponent;
import org.briarproject.briar.android.StartupFailureActivity;
import org.briarproject.briar.android.account.AuthorNameFragment;
import org.briarproject.briar.android.account.DozeFragment;
import org.briarproject.briar.android.account.NewOrRecoverActivity;
import org.briarproject.briar.android.account.NewOrRecoverFragment;
import org.briarproject.briar.android.account.SetPasswordFragment;
import org.briarproject.briar.android.account.SetupActivity;
import org.briarproject.briar.android.account.UnlockActivity;
@@ -65,6 +63,15 @@ import org.briarproject.briar.android.privategroup.memberlist.GroupMemberModule;
import org.briarproject.briar.android.privategroup.reveal.GroupRevealModule;
import org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity;
import org.briarproject.briar.android.privategroup.reveal.RevealContactsFragment;
import org.briarproject.briar.android.remotewipe.RemoteWipeActivatedActivity;
import org.briarproject.briar.android.remotewipe.RemoteWipeDisplayFragment;
import org.briarproject.briar.android.remotewipe.RemoteWipeSetupActivity;
import org.briarproject.briar.android.remotewipe.RemoteWipeSetupExplainerFragment;
import org.briarproject.briar.android.remotewipe.WiperSelectorFragment;
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeActivity;
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeExplainerFragment;
import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeActivity;
import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeSuccessFragment;
import org.briarproject.briar.android.reporting.CrashFragment;
import org.briarproject.briar.android.reporting.CrashReportActivity;
import org.briarproject.briar.android.reporting.ReportFormFragment;
@@ -80,20 +87,19 @@ import org.briarproject.briar.android.sharing.ShareBlogFragment;
import org.briarproject.briar.android.sharing.ShareForumActivity;
import org.briarproject.briar.android.sharing.ShareForumFragment;
import org.briarproject.briar.android.sharing.SharingModule;
import org.briarproject.briar.android.socialbackup.SetupExplainerFragment;
import org.briarproject.briar.android.socialbackup.recover.CustodianRecoveryModeExplainerFragment;
import org.briarproject.briar.android.socialbackup.CustodianSelectorFragment;
import org.briarproject.briar.android.socialbackup.DistributedBackupActivity;
import org.briarproject.briar.android.socialbackup.SocialBackupSetupActivity;
import org.briarproject.briar.android.socialbackup.ExistingBackupFragment;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardActivity;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardErrorFragment;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardFragment;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardSuccessFragment;
import org.briarproject.briar.android.socialbackup.recover.OwnerRecoveryModeErrorFragment;
import org.briarproject.briar.android.socialbackup.recover.OwnerRecoveryModeExplainerFragment;
import org.briarproject.briar.android.socialbackup.recover.OwnerRecoveryModeMainFragment;
import org.briarproject.briar.android.socialbackup.recover.OwnerReturnShardActivity;
import org.briarproject.briar.android.socialbackup.recover.OwnerReturnShardFragment;
import org.briarproject.briar.android.socialbackup.ShardsSentFragment;
import org.briarproject.briar.android.socialbackup.ThresholdSelectorFragment;
import org.briarproject.briar.android.socialbackup.creation.CreateBackupModule;
import org.briarproject.briar.android.socialbackup.recover.OwnerReturnShardSuccessFragment;
@@ -102,7 +108,6 @@ import org.briarproject.briar.android.socialbackup.recover.RestoreAccountDozeFra
import org.briarproject.briar.android.socialbackup.recover.RestoreAccountSetPasswordFragment;
import org.briarproject.briar.android.splash.SplashScreenActivity;
import org.briarproject.briar.android.test.TestDataActivity;
import org.briarproject.briar.api.socialbackup.recovery.RestoreAccount;
import dagger.Component;
@@ -205,8 +210,6 @@ public interface ActivityComponent {
void inject(CrashReportActivity crashReportActivity);
void inject(NewOrRecoverActivity newOrRecoverActivity);
void inject(CustodianReturnShardActivity custodianReturnShardActivity);
void inject(OwnerReturnShardActivity ownerReturnShardActivity);
@@ -215,6 +218,14 @@ public interface ActivityComponent {
void inject(RestoreAccountActivity restoreAccountActivity);
void inject(RemoteWipeSetupActivity remoteWipeSetupActivity);
void inject(ActivateRemoteWipeActivity activateRemoteWipeActivity);
void inject(RemoteWipeActivatedActivity remoteWipeActivatedActivity);
void inject(RevokeRemoteWipeActivity revokeRemoteWipeActivity);
// Fragments
void inject(AuthorNameFragment fragment);
@@ -275,28 +286,22 @@ public interface ActivityComponent {
void inject(ThresholdSelectorFragment thresholdSelectorFragment);
void inject(DistributedBackupActivity distributedBackupActivity);
void inject(SocialBackupSetupActivity distributedBackupActivity);
void inject(DatabaseComponent databaseComponent);
void inject(CustodianSelectorFragment custodianSelectorFragment);
void inject(ShardsSentFragment shardsSentFragment);
void inject(OwnerRecoveryModeExplainerFragment ownerRecoveryModeExplainerFragment);
void inject(ExistingBackupFragment existingBackupFragment);
void inject(NewOrRecoverFragment newOrRecoverFragment);
void inject(CustodianRecoveryModeExplainerFragment custodianRecoveryModeExplainerFragment);
void inject(CustodianReturnShardFragment custodianReturnShardFragment);
void inject(OwnerReturnShardFragment ownerReturnShardFragment);
void inject(CustodianReturnShardSuccessFragment custodianReturnShardSuccessFragment);
void inject(RestoreAccountSetPasswordFragment restoreAccountSetPasswordFragment);
void inject(RestoreAccountDozeFragment restoreAccountDozeFragment);
@@ -306,4 +311,16 @@ public interface ActivityComponent {
void inject(OwnerRecoveryModeErrorFragment ownerRecoveryModeErrorFragment);
void inject(CustodianReturnShardErrorFragment custodianReturnShardErrorFragment);
void inject(WiperSelectorFragment wiperSelectorFragment);
void inject(RemoteWipeDisplayFragment remoteWipeDisplayFragment);
void inject(ActivateRemoteWipeExplainerFragment activateRemoteWipeExplainerFragment);
void inject(RevokeRemoteWipeSuccessFragment revokeRemoteWipeSuccessFragment);
void inject(RemoteWipeSetupExplainerFragment remoteWipeSetupExplainerFragment);
void inject(SetupExplainerFragment setupExplainerFragment);
}

View File

@@ -52,6 +52,8 @@ import org.briarproject.briar.android.conversation.ConversationVisitor.TextCache
import org.briarproject.briar.android.forum.ForumActivity;
import org.briarproject.briar.android.introduction.IntroductionActivity;
import org.briarproject.briar.android.privategroup.conversation.GroupActivity;
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeActivity;
import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeActivity;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardActivity;
import org.briarproject.briar.android.util.BriarSnackbarBuilder;
import org.briarproject.briar.android.view.BriarRecyclerView;
@@ -371,6 +373,20 @@ public class ConversationActivity extends BriarActivity
observeOnce(viewModel.getContactItem(), this, contact ->
menu.findItem(R.id.action_set_alias).setEnabled(true));
// enable remote wipe action if available
observeOnce(viewModel.amRemoteWiper(), this, amWiper -> {
if (amWiper != null && amWiper) {
menu.findItem(R.id.action_remote_wipe).setEnabled(true);
}
});
// enable revoke remote wipe action if available
observeOnce(viewModel.isRemoteWiper(), this, isWiper -> {
if (isWiper != null && isWiper) {
menu.findItem(R.id.action_revoke_remote_wipe).setEnabled(true);
}
});
// enable help recover account action if available
observeOnce(viewModel.amCustodian(), this, enable -> {
if (enable) {
@@ -410,6 +426,18 @@ public class ConversationActivity extends BriarActivity
i.putExtra(CONTACT_ID, contactId.getInt());
startActivity(i);
return true;
case R.id.action_remote_wipe:
if (contactId == null) return false;
Intent r = new Intent(this, ActivateRemoteWipeActivity.class);
r.putExtra(CONTACT_ID, contactId.getInt());
startActivity(r);
return true;
case R.id.action_revoke_remote_wipe:
if (contactId == null) return false;
Intent s = new Intent(this, RevokeRemoteWipeActivity.class);
s.putExtra(CONTACT_ID, contactId.getInt());
startActivity(s);
return true;
default:
return super.onOptionsItemSelected(item);
}

View File

@@ -3,6 +3,7 @@ package org.briarproject.briar.android.conversation;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.api.conversation.ConversationRequest;
import org.briarproject.briar.api.conversation.ConversationResponse;
import org.briarproject.briar.api.remotewipe.RemoteWipeMessageHeader;
import org.briarproject.briar.api.socialbackup.ShardMessageHeader;
import javax.annotation.Nullable;
@@ -38,6 +39,13 @@ class ConversationNoticeItem extends ConversationItem {
this.msgText = null;
}
ConversationNoticeItem(@LayoutRes int layoutRes, String text,
RemoteWipeMessageHeader r) {
super(layoutRes, r);
this.text = text;
this.msgText = null;
}
@Nullable
String getMsgText() {
return msgText;

View File

@@ -40,7 +40,7 @@ import org.briarproject.briar.api.messaging.PrivateMessage;
import org.briarproject.briar.api.messaging.PrivateMessageFactory;
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.messaging.event.AttachmentReceivedEvent;
import org.briarproject.briar.api.socialbackup.SocialBackup;
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
import org.briarproject.briar.api.socialbackup.SocialBackupManager;
import java.util.Collection;
@@ -86,6 +86,7 @@ public class ConversationViewModel extends DbViewModel
private final PrivateMessageFactory privateMessageFactory;
private final AttachmentRetriever attachmentRetriever;
private final AttachmentCreator attachmentCreator;
private final RemoteWipeManager remoteWipeManager;
private final SocialBackupManager socialBackupManager;
@Nullable
@@ -107,6 +108,8 @@ public class ConversationViewModel extends DbViewModel
new MutableLiveData<>();
private final MutableLiveEvent<PrivateMessageHeader> addedHeader =
new MutableLiveEvent<>();
private final MutableLiveData<Boolean> amRemoteWiper = new MutableLiveData<>();
private final MutableLiveData<Boolean> isRemoteWiper = new MutableLiveData<>();
private final MutableLiveData<Boolean> amCustodian = new MutableLiveData<>();
@Inject
@@ -122,6 +125,7 @@ public class ConversationViewModel extends DbViewModel
SettingsManager settingsManager,
PrivateMessageFactory privateMessageFactory,
AttachmentRetriever attachmentRetriever,
RemoteWipeManager remoteWipeManager,
AttachmentCreator attachmentCreator,
SocialBackupManager socialBackupManager) {
super(application, dbExecutor, lifecycleManager, db, androidExecutor);
@@ -134,6 +138,7 @@ public class ConversationViewModel extends DbViewModel
this.privateMessageFactory = privateMessageFactory;
this.attachmentRetriever = attachmentRetriever;
this.attachmentCreator = attachmentCreator;
this.remoteWipeManager = remoteWipeManager;
this.socialBackupManager = socialBackupManager;
messagingGroupId = map(contactItem, c ->
messagingManager.getContactGroup(c.getContact()).getId());
@@ -303,11 +308,18 @@ public class ConversationViewModel extends DbViewModel
showIntroductionOnboarding.postEvent(true);
}
// Check if we are a remote wiper for this contact
boolean amWiper = db.transactionWithResult(true,
txn -> remoteWipeManager.amWiper(txn, c));
amRemoteWiper.postValue(amWiper);
boolean isWiper = db.transactionWithResult(true,
txn -> remoteWipeManager.isWiper(txn, c));
isRemoteWiper.postValue(isWiper);
// Check if we are a social backup custodian for this contact
boolean amCustodianBool = db.transactionWithResult(true,
txn -> socialBackupManager.amCustodian(txn, c));
amCustodian.postValue(amCustodianBool);
}
@DatabaseExecutor
@@ -393,6 +405,14 @@ public class ConversationViewModel extends DbViewModel
return addedHeader;
}
LiveData<Boolean> amRemoteWiper() {
return amRemoteWiper;
}
LiveData<Boolean> isRemoteWiper() {
return isRemoteWiper;
}
LiveData<Boolean> amCustodian() {
return amCustodian;
}

View File

@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.sync.MessageId;
import org.briarproject.briar.R;
import org.briarproject.briar.android.attachment.AttachmentItem;
import org.briarproject.briar.android.util.UiUtils;
import org.briarproject.briar.api.blog.BlogInvitationRequest;
import org.briarproject.briar.api.blog.BlogInvitationResponse;
import org.briarproject.briar.api.conversation.ConversationMessageVisitor;
@@ -16,6 +17,7 @@ import org.briarproject.briar.api.introduction.IntroductionResponse;
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
import org.briarproject.briar.api.remotewipe.RemoteWipeMessageHeader;
import org.briarproject.briar.api.socialbackup.ShardMessageHeader;
import java.util.List;
@@ -308,6 +310,55 @@ class ConversationVisitor implements
}
}
@Override
public ConversationItem visitRemoteWipeMessage(RemoteWipeMessageHeader r) {
switch (r.getMessageType()) {
case SETUP:
if (r.isLocal()) {
String text = ctx.getString(R.string.remote_wipe_setup_sent,
contactName.getValue());
return new ConversationNoticeItem(
R.layout.list_item_conversation_notice_out, text,
r);
} else {
String text =
ctx.getString(R.string.remote_wipe_setup_received,
contactName.getValue());
return new ConversationNoticeItem(
R.layout.list_item_conversation_notice_in, text, r);
}
case WIPE:
String text = ctx.getString(R.string.remote_wipe_wipe_sent,
contactName.getValue()) + " " + UiUtils
.formatDateAbsolute(ctx, r.getMessageExpiry());
return new ConversationNoticeItem(
R.layout.list_item_conversation_notice_out, text, r);
case CONFIRM:
System.out.println("Processing confirm message");
String confirmText =
ctx.getString(R.string.remote_wipe_confirm_received,
contactName.getValue());
return new ConversationNoticeItem(
R.layout.list_item_conversation_notice_in, confirmText, r);
default: // REVOKE
String revokeText;
if (r.isLocal()) {
revokeText = ctx.getString(R.string.remote_wipe_revoke_sent,
contactName.getValue());
return new ConversationNoticeItem(
R.layout.list_item_conversation_notice_out,
revokeText, r);
} else {
revokeText =
ctx.getString(R.string.remote_wipe_revoke_received,
contactName.getValue());
return new ConversationNoticeItem(
R.layout.list_item_conversation_notice_in,
revokeText, r);
}
}
}
interface TextCache {
@Nullable
String getText(MessageId m);

View File

@@ -7,7 +7,6 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.BriarService;
import org.briarproject.briar.android.account.NewOrRecoverActivity;
import org.briarproject.briar.android.account.SetupActivity;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
@@ -108,7 +107,7 @@ public class StartupActivity extends BaseActivity implements
private void onAccountDeleted() {
setResult(RESULT_CANCELED);
finish();
Intent i = new Intent(this, NewOrRecoverActivity.class);
Intent i = new Intent(this, SetupActivity.class);
i.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP |
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_TASK_ON_HOME);
startActivity(i);

View File

@@ -138,6 +138,7 @@ public class NavDrawerActivity extends BriarActivity implements
navDrawerViewModel.showExpiryWarning()
.observe(this, this::showExpiryWarning);
}
navDrawerViewModel.shouldAskForDozeWhitelisting().observe(this, ask -> {
if (ask) showDozeDialog(getString(R.string.setup_doze_intro));
});
@@ -158,7 +159,8 @@ public class NavDrawerActivity extends BriarActivity implements
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
navDrawerViewModel.checkTransportsOnboarding();
// navDrawerViewModel.checkTransportsOnboarding();
navDrawerViewModel.checkSocialBackupOnboarding();
}
};
drawerLayout.addDrawerListener(drawerToggle);
@@ -167,9 +169,12 @@ public class NavDrawerActivity extends BriarActivity implements
initializeTransports();
transportsView.setAdapter(transportsAdapter);
observeOnce(navDrawerViewModel.showTransportsOnboarding(), this, show ->
observeOnce(torIcon, this, imageView ->
showTransportsOnboarding(show, imageView)));
// observeOnce(navDrawerViewModel.showTransportsOnboarding(), this, show ->
// observeOnce(torIcon, this, imageView ->
// showTransportsOnboarding(show, imageView)));
observeOnce(navDrawerViewModel.showSocialBackupOnboarding(), this,
this::showSocialBackupOnboarding);
lockManager.isLockable().observe(this, this::setLockVisible);
@@ -468,6 +473,22 @@ public class NavDrawerActivity extends BriarActivity implements
}
}
private void showSocialBackupOnboarding(boolean show) {
if (show) {
new MaterialTapTargetPrompt.Builder(NavDrawerActivity.this,
R.style.OnboardingDialogTheme)
.setTarget(R.id.nav_btn_settings)
.setPrimaryText(R.string.social_backup_onboarding_title)
.setSecondaryText(R.string.social_backup_onboarding_long)
.setFocalRadius((float) 350)
.setFocalPadding((float) 100)
.setBackgroundColour(
ContextCompat.getColor(this, R.color.briar_primary))
.show();
navDrawerViewModel.socialBackupOnboardingShown();
}
}
private static class Transport {
private final TransportId id;

View File

@@ -39,6 +39,8 @@ public class NavDrawerViewModel extends DbViewModel {
private static final String EXPIRY_DATE_WARNING = "expiryDateWarning";
private static final String SHOW_TRANSPORTS_ONBOARDING =
"showTransportsOnboarding";
private static final String SHOW_SOCIAL_BACKUP_ONBOARDING =
"showSocialBackupOnboarding";
private final SettingsManager settingsManager;
@@ -48,6 +50,8 @@ public class NavDrawerViewModel extends DbViewModel {
new MutableLiveData<>();
private final MutableLiveData<Boolean> showTransportsOnboarding =
new MutableLiveData<>();
private final MutableLiveData<Boolean> showSocialBackupOnboarding =
new MutableLiveData<>();
@Inject
NavDrawerViewModel(Application app,
@@ -142,6 +146,11 @@ public class NavDrawerViewModel extends DbViewModel {
return showTransportsOnboarding;
}
@UiThread
LiveData<Boolean> showSocialBackupOnboarding() {
return showSocialBackupOnboarding;
}
@UiThread
void checkTransportsOnboarding() {
if (showTransportsOnboarding.getValue() != null) return;
@@ -171,4 +180,35 @@ public class NavDrawerViewModel extends DbViewModel {
}
});
}
@UiThread
void checkSocialBackupOnboarding() {
if (showSocialBackupOnboarding.getValue() != null) return;
runOnDbThread(() -> {
try {
Settings settings =
settingsManager.getSettings(SETTINGS_NAMESPACE);
boolean show =
settings.getBoolean(SHOW_SOCIAL_BACKUP_ONBOARDING,
true);
showSocialBackupOnboarding.postValue(show);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
}
@UiThread
void socialBackupOnboardingShown() {
showSocialBackupOnboarding.setValue(false);
runOnDbThread(() -> {
try {
Settings settings = new Settings();
settings.putBoolean(SHOW_SOCIAL_BACKUP_ONBOARDING, false);
settingsManager.mergeSettings(settings, SETTINGS_NAMESPACE);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
});
}
}

View File

@@ -0,0 +1,41 @@
package org.briarproject.briar.android.remotewipe;
import android.os.Bundle;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import javax.annotation.Nullable;
import javax.inject.Inject;
import androidx.lifecycle.ViewModelProvider;
public class RemoteWipeActivatedActivity extends BriarActivity {
@Inject
ViewModelProvider.Factory viewModelFactory;
RemoteWipeActivatedViewModel viewModel;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(this, viewModelFactory)
.get(RemoteWipeActivatedViewModel.class);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel.getConfirmSent()
.observeEvent(this, confirmed -> {
if (confirmed) {
signOut(true, true);
}
});
viewModel.sendConfirmMessages();
}
}

View File

@@ -0,0 +1,67 @@
package org.briarproject.briar.android.remotewipe;
import android.app.Application;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.event.EventListener;
import org.briarproject.bramble.api.sync.event.MessagesSentEvent;
import org.briarproject.briar.android.viewmodel.LiveEvent;
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
public class RemoteWipeActivatedViewModel extends AndroidViewModel implements
EventListener {
private final RemoteWipeManager remoteWipeManager;
private final DatabaseComponent db;
private final MutableLiveEvent<Boolean> confirmSent =
new MutableLiveEvent<>();
private int numberOfConfirmMessages;
private int messagesSent = 0;
@Inject
RemoteWipeActivatedViewModel(
@NonNull Application application,
RemoteWipeManager remoteWipeManager,
DatabaseComponent db, EventBus eventBus) {
super(application);
this.remoteWipeManager = remoteWipeManager;
this.db = db;
eventBus.addListener(this);
}
public void sendConfirmMessages() {
try {
numberOfConfirmMessages = db.transactionWithResult(false,
remoteWipeManager::sendConfirmMessages);
} catch (DbException | FormatException e) {
// If there is a problem sending the messages, just wipe
confirmSent.postEvent(true);
}
}
public LiveEvent<Boolean> getConfirmSent() {
return confirmSent;
}
@Override
public void eventOccurred(Event e) {
// As soon as we know the confirm messages are sent, we can wipe
if (e instanceof MessagesSentEvent) {
messagesSent++;
if (messagesSent >= numberOfConfirmMessages) {
confirmSent.postEvent(true);
}
}
}
}

View File

@@ -0,0 +1,115 @@
package org.briarproject.briar.android.remotewipe;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.contact.ContactListAdapter;
import org.briarproject.briar.android.contact.ContactListItem;
import org.briarproject.briar.android.contact.OnContactClickListener;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.view.BriarRecyclerView;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
public class RemoteWipeDisplayFragment extends BaseFragment
implements OnContactClickListener<ContactListItem> {
public static final String TAG = RemoteWipeDisplayFragment.class.getName();
private final ContactListAdapter adapter = new ContactListAdapter(this);
private BriarRecyclerView list;
@Inject
ViewModelProvider.Factory viewModelFactory;
private RemoteWipeSetupViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(RemoteWipeSetupViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
// change toolbar text (relevant when navigating back to this fragment)
requireActivity().setTitle(R.string.assigned_wipers);
View contentView = inflater.inflate(R.layout.fragment_remote_wipe_display, container, false);
viewModel.getWiperContactIds();
list = contentView.findViewById(R.id.wiperList);
list.setLayoutManager(new LinearLayoutManager(getActivity()));
list.setAdapter(adapter);
list.setEmptyText(R.string.no_contacts);
viewModel.getContactListItems().observe(getViewLifecycleOwner(),
result -> result.onError(this::handleException)
.onSuccess(adapter::submitList)
);
Button changeWipersButton = contentView.findViewById(R.id.button_change);
changeWipersButton.setOnClickListener(e -> viewModel.onModifyWipers());
Button disableRemoteWipeButton = contentView.findViewById(R.id.button_cancel);
disableRemoteWipeButton.setOnClickListener(e -> viewModel.onDisableRemoteWipe());
viewModel.getState().observe(getViewLifecycleOwner(), this::onStateChanged);
return contentView;
}
@Override
public String getUniqueTag() {
return TAG;
}
@Override
public void onItemClick(View view, ContactListItem item) {
}
@Override
public void onStart() {
super.onStart();
list.startPeriodicUpdate();
}
@Override
public void onStop() {
super.onStop();
list.stopPeriodicUpdate();
}
private void onStateChanged(RemoteWipeSetupState state) {
if (state.equals(RemoteWipeSetupState.DISABLED)) {
showDisabledDialog();
}
}
private void showDisabledDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
R.style.BriarDialogTheme);
builder.setTitle(R.string.remote_wipe_disable_success);
builder.setMessage(R.string.remote_wipe_disable_success_explain);
builder.setPositiveButton(R.string.ok,
(dialog, which) -> viewModel.onSuccessDismissed());
builder.setIcon(R.drawable.ic_baseline_done_outline_24);
AlertDialog dialog = builder.create();
dialog.show();
}
}

View File

@@ -0,0 +1,38 @@
package org.briarproject.briar.android.remotewipe;
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeViewModel;
import org.briarproject.briar.android.remotewipe.revoke.RevokeRemoteWipeViewModel;
import org.briarproject.briar.android.viewmodel.ViewModelKey;
import androidx.lifecycle.ViewModel;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
@Module
public abstract class RemoteWipeModule {
@Binds
@IntoMap
@ViewModelKey(RemoteWipeSetupViewModel.class)
abstract ViewModel bindRemoteWipeSetupViewModel(
RemoteWipeSetupViewModel remoteWipeSetupViewModel);
@Binds
@IntoMap
@ViewModelKey(ActivateRemoteWipeViewModel.class)
abstract ViewModel bindActivateRemoteWipeViewModel(
ActivateRemoteWipeViewModel activateRemoteWipeViewModel);
@Binds
@IntoMap
@ViewModelKey(RevokeRemoteWipeViewModel.class)
abstract ViewModel bindRevokeRemoteWipeViewModel(
RevokeRemoteWipeViewModel RevokeRemoteWipeViewModel);
@Binds
@IntoMap
@ViewModelKey(RemoteWipeActivatedViewModel.class)
abstract ViewModel bindRemoteWipeActivatedViewModel(
RemoteWipeActivatedViewModel remoteWipeActivatedViewModel);
}

View File

@@ -0,0 +1,76 @@
package org.briarproject.briar.android.remotewipe;
import android.os.Bundle;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.contactselection.ContactSelectorListener;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.socialbackup.ThresholdSelectorFragment;
import java.util.Collection;
import javax.inject.Inject;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
public class RemoteWipeSetupActivity extends BriarActivity implements
BaseFragment.BaseFragmentListener, ContactSelectorListener {
@Inject
ViewModelProvider.Factory viewModelFactory;
RemoteWipeSetupViewModel viewModel;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(this, viewModelFactory)
.get(RemoteWipeSetupViewModel.class);
viewModel.getState().observe(this, this::onStateChanged);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_distributed_backup);
if (viewModel.remoteWipeIsSetup()) {
showInitialFragment(new RemoteWipeDisplayFragment());
} else {
showInitialFragment(new RemoteWipeSetupExplainerFragment());
}
}
@Override
public void contactsSelected(Collection<ContactId> contacts) {
Toast.makeText(this,
String.format("Selected %d contacts", contacts.size()),
Toast.LENGTH_SHORT).show();
try {
viewModel.setupRemoteWipe(contacts);
} catch (Exception e) {
// Display error fragment
}
}
private void onStateChanged(RemoteWipeSetupState state) {
if (state.equals(RemoteWipeSetupState.FAILED)) {
Toast.makeText(this,
R.string.remote_wipe_setup_failed,
Toast.LENGTH_LONG).show();
finish();
} else if (state.equals(RemoteWipeSetupState.SELECTING)) {
showNextFragment(WiperSelectorFragment.newInstance());
} else if (state.equals(RemoteWipeSetupState.FINISHED)) {
finish();
} else if (state.equals(RemoteWipeSetupState.MODIFY)) {
showNextFragment(WiperSelectorFragment.newInstance());
}
}
}

View File

@@ -0,0 +1,57 @@
package org.briarproject.briar.android.remotewipe;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
public class RemoteWipeSetupExplainerFragment extends
BaseFragment {
public static final String TAG =
RemoteWipeSetupExplainerFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private RemoteWipeSetupViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(RemoteWipeSetupViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_remote_wipe_setup_explainer,
container, false);
Button confirmButton = view.findViewById(R.id.button_confirm);
confirmButton.setOnClickListener(e -> viewModel.onExplainerConfirmed());
Button cancelButton = view.findViewById(R.id.button_cancel);
cancelButton.setOnClickListener(e -> viewModel.onExplainerCancelled());
return view;
}
@Override
public String getUniqueTag() {
return TAG;
}
}

View File

@@ -0,0 +1,10 @@
package org.briarproject.briar.android.remotewipe;
public enum RemoteWipeSetupState {
FAILED,
SUCCESS,
FINISHED,
SELECTING,
MODIFY,
DISABLED
}

View File

@@ -0,0 +1,140 @@
package org.briarproject.briar.android.remotewipe;
import android.app.Application;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.connection.ConnectionRegistry;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.android.contact.ContactsViewModel;
import org.briarproject.briar.api.conversation.ConversationManager;
import org.briarproject.briar.api.identity.AuthorManager;
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
import java.text.Normalizer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import androidx.lifecycle.MutableLiveData;
@NotNullByDefault
public class RemoteWipeSetupViewModel extends ContactsViewModel {
private final RemoteWipeManager remoteWipeManager;
private final DatabaseComponent db;
private List<ContactId> wiperContactIds;
private final MutableLiveData<RemoteWipeSetupState> state =
new MutableLiveData<>();
private final ContactManager contactManager;
private final AuthorManager authorManager;
@Inject
RemoteWipeSetupViewModel(
@NonNull Application application,
RemoteWipeManager remoteWipeManager,
@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager,
AuthorManager authorManager,
ConversationManager conversationManager,
ConnectionRegistry connectionRegistry,
EventBus eventBus,
AndroidExecutor androidExecutor,
ContactManager contactManager,
DatabaseComponent db) {
super(application, dbExecutor, lifecycleManager, db, androidExecutor,
contactManager, authorManager, conversationManager,
connectionRegistry, eventBus);
this.remoteWipeManager = remoteWipeManager;
this.contactManager = contactManager;
this.authorManager = authorManager;
this.db = db;
getWiperContactIds();
loadContacts();
}
public boolean remoteWipeIsSetup() {
try {
return db.transactionWithResult(true,
txn -> {
boolean isSetup = remoteWipeManager.remoteWipeIsSetup(txn);
if (isSetup) wiperContactIds = remoteWipeManager.getWiperContactIds(txn);
return isSetup;
});
} catch (DbException e) {
return false;
}
}
public List<ContactId> getWiperContactIds() {
try {
wiperContactIds = db.transactionWithResult(true,
remoteWipeManager::getWiperContactIds);
} catch (DbException ignored) {
return new ArrayList<ContactId>();
}
return wiperContactIds;
}
@UiThread
public void onExplainerConfirmed() {
state.postValue(RemoteWipeSetupState.SELECTING);
}
@UiThread
public void onExplainerCancelled() {
state.postValue(RemoteWipeSetupState.FINISHED);
}
@UiThread
public void onSuccessDismissed() {
state.postValue(RemoteWipeSetupState.FINISHED);
}
@UiThread
public void onModifyWipers() {
state.postValue(RemoteWipeSetupState.MODIFY);
}
@UiThread
public void onDisableRemoteWipe() {
try {
db.transaction(false, remoteWipeManager::revokeAll);
state.postValue(RemoteWipeSetupState.DISABLED);
} catch (DbException | FormatException e) {
e.printStackTrace();
state.postValue(RemoteWipeSetupState.FINISHED);
}
}
public void setupRemoteWipe(Collection<ContactId> wipers)
throws DbException, FormatException {
db.transaction(false, txn -> {
remoteWipeManager.setup(txn, (List<ContactId>) wipers);
state.postValue(RemoteWipeSetupState.SUCCESS);
});
}
@Override
protected boolean displayContact(ContactId contactId) {
// Check if contact is a wiper
return wiperContactIds.contains(contactId);
}
public MutableLiveData<RemoteWipeSetupState> getState() {
return state;
}
}

View File

@@ -0,0 +1,118 @@
package org.briarproject.briar.android.remotewipe;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactId;
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.ActivityComponent;
import org.briarproject.briar.android.contactselection.BaseContactSelectorAdapter;
import org.briarproject.briar.android.contactselection.ContactSelectorController;
import org.briarproject.briar.android.contactselection.ContactSelectorFragment;
import org.briarproject.briar.android.contactselection.SelectableContactItem;
import org.briarproject.briar.android.socialbackup.creation.CreateBackupController;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class WiperSelectorFragment extends ContactSelectorFragment {
public static final String TAG = WiperSelectorFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private RemoteWipeSetupViewModel viewModel;
@Inject
CreateBackupController controller;
public static WiperSelectorFragment newInstance() {
Bundle args = new Bundle();
WiperSelectorFragment
fragment = new WiperSelectorFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(RemoteWipeSetupViewModel.class);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
selectedContacts.addAll(viewModel.getWiperContactIds());
requireActivity().setTitle(R.string.title_select_wipers);
viewModel.getState().observe(this, this::onStateChanged);
}
private void onStateChanged(RemoteWipeSetupState state) {
if (state.equals(RemoteWipeSetupState.SUCCESS)) {
showSuccessDialog();
}
}
@Override
protected ContactSelectorController<SelectableContactItem> getController() {
return controller;
}
@Override
public String getUniqueTag() {
return TAG;
}
@Override
protected void onSelectionChanged() {
super.onSelectionChanged();
if (menu == null) return;
MenuItem item = menu.findItem(R.id.action_contacts_selected);
if (item == null) return;
BaseContactSelectorAdapter a = adapter;
selectedContacts = a.getSelectedContactIds();
int n = selectedContacts.size();
int min = 2;
boolean enough = n >= min;
item.setVisible(enough);
if (n == 0) {
Toast.makeText(getContext(), String.format(getString(R.string.select_at_least_n_contacts), min),
Toast.LENGTH_SHORT).show();
} else if (n < min) {
Toast.makeText(getContext(), String.format(getString(R.string.select_at_least_n_more_contacts), min - n),
Toast.LENGTH_SHORT).show();
}
}
private void showSuccessDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
R.style.BriarDialogTheme);
builder.setTitle(R.string.remote_wipe_setup_success);
builder.setPositiveButton(R.string.ok,
(dialog, which) -> viewModel.onSuccessDismissed());
builder.setIcon(R.drawable.ic_baseline_done_outline_24);
AlertDialog dialog = builder.create();
dialog.show();
}
}

View File

@@ -0,0 +1,66 @@
package org.briarproject.briar.android.remotewipe.activate;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.fragment.BaseFragment;
import javax.inject.Inject;
import androidx.lifecycle.ViewModelProvider;
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
public class ActivateRemoteWipeActivity extends BriarActivity implements
BaseFragment.BaseFragmentListener {
@Inject
ViewModelProvider.Factory viewModelFactory;
ActivateRemoteWipeViewModel viewModel;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(this, viewModelFactory)
.get(ActivateRemoteWipeViewModel.class);
viewModel.getState().observe(this, this::onStateChanged);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_distributed_backup);
if (savedInstanceState == null) {
Intent intent = getIntent();
int id = intent.getIntExtra(CONTACT_ID, -1);
if (id == -1) throw new IllegalStateException("No ContactId");
ContactId contactId = new ContactId(id);
viewModel.setContactId(contactId);
showInitialFragment(new ActivateRemoteWipeExplainerFragment());
}
}
private void onStateChanged(ActivateRemoteWipeState state) {
switch(state) {
case FAILED:
Toast.makeText(this,
R.string.remote_wipe_activate_failure,
Toast.LENGTH_LONG).show();
break;
case SUCCESS:
// Handled by the popup dialog on the explainer
break;
default: // FINISHED or CANCELLED
finish();
break;
}
}
}

View File

@@ -0,0 +1,83 @@
package org.briarproject.briar.android.remotewipe.activate;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
public class ActivateRemoteWipeExplainerFragment extends BaseFragment {
public static final String TAG =
ActivateRemoteWipeExplainerFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private ActivateRemoteWipeViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(ActivateRemoteWipeViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_activate_remote_wipe_explainer,
container, false);
TextView titleText = view.findViewById(R.id.textView);
titleText.setText(String.format(getString(R.string.remote_wipe_activate_explain_short), viewModel.getContactName()));
TextView explainText = view.findViewById(R.id.textViewExplain);
explainText.setText(String.format(getString(R.string.remote_wipe_activate_explain_long), viewModel.getContactName()));
Button cancelButton = view.findViewById(R.id.button_cancel);
cancelButton.setOnClickListener(e -> viewModel.onCancelClicked());
Button confirmButton = view.findViewById(R.id.button_confirm);
confirmButton.setOnClickListener(e -> viewModel.onConfirmClicked());
viewModel.getState().observe(getViewLifecycleOwner(), this::onStateChanged);
return view;
}
private void onStateChanged(ActivateRemoteWipeState state) {
if (state == ActivateRemoteWipeState.SUCCESS) {
showSuccessDialog();
}
}
@Override
public String getUniqueTag() {
return TAG;
}
private void showSuccessDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
R.style.BriarDialogTheme);
builder.setTitle(R.string.remote_wipe_activate_success);
builder.setPositiveButton(R.string.ok,
(dialog, which) -> viewModel.onSuccessDismissed());
builder.setIcon(R.drawable.ic_baseline_done_outline_24);
AlertDialog dialog = builder.create();
dialog.show();
}
}

View File

@@ -0,0 +1,8 @@
package org.briarproject.briar.android.remotewipe.activate;
public enum ActivateRemoteWipeState {
FAILED,
SUCCESS,
FINISHED,
CANCELLED
}

View File

@@ -0,0 +1,89 @@
package org.briarproject.briar.android.remotewipe.activate;
import android.app.Application;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.briar.android.remotewipe.RemoteWipeSetupState;
import org.briarproject.briar.android.util.UiUtils;
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
import java.text.Normalizer;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData;
public class ActivateRemoteWipeViewModel extends AndroidViewModel {
private final RemoteWipeManager remoteWipeManager;
private final ContactManager contactManager;
private final DatabaseComponent db;
private final MutableLiveData<ActivateRemoteWipeState> state = new MutableLiveData<>();
private ContactId contactId;
private String contactName;
@Inject
public ActivateRemoteWipeViewModel(
@NonNull Application application,
RemoteWipeManager remoteWipeManager,
ContactManager contactManager,
DatabaseComponent db) {
super(application);
this.remoteWipeManager = remoteWipeManager;
this.contactManager = contactManager;
this.db = db;
}
private void activateWipe() {
try {
db.transaction(false, txn -> {
try {
remoteWipeManager.wipe(txn, db.getContact(txn, contactId));
} catch (DbException e) {
state.postValue(ActivateRemoteWipeState.FAILED);
} catch (FormatException e) {
state.postValue(ActivateRemoteWipeState.FAILED);
}
state.postValue(ActivateRemoteWipeState.SUCCESS);
});
} catch (DbException e) {
state.postValue(ActivateRemoteWipeState.FAILED);
}
}
public MutableLiveData<ActivateRemoteWipeState> getState() {
return state;
}
public void setContactId(ContactId c) {
contactId = c;
try {
contactName = UiUtils.getContactDisplayName(contactManager.getContact(c));
} catch (DbException e) {
e.printStackTrace();
}
}
public String getContactName() {
return contactName;
}
public void onCancelClicked() {
state.postValue(ActivateRemoteWipeState.CANCELLED);
}
public void onSuccessDismissed() {
state.postValue(ActivateRemoteWipeState.FINISHED);
}
public void onConfirmClicked() {
activateWipe();
}
}

View File

@@ -0,0 +1,67 @@
package org.briarproject.briar.android.remotewipe.revoke;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.fragment.BaseFragment;
import javax.inject.Inject;
import androidx.lifecycle.ViewModelProvider;
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
public class RevokeRemoteWipeActivity extends BriarActivity implements
BaseFragment.BaseFragmentListener {
@Inject
ViewModelProvider.Factory viewModelFactory;
RevokeRemoteWipeViewModel viewModel;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(this, viewModelFactory)
.get(RevokeRemoteWipeViewModel.class);
viewModel.getState().observe(this, this::onStateChanged);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_distributed_backup);
if (savedInstanceState == null) {
Intent intent = getIntent();
int id = intent.getIntExtra(CONTACT_ID, -1);
if (id == -1) throw new IllegalStateException("No ContactId");
ContactId contactId = new ContactId(id);
viewModel.revokeRemoteWipeStatus(contactId);
// showInitialFragment(new ActivateRemoteWipeExplainerFragment());
}
}
private void onStateChanged(RevokeRemoteWipeState state) {
switch(state) {
case FAILED:
// TODO change text
Toast.makeText(this,
R.string.remote_wipe_activate_failure,
Toast.LENGTH_LONG).show();
break;
case SUCCESS:
showNextFragment(new RevokeRemoteWipeSuccessFragment());
break;
default: // FINISHED or CANCELLED
finish();
break;
}
}
}

View File

@@ -0,0 +1,7 @@
package org.briarproject.briar.android.remotewipe.revoke;
public enum RevokeRemoteWipeState {
FAILED,
SUCCESS,
FINISHED
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.socialbackup.recover;
package org.briarproject.briar.android.remotewipe.revoke;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -6,8 +6,6 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
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.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
@@ -18,24 +16,21 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class CustodianReturnShardSuccessFragment extends
BaseFragment {
public class RevokeRemoteWipeSuccessFragment extends BaseFragment {
public static final String TAG =
CustodianReturnShardFragment.class.getName();
RevokeRemoteWipeSuccessFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private CustodianReturnShardViewModel viewModel;
private RevokeRemoteWipeViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(CustodianReturnShardViewModel.class);
.get(RevokeRemoteWipeViewModel.class);
}
@Nullable
@@ -43,12 +38,11 @@ public class CustodianReturnShardSuccessFragment extends
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recovery_custodian_done,
View view = inflater.inflate(R.layout.fragment_revoke_remote_wipe_success,
container, false);
Button button = view.findViewById(R.id.button);
button.setOnClickListener(e -> viewModel.onSuccessDismissed());
return view;
}

View File

@@ -0,0 +1,60 @@
package org.briarproject.briar.android.remotewipe.revoke;
import android.app.Application;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.briar.android.remotewipe.activate.ActivateRemoteWipeState;
import org.briarproject.briar.api.remotewipe.RemoteWipeManager;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData;
public class RevokeRemoteWipeViewModel extends AndroidViewModel {
private final RemoteWipeManager remoteWipeManager;
private final DatabaseComponent db;
private final MutableLiveData<RevokeRemoteWipeState> state = new MutableLiveData<>();
private ContactId contactId;
@Inject
public RevokeRemoteWipeViewModel(
@NonNull Application application,
RemoteWipeManager remoteWipeManager,
DatabaseComponent db) {
super(application);
this.remoteWipeManager = remoteWipeManager;
this.db = db;
}
public MutableLiveData<RevokeRemoteWipeState> getState() {
return state;
}
public void revokeRemoteWipeStatus(ContactId c) {
contactId = c;
try {
db.transaction(false, txn -> {
remoteWipeManager.revoke(txn, contactId);
});
} catch (DbException e) {
state.postValue(RevokeRemoteWipeState.FAILED);
} catch (FormatException e) {
state.postValue(RevokeRemoteWipeState.FAILED);
}
state.postValue(RevokeRemoteWipeState.SUCCESS);
}
public void onCancelClicked() {
// state.postValue(ActivateRemoteWipeState.CANCELLED);
}
public void onSuccessDismissed() {
state.postValue(RevokeRemoteWipeState.FINISHED);
}
}

View File

@@ -1,10 +1,12 @@
package org.briarproject.briar.android.settings;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
@@ -12,6 +14,7 @@ import org.briarproject.bramble.api.FeatureFlags;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.android.util.UiUtils;
import org.briarproject.briar.android.view.AuthorView;
@@ -19,11 +22,15 @@ import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.ViewModelProvider;
import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
import de.hdodenhof.circleimageview.CircleImageView;
import uk.co.samuelwall.materialtaptargetprompt.MaterialTapTargetPrompt;
import static android.widget.Toast.LENGTH_LONG;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_AVATAR_IMAGE;
import static org.briarproject.briar.android.util.UiUtils.resolveColorAttribute;
public class SettingsActivity extends BriarActivity {

View File

@@ -23,6 +23,7 @@ import java.util.Collection;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import static java.util.Objects.requireNonNull;
@@ -32,6 +33,18 @@ public class CustodianSelectorFragment extends ContactSelectorFragment {
public static final String TAG = CustodianSelectorFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private SocialBackupSetupViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(SocialBackupSetupViewModel.class);
}
@Inject
CreateBackupController controller;
@@ -44,11 +57,6 @@ public class CustodianSelectorFragment extends ContactSelectorFragment {
return fragment;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -78,15 +86,19 @@ public class CustodianSelectorFragment extends ContactSelectorFragment {
int n = selectedContacts.size();
int min = 2;
boolean enough = n >= min;
int max = 7;
boolean amountIsValid = (n >= min) && (n <= max);
item.setVisible(enough);
item.setVisible(amountIsValid);
if (n == 0) {
Toast.makeText(getContext(), String.format(getString(R.string.select_at_least_n_contacts), min),
Toast.LENGTH_SHORT).show();
} else if (n < min) {
Toast.makeText(getContext(), String.format(getString(R.string.select_at_least_n_more_contacts), min - n),
Toast.LENGTH_SHORT).show();
} else if (n > max) {
Toast.makeText(getContext(), String.format(getString(R.string.select_no_more_than_n_contacts), max),
Toast.LENGTH_SHORT).show();
}
}

View File

@@ -0,0 +1,27 @@
package org.briarproject.briar.android.socialbackup;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.briarproject.briar.R;
import org.briarproject.briar.android.contact.BaseContactListAdapter;
import org.briarproject.briar.android.contact.ContactItem;
import org.briarproject.briar.android.contact.ContactItemViewHolder;
public class CustodianStatusAdapter extends BaseContactListAdapter<ContactItem, ContactItemViewHolder<ContactItem>> {
CustodianStatusAdapter(Context context) {
super(context, ContactItem.class, null);
}
@Override
public ContactItemViewHolder<ContactItem> onCreateViewHolder(
ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(
R.layout.list_item_contact_small, viewGroup, false);
return new ContactItemViewHolder<>(v);
}
}

View File

@@ -1,112 +0,0 @@
package org.briarproject.briar.android.socialbackup;
import android.os.Bundle;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.contactselection.ContactSelectorListener;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.api.socialbackup.BackupMetadata;
import org.briarproject.briar.api.socialbackup.SocialBackupManager;
import java.util.Collection;
import java.util.List;
import javax.inject.Inject;
public class DistributedBackupActivity extends BriarActivity implements
BaseFragment.BaseFragmentListener, ContactSelectorListener,
ThresholdDefinedListener,
ShardsSentFragment.ShardsSentDismissedListener {
private Collection<ContactId> custodians;
@Inject
public SocialBackupManager socialBackupManager;
@Inject
public ContactManager contactManager;
@Inject
public DatabaseComponent db;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_distributed_backup);
try {
db.transaction(false, txn -> {
BackupMetadata backupMetadata =
socialBackupManager.getBackupMetadata(txn);
if (backupMetadata == null) throw new DbException();
ExistingBackupFragment fragment =
ExistingBackupFragment.newInstance(backupMetadata);
showInitialFragment(fragment);
});
} catch (DbException e) {
// Check the number of contacts in the contacts list > 1
try {
if (contactManager.getContacts().size() < 2) {
Toast.makeText(this,
R.string.social_backup_not_enough_contacts,
Toast.LENGTH_LONG).show();
finish();
}
} catch (DbException dbException) {
Toast.makeText(this,
R.string.reading_contacts_error,
Toast.LENGTH_LONG).show();
finish();
}
CustodianSelectorFragment fragment =
CustodianSelectorFragment.newInstance();
showInitialFragment(fragment);
}
}
@Override
public void contactsSelected(Collection<ContactId> contacts) {
Toast.makeText(this,
String.format("Selected %d contacts", contacts.size()),
Toast.LENGTH_SHORT).show();
custodians = contacts;
ThresholdSelectorFragment fragment =
ThresholdSelectorFragment.newInstance(contacts.size());
showNextFragment(fragment);
}
@Override
public void thresholdDefined(int threshold) {
try {
db.transaction(false, txn -> {
socialBackupManager
.createBackup(txn, (List<ContactId>) custodians,
threshold);
ShardsSentFragment fragment = new ShardsSentFragment();
showNextFragment(fragment);
});
} catch (DbException e) {
Toast.makeText(this,
"There was an error when creating the backup",
Toast.LENGTH_LONG).show();
finish();
}
}
@Override
public void shardsSentDismissed() {
finish();
}
}

View File

@@ -2,42 +2,48 @@ package org.briarproject.briar.android.socialbackup;
import android.content.Context;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import org.briarproject.bramble.api.identity.Author;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.contact.ContactListAdapter;
import org.briarproject.briar.android.contact.ContactListItem;
import org.briarproject.briar.android.contact.OnContactClickListener;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.api.socialbackup.BackupMetadata;
import org.briarproject.briar.android.view.BriarRecyclerView;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
public class ExistingBackupFragment extends BaseFragment {
public class ExistingBackupFragment extends BaseFragment implements
OnContactClickListener<ContactListItem> {
private static final String THRESHOLD = "threshold";
private static final String CUSTODIANS = "custodians";
public static final String TAG = ExistingBackupFragment.class.getName();
private final ContactListAdapter adapter = new ContactListAdapter(this);
private BriarRecyclerView list;
public static ExistingBackupFragment newInstance(
BackupMetadata backupMetadata) {
Bundle bundle = new Bundle();
List<Author> custodians = backupMetadata.getCustodians();
ArrayList custodianNames = new ArrayList();
for (Author custodian : custodians) {
custodianNames.add(custodian.getName());
}
bundle.putStringArrayList(CUSTODIANS, custodianNames);
bundle.putInt(THRESHOLD, backupMetadata.getThreshold());
ExistingBackupFragment fragment = new ExistingBackupFragment();
fragment.setArguments(bundle);
return fragment;
@Inject
ViewModelProvider.Factory viewModelFactory;
private SocialBackupSetupViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(SocialBackupSetupViewModel.class);
}
@Override
@@ -51,43 +57,69 @@ public class ExistingBackupFragment extends BaseFragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable
ViewGroup container, @Nullable Bundle savedInstanceState) {
// change toolbar text (relevant when navigating back to this fragment)
// requireActivity().setTitle(R.string.social_backup_trusted_contacts);
View view = inflater.inflate(R.layout.fragment_existing_backup,
container, false);
Bundle args = requireArguments();
ArrayList<String> custodianNames = args.getStringArrayList(CUSTODIANS);
viewModel.loadCustodianList();
list = view.findViewById(R.id.custodianList);
list.setLayoutManager(new LinearLayoutManager(getActivity()));
list.setAdapter(adapter);
list.setEmptyText(R.string.no_contacts);
StringBuilder custodianNamesString = new StringBuilder();
for (String custodianName : custodianNames) {
custodianNamesString
.append("")
.append(custodianName)
.append("\n");
}
viewModel.getContactListItems().observe(getViewLifecycleOwner(),
result -> result.onError(this::handleException)
.onSuccess(adapter::submitList)
);
TextView textViewThreshold = view.findViewById(R.id.textViewThreshold);
textViewThreshold.setText(getString(R.string.existing_backup_explain,
args.getInt(THRESHOLD)));
TextView textViewCustodians =
view.findViewById(R.id.textViewCustodians);
textViewCustodians.setText(custodianNamesString);
int threshold = viewModel.getThresholdFromExistingBackup();
int numberOfCustodians =
viewModel.getNumberOfCustodiansFromExistingBackup();
TextView mOfn = view.findViewById(R.id.textViewThreshold);
mOfn.setText(String.format(
getString(R.string.existing_backup_explain), threshold));
TextView thresholdRepresentation =
view.findViewById(R.id.textViewThresholdRepresentation);
thresholdRepresentation.setText(
buildThresholdRepresentationString(threshold,
numberOfCustodians));
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
// listener = (ShardsSentDismissedListener) context;
}
@Override
public String getUniqueTag() {
return TAG;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
public void onItemClick(View view, ContactListItem item) {
}
private SpannableStringBuilder buildThresholdRepresentationString(
int threshold, int numberOfCustodians) {
char[] charArray = new char[numberOfCustodians];
Arrays.fill(charArray, ' ');
SpannableStringBuilder string =
new SpannableStringBuilder(new String(charArray));
for (int i = 0; i < numberOfCustodians; i++) {
int drawable = i < threshold
? R.drawable.ic_custodian_required
: R.drawable.ic_custodian_optional;
string.setSpan(new ImageSpan(getContext(), drawable), i,
i + 1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
// If we have more than 6, split it on two lines
if (numberOfCustodians > 6) string.insert(4, "\n");
return string;
}
}

View File

@@ -0,0 +1,54 @@
package org.briarproject.briar.android.socialbackup;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
public class SetupExplainerFragment extends BaseFragment {
public static final String TAG =
SetupExplainerFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private SocialBackupSetupViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(SocialBackupSetupViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable
ViewGroup container, @Nullable Bundle savedInstanceState) {
View view =
inflater.inflate(R.layout.fragment_social_backup_setup_explainer,
container, false);
Button button = view.findViewById(R.id.button);
button.setOnClickListener(e -> viewModel.onExplainerDismissed());
return view;
}
@Override
public String getUniqueTag() {
return TAG;
}
}

View File

@@ -1,74 +0,0 @@
package org.briarproject.briar.android.socialbackup;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
public class ShardsSentFragment extends BaseFragment {
public static final String TAG = ShardsSentFragment.class.getName();
interface ShardsSentDismissedListener {
@UiThread
void shardsSentDismissed();
}
protected ShardsSentDismissedListener listener;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requireActivity().setTitle(R.string.title_distributed_backup);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_shards_sent,
container, false);
Button button = view.findViewById(R.id.button);
button.setOnClickListener(e -> {
listener.shardsSentDismissed();
});
return view;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (ShardsSentDismissedListener) context;
}
@Override
public String getUniqueTag() {
return TAG;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
public void onBackPressed() {
listener.shardsSentDismissed();
}
}

View File

@@ -0,0 +1,94 @@
package org.briarproject.briar.android.socialbackup;
import android.os.Bundle;
import android.widget.Toast;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.contactselection.ContactSelectorListener;
import org.briarproject.briar.android.fragment.BaseFragment;
import java.util.Collection;
import java.util.List;
import javax.inject.Inject;
import androidx.lifecycle.ViewModelProvider;
public class SocialBackupSetupActivity extends BriarActivity implements
BaseFragment.BaseFragmentListener, ContactSelectorListener {
private SocialBackupSetupViewModel viewModel;
@Inject
ViewModelProvider.Factory viewModelFactory;
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(this, viewModelFactory)
.get(SocialBackupSetupViewModel.class);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_distributed_backup);
if (viewModel.haveExistingBackup()) {
showInitialFragment(new ExistingBackupFragment());
} else {
try {
if (!viewModel.haveEnoughContacts()) {
Toast.makeText(this,
R.string.social_backup_not_enough_contacts,
Toast.LENGTH_LONG).show();
finish();
}
} catch (DbException dbException) {
Toast.makeText(this,
R.string.reading_contacts_error,
Toast.LENGTH_LONG).show();
finish();
}
showInitialFragment(new SetupExplainerFragment());
}
viewModel.getState()
.observe(this, this::onStateChanged);
}
private void onStateChanged(SocialBackupSetupViewModel.State state) {
switch (state) {
case SUCCESS:
finish();
break;
case FAILURE:
Toast.makeText(this,
"There was an error when creating the backup",
Toast.LENGTH_LONG).show();
finish();
break;
case CHOOSING_CUSTODIANS:
CustodianSelectorFragment fragment =
CustodianSelectorFragment.newInstance();
showNextFragment(fragment);
break;
}
}
@Override
public void contactsSelected(Collection<ContactId> contacts) {
Toast.makeText(this,
String.format("Selected %d contacts", contacts.size()),
Toast.LENGTH_SHORT).show();
viewModel.setCustodians((List<ContactId>) contacts);
ThresholdSelectorFragment fragment =
ThresholdSelectorFragment.newInstance(contacts.size());
showNextFragment(fragment);
}
}

View File

@@ -0,0 +1,20 @@
package org.briarproject.briar.android.socialbackup;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardViewModel;
import org.briarproject.briar.android.viewmodel.ViewModelKey;
import androidx.lifecycle.ViewModel;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoMap;
@Module
public abstract class SocialBackupSetupModule {
@Binds
@IntoMap
@ViewModelKey(SocialBackupSetupViewModel.class)
abstract ViewModel bindSocialBackupSetupViewModel(
SocialBackupSetupViewModel socialBackupSetupViewModel);
}

View File

@@ -0,0 +1,147 @@
package org.briarproject.briar.android.socialbackup;
import android.app.Application;
import org.briarproject.bramble.api.connection.ConnectionRegistry;
import org.briarproject.bramble.api.contact.ContactId;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.db.DatabaseComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.event.EventBus;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.android.contact.ContactsViewModel;
import org.briarproject.briar.api.conversation.ConversationManager;
import org.briarproject.briar.api.identity.AuthorManager;
import org.briarproject.briar.api.socialbackup.BackupMetadata;
import org.briarproject.briar.api.socialbackup.SocialBackupManager;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.lifecycle.MutableLiveData;
public class SocialBackupSetupViewModel extends ContactsViewModel {
private final SocialBackupManager socialBackupManager;
private final DatabaseComponent db;
private final ContactManager contactManager;
private BackupMetadata backupMetadata;
private List<ContactId> custodians;
private int threshold;
public enum State {
EXPLAINING,
CHOOSING_CUSTODIANS,
GETTING_THRESHOLD,
SUCCESS,
FAILURE
}
private final MutableLiveData<State> state =
new MutableLiveData<>();
@Inject
public SocialBackupSetupViewModel(
@NonNull Application app,
DatabaseComponent db,
@DatabaseExecutor Executor dbExecutor,
LifecycleManager lifecycleManager,
AuthorManager authorManager,
ConversationManager conversationManager,
ConnectionRegistry connectionRegistry,
EventBus eventBus,
AndroidExecutor androidExecutor,
SocialBackupManager socialBackupManager,
ContactManager contactManager
) {
super(app, dbExecutor, lifecycleManager, db, androidExecutor,
contactManager, authorManager, conversationManager,
connectionRegistry, eventBus);
this.socialBackupManager = socialBackupManager;
this.db = db;
this.contactManager = contactManager;
}
public void loadCustodianList() {
try {
custodians = db.transactionWithResult(true,
socialBackupManager::getCustodianContactIds);
} catch (DbException e) {
custodians = new ArrayList<>();
}
loadContacts();
}
public boolean haveExistingBackup() {
try {
backupMetadata = db.transactionWithNullableResult(true,
socialBackupManager::getBackupMetadata);
} catch (DbException e) {
return false;
}
return (backupMetadata != null);
}
// public BackupMetadata getBackupMetadata() {
// return backupMetadata;
// }
public boolean haveEnoughContacts() throws DbException {
return (contactManager.getContacts().size() > 1);
}
public void setCustodians(List<ContactId> contacts) {
custodians = contacts;
}
public void createBackup() {
try {
db.transaction(false, txn -> {
socialBackupManager
.createBackup(txn, (List<ContactId>) custodians,
threshold);
});
} catch (DbException e) {
state.postValue(State.FAILURE);
}
}
public void setThreshold(int threshold) {
this.threshold = threshold;
createBackup();
}
public void onSuccessDismissed() {
state.postValue(State.SUCCESS);
}
public MutableLiveData<State> getState() {
return state;
}
public void onExplainerDismissed() {
state.postValue(State.CHOOSING_CUSTODIANS);
}
@Override
protected boolean displayContact(ContactId contactId) {
// Check if contact holds a backup piece
return custodians.contains(contactId);
}
public int getThresholdFromExistingBackup() {
return backupMetadata.getThreshold();
}
public int getNumberOfCustodiansFromExistingBackup() {
return backupMetadata.getCustodians().size();
}
}

View File

@@ -1,12 +0,0 @@
package org.briarproject.briar.android.socialbackup;
import org.briarproject.bramble.api.db.DbException;
import androidx.annotation.UiThread;
public interface ThresholdDefinedListener {
@UiThread
void thresholdDefined(int threshold) throws DbException;
}

View File

@@ -2,6 +2,10 @@ package org.briarproject.briar.android.socialbackup;
import android.content.Context;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -11,22 +15,28 @@ import android.view.ViewGroup;
import android.widget.SeekBar;
import android.widget.TextView;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.login.StrengthMeter;
import org.magmacollective.darkcrystal.secretsharingwrapper.SecretSharingWrapper;
import java.util.Arrays;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
import static android.view.View.GONE;
public class ThresholdSelectorFragment extends BaseFragment {
public static final String TAG = ThresholdSelectorFragment.class.getName();
private static final String NUMBER_CUSTODIANS = "numberCustodians";
protected ThresholdDefinedListener listener;
private int numberOfCustodians;
private int threshold;
private int recommendedThreshold;
@@ -34,6 +44,19 @@ public class ThresholdSelectorFragment extends BaseFragment {
private TextView thresholdRepresentation;
private TextView message;
private TextView mOfn;
private StrengthMeter strengthMeter;
@Inject
ViewModelProvider.Factory viewModelFactory;
private SocialBackupSetupViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(SocialBackupSetupViewModel.class);
}
public static ThresholdSelectorFragment newInstance(int numberCustodians) {
Bundle bundle = new Bundle();
@@ -62,21 +85,21 @@ public class ThresholdSelectorFragment extends BaseFragment {
thresholdRepresentation =
view.findViewById(R.id.textViewThresholdRepresentation);
message = view.findViewById(R.id.textViewMessage);
mOfn = view.findViewById(R.id.textViewmOfn);
mOfn = view.findViewById(R.id.text_view_m_of_n);
strengthMeter = view.findViewById(R.id.strength_meter);
if (numberOfCustodians == 2) {
message.setText(R.string.threshold_too_few_custodians);
}
if (numberOfCustodians > 3) {
seekBar.setMax(numberOfCustodians -3);
seekBar.setProgress(threshold - 2);
seekBar.setOnSeekBarChangeListener(new SeekBarListener());
recommendedThreshold =
SecretSharingWrapper.defaultThreshold(numberOfCustodians);
threshold = recommendedThreshold;
seekBar.setProgress(threshold - 2);
strengthMeter.setStrength(1);
} else {
seekBar.setEnabled(false);
seekBar.setVisibility(GONE);
strengthMeter.setVisibility(GONE);
threshold = 2;
seekBar.setMax(numberOfCustodians);
seekBar.setProgress(threshold);
@@ -98,20 +121,13 @@ public class ThresholdSelectorFragment extends BaseFragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
listener = (ThresholdDefinedListener) context;
}
@Override
public String getUniqueTag() {
return TAG;
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.define_threshold_actions, menu);
@@ -122,26 +138,42 @@ public class ThresholdSelectorFragment extends BaseFragment {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_threshold_defined:
try {
listener.thresholdDefined(threshold);
} catch (DbException e) {
e.printStackTrace();
}
viewModel.setThreshold(threshold);
showSuccessDialog();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private String buildThresholdRepresentationString() {
String thresholdRepresentationText = "";
for (int i = 0; i < threshold; i++) {
thresholdRepresentationText += getString(R.string.filled_bullet);
private void showSuccessDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
R.style.BriarDialogTheme);
builder.setTitle(R.string.backup_created);
builder.setMessage(R.string.backup_done_info);
builder.setPositiveButton(R.string.ok,
(dialog, which) -> viewModel.onSuccessDismissed());
builder.setIcon(R.drawable.ic_baseline_done_outline_24);
AlertDialog dialog = builder.create();
dialog.show();
}
private SpannableStringBuilder buildThresholdRepresentationString() {
char[] charArray = new char[numberOfCustodians];
Arrays.fill(charArray, ' ');
SpannableStringBuilder string = new SpannableStringBuilder(new String(charArray));
for (int i = 0; i < numberOfCustodians; i++) {
int drawable = i < threshold
? R.drawable.ic_custodian_required
: R.drawable.ic_custodian_optional;
string.setSpan(new ImageSpan(getContext(), drawable), i,
i+1,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
for (int i = 0; i < (numberOfCustodians - threshold); i++) {
thresholdRepresentationText += getString(R.string.linear_bullet);
}
return thresholdRepresentationText;
// If we have more than 6, split it on two lines
if (numberOfCustodians > 6) string.insert(4, "\n");
return string;
}
private class SeekBarListener implements SeekBar.OnSeekBarChangeListener {
@@ -159,12 +191,23 @@ public class ThresholdSelectorFragment extends BaseFragment {
int sanityLevel = SecretSharingWrapper
.thresholdSanity(threshold, numberOfCustodians);
int text = R.string.threshold_secure;
if (threshold == recommendedThreshold)
float strength = 1;
if (threshold == recommendedThreshold) {
text = R.string.threshold_recommended;
if (sanityLevel < -1) text = R.string.threshold_low_insecure;
if (sanityLevel > 0) text = R.string.threshold_high_insecure;
}
if (sanityLevel < -1) {
strength = 0.75f;
text = R.string.threshold_low_insecure;
}
if (sanityLevel < -2) {
strength = 0.5f;
}
if (sanityLevel > 0) {
strength = 0.75f;
text = R.string.threshold_high_insecure;
}
strengthMeter.setStrength(strength);
message.setText(text);
// TODO change colour of thresholdRepresentation to green/red based on sanityLevel
}
@Override

View File

@@ -32,11 +32,6 @@ public class CustodianRecoveryModeExplainerFragment extends BaseFragment {
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(CustodianReturnShardViewModel.class);
}
// @Override
// public void onCreate(@Nullable Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
// requireActivity().setTitle(R.string.title_help_recover);
// }
@Nullable
@Override

View File

@@ -13,7 +13,6 @@ import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.api.socialbackup.recovery.CustodianTask;
import java.io.IOException;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import javax.inject.Inject;
@@ -21,17 +20,12 @@ import javax.inject.Inject;
import androidx.fragment.app.FragmentManager;
import androidx.lifecycle.ViewModelProvider;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.briar.android.conversation.ConversationActivity.CONTACT_ID;
public class CustodianReturnShardActivity extends BriarActivity
implements BaseFragment.BaseFragmentListener {
private CustodianReturnShardViewModel viewModel;
private static final Logger LOG =
getLogger(CustodianReturnShardActivity.class.getName());
private ContactId contactId;
@Inject
ViewModelProvider.Factory viewModelFactory;
@@ -52,7 +46,7 @@ public class CustodianReturnShardActivity extends BriarActivity
Intent intent = getIntent();
int id = intent.getIntExtra(CONTACT_ID, -1);
if (id == -1) throw new IllegalStateException("No ContactId");
contactId = new ContactId(id);
ContactId contactId = new ContactId(id);
try {
viewModel.start(contactId);
@@ -96,7 +90,8 @@ public class CustodianReturnShardActivity extends BriarActivity
"It looks like you are not connected to a Wifi network",
Toast.LENGTH_SHORT).show();
FragmentManager fm = getSupportFragmentManager();
if (fm.findFragmentByTag(CustodianReturnShardFragment.TAG) == null) {
if (fm.findFragmentByTag(CustodianReturnShardFragment.TAG) ==
null) {
BaseFragment f = new CustodianReturnShardErrorFragment();
fm.beginTransaction()
.replace(R.id.fragmentContainer, f, f.getUniqueTag())
@@ -106,19 +101,15 @@ public class CustodianReturnShardActivity extends BriarActivity
}
}
private void onReturnShardStateChanged(CustodianTask.State state) {
if (state instanceof CustodianTask.State.Success) {
CustodianReturnShardSuccessFragment fragment = new CustodianReturnShardSuccessFragment();
showNextFragment(fragment);
} else if (state instanceof CustodianTask.State.Failure) {
// TODO error fragment here
// TODO handle reason
Toast.makeText(this,
"Backup piece transfer failed",
Toast.LENGTH_SHORT).show();
finish();
}
if (state instanceof CustodianTask.State.Failure) {
// TODO error fragment here
// TODO handle reason
Toast.makeText(this,
"Backup piece transfer failed",
Toast.LENGTH_SHORT).show();
finish();
}
}
private void showCameraFragment() {

View File

@@ -5,6 +5,7 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
@@ -24,6 +25,7 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
import androidx.annotation.UiThread;
import androidx.appcompat.app.AlertDialog;
import androidx.lifecycle.ViewModelProvider;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
@@ -53,6 +55,7 @@ public class CustodianReturnShardFragment extends BaseFragment
private LinearLayout cameraOverlay;
private View statusView;
private TextView status;
private ProgressBar bottomSpinner;
public static CustodianReturnShardFragment newInstance() {
Bundle args = new Bundle();
@@ -84,6 +87,7 @@ public class CustodianReturnShardFragment extends BaseFragment
cameraOverlay = view.findViewById(R.id.camera_overlay);
statusView = view.findViewById(R.id.status_container);
status = view.findViewById(R.id.connect_status);
bottomSpinner = view.findViewById(R.id.qr_code_progress_bar);
viewModel.getState().observe(getViewLifecycleOwner(),
this::onReturnShardStateChanged);
@@ -141,7 +145,6 @@ public class CustodianReturnShardFragment extends BaseFragment
@UiThread
private void onReturnShardStateChanged(@Nullable CustodianTask.State state) {
LOG.info("State changed");
// if (state instanceof CustodianTask.State.Connecting) {
// try {
// cameraView.stop();
@@ -163,8 +166,9 @@ public class CustodianReturnShardFragment extends BaseFragment
} else if (state instanceof CustodianTask.State.ReceivingAck) {
status.setText("Receiving Ack");
} else if (state instanceof CustodianTask.State.Success) {
// TODO
status.setText(R.string.exchanging_contact_details);
statusView.setVisibility(INVISIBLE);
bottomSpinner.setVisibility(INVISIBLE);
showSuccessDialog();
} else if (state instanceof CustodianTask.State.Failure) {
// the activity will replace this fragment with an error fragment
statusView.setVisibility(INVISIBLE);
@@ -190,4 +194,15 @@ public class CustodianReturnShardFragment extends BaseFragment
requireActivity().getSupportFragmentManager().popBackStack();
}
private void showSuccessDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext(),
R.style.BriarDialogTheme);
builder.setTitle(R.string.custodian_shard_sent);
//builder.setMessage();
builder.setPositiveButton(R.string.ok,
(dialog, which) -> viewModel.onSuccessDismissed());
builder.setIcon(R.drawable.ic_baseline_done_outline_24);
AlertDialog dialog = builder.create();
dialog.show();
}
}

View File

@@ -53,7 +53,7 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
final QrCodeDecoder qrCodeDecoder;
private boolean qrCodeRead = false;
private WifiManager wifiManager;
private final MutableLiveEvent<Boolean > continueClicked = new MutableLiveEvent<>();
private final MutableLiveEvent<Boolean> continueClicked = new MutableLiveEvent<>();
private final MutableLiveEvent<Boolean> showCameraFragment =
new MutableLiveEvent<>();
private final MutableLiveEvent<Boolean> successDismissed =
@@ -177,7 +177,6 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
successDismissed.setEvent(true);
}
QrCodeDecoder getQrCodeDecoder() {
return qrCodeDecoder;
}

View File

@@ -44,13 +44,6 @@ public class OwnerReturnShardActivity extends BaseActivity
private OwnerReturnShardViewModel viewModel;
// private final ActivityResultLauncher<String[]> permissionLauncher =
// registerForActivityResult(
// new ActivityResultContracts.RequestMultiplePermissions(),
// r ->
// permissionManager.onRequestPermissionResult(r,
// viewModel::showQrCodeFragmentIfAllowed));
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
@@ -154,7 +147,8 @@ public class OwnerReturnShardActivity extends BaseActivity
"WARNING: Mismatched backup piece!",
Toast.LENGTH_LONG).show();
}
boolean added = (result != RestoreAccount.AddReturnShardPayloadResult.DUPLICATE) ? true : false;
boolean added = result !=
RestoreAccount.AddReturnShardPayloadResult.DUPLICATE;
Toast.makeText(this,
"Success - got backup piece" + (added ? "" : " duplicate"),
Toast.LENGTH_SHORT).show();

View File

@@ -27,7 +27,6 @@ import androidx.lifecycle.ViewModelProvider;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.widget.LinearLayout.HORIZONTAL;
@@ -158,5 +157,4 @@ public class OwnerReturnShardFragment extends BaseFragment
protected void finish() {
requireActivity().getSupportFragmentManager().popBackStack();
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/briar_button_text_positive" android:state_enabled="true"/>
<item android:color="@color/briar_button_text_disabled" />
</selector>

View File

@@ -0,0 +1,5 @@
<vector android:height="48dp" android:tint="#660066"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<vector android:height="48dp" android:tint="#FF00FF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

View File

@@ -0,0 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="72dp"
android:width="72dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M12,5.5A3.5,3.5 0 0,1 15.5,9A3.5,3.5 0 0,1 12,12.5A3.5,3.5 0 0,1 8.5,9A3.5,3.5 0 0,1 12,5.5M5,8C5.56,8 6.08,8.15 6.53,8.42C6.38,9.85 6.8,11.27 7.66,12.38C7.16,13.34 6.16,14 5,14A3,3 0 0,1 2,11A3,3 0 0,1 5,8M19,8A3,3 0 0,1 22,11A3,3 0 0,1 19,14C17.84,14 16.84,13.34 16.34,12.38C17.2,11.27 17.62,9.85 17.47,8.42C17.92,8.15 18.44,8 19,8M5.5,18.25C5.5,16.18 8.41,14.5 12,14.5C15.59,14.5 18.5,16.18 18.5,18.25V20H5.5V18.25M0,20V18.5C0,17.11 1.89,15.94 4.45,15.6C3.86,16.28 3.5,17.22 3.5,18.25V20H0M24,20H20.5V18.25C20.5,17.22 20.14,16.28 19.55,15.6C22.11,15.94 24,17.11 24,18.5V20Z" />
</vector>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="409.2dp"
android:height="161.7dp"
android:viewportHeight="161.7"
android:viewportWidth="409.2">
<path
android:fillColor="#FF000000"
android:pathData="M369.8,157.4l-4.3,-4.3l-7.1,-2.4c-3.9,-1.3 -8.7,-3 -10.7,-3.7l-3.7,-1.3l3.5,-0.2c8.2,-0.4 13,-4 14.3,-10.9c0.8,-4.1 1.1,-17.3 0.8,-33c-0.2,-8.1 -0.2,-15.4 0,-16.3c0.1,-0.9 0.5,-2.4 0.9,-3.4c1.2,-3.5 0.3,-11.9 -1.9,-17.6c-0.3,-0.9 -1.9,-4.2 -3.5,-7.4c-4.2,-8.2 -4.5,-8.9 -4.9,-10.5c-0.5,-1.8 -0.2,-5.4 0.5,-6.8c0.7,-1.3 2.2,-2.9 3.2,-3.5c1.3,-0.7 2.6,0.1 4.7,2.9c3.4,4.5 14,19.4 15.7,22.2c3.7,6 6,11.2 8,18.8c0.7,2.5 1.9,7 2.7,10.1c0.8,3.1 2.7,10.2 4.1,15.8l2.6,10.2l4.6,5.2c2.6,2.9 5.8,6.5 7.2,8c1.4,1.6 2.5,3 2.5,3.2c0,0.3 -34.5,29.3 -34.9,29.3C374.2,161.7 372.2,159.7 369.8,157.4zM275.9,141c-1.3,-0.6 -2.2,-1.4 -2.9,-2.3c-2.1,-2.7 -2,2.4 -1.9,-68.5l0.1,-64l0.7,-1.2c1,-1.9 2,-2.9 3.7,-3.9l1.6,-0.9l37.8,-0.1c42.5,-0.1 39.4,-0.2 42.1,2.2c0.9,0.8 1.8,2 2.2,2.9c0.7,1.6 0.7,1.6 0.8,14.2l0.1,12.6l-1.8,-0.1c-1.4,-0.1 -2.1,0 -3.2,0.5c-2,1 -3.9,2.9 -5.1,5.1l-1,2l0,-12.8l0,-12.8h-33.6h-33.6v51.3v51.3h33.6h33.6l0.1,-34.4c0.1,-33 0.1,-34.4 0.6,-32.9c0.3,0.8 1.8,4 3.4,7c5.5,10.6 5.4,9.9 5.4,47.2c0,27.6 -0.1,30 -1.7,33.1c-1.1,2.2 -2.7,3.7 -5.1,4.7l-1.7,0.7L314,141.8l-36.2,0.1L275.9,141L275.9,141zM318.3,135.9c2.9,-1.3 4.5,-3.7 4.4,-6.6c0,-4.1 -3.1,-7.2 -7.1,-7.2c-2.1,0 -3.6,0.6 -5.2,2.2c-2.2,2.2 -2.8,5.4 -1.3,8.3c0.7,1.4 2.5,3 4,3.5C314.6,136.6 317,136.6 318.3,135.9z"/>
<path
android:fillColor="#FF000000"
android:pathData="M39.4,157.4l4.3,-4.3l7.1,-2.4c3.9,-1.3 8.7,-3 10.7,-3.7l3.7,-1.3l-3.5,-0.2c-8.2,-0.4 -13,-4 -14.3,-10.9c-0.8,-4.1 -1.1,-17.3 -0.8,-33c0.2,-8.1 0.2,-15.4 0,-16.3c-0.1,-0.9 -0.5,-2.4 -0.9,-3.4c-1.2,-3.5 -0.3,-11.9 1.9,-17.6c0.3,-0.9 1.9,-4.2 3.5,-7.4c4.2,-8.2 4.5,-8.9 4.9,-10.5c0.5,-1.8 0.2,-5.4 -0.5,-6.8c-0.7,-1.3 -2.2,-2.9 -3.2,-3.5c-1.3,-0.7 -2.6,0.1 -4.7,2.9c-3.4,4.5 -14,19.4 -15.7,22.2c-3.7,6 -6,11.2 -8,18.8c-0.7,2.5 -1.9,7 -2.7,10.1c-0.8,3.1 -2.7,10.2 -4.1,15.8l-2.6,10.2l-4.6,5.2c-2.6,2.9 -5.8,6.5 -7.2,8s-2.5,3 -2.5,3.2c0,0.3 34.5,29.3 34.9,29.3C35,161.7 37.1,159.7 39.4,157.4zM133.3,141c1.3,-0.6 2.2,-1.4 2.9,-2.3c2.1,-2.7 2,2.4 1.9,-68.5l-0.1,-64l-0.7,-1.2c-1,-1.9 -2,-2.9 -3.7,-3.9l-1.6,-0.9l-37.8,-0.1c-42.5,-0.1 -39.4,-0.2 -42.1,2.2c-0.9,0.8 -1.8,2 -2.2,2.9c-0.7,1.6 -0.7,1.6 -0.8,14.2L49,32l1.8,-0.1c1.4,-0.1 2.1,0 3.2,0.5c2,1 3.9,2.9 5.1,5.1l1,2l0,-12.8l0,-12.8h33.6h33.6v51.3v51.3L93.8,116.5L60.2,116.5l-0.1,-34.4c-0.1,-33 -0.1,-34.4 -0.6,-32.9c-0.3,0.8 -1.8,4 -3.4,7c-5.5,10.6 -5.4,9.9 -5.4,47.2c0,27.6 0.1,30 1.7,33.1c1.1,2.2 2.7,3.7 5.1,4.7l1.7,0.7l36.2,0.1l36.2,0.1L133.3,141L133.3,141zM90.9,135.9c-2.9,-1.3 -4.5,-3.7 -4.4,-6.6c0,-4.1 3.1,-7.2 7.1,-7.2c2.1,0 3.6,0.6 5.2,2.2c2.2,2.2 2.8,5.4 1.3,8.3c-0.7,1.4 -2.5,3 -4,3.5C94.6,136.6 92.3,136.6 90.9,135.9z"/>
<path
android:fillColor="#000000"
android:pathData="M 207.61295,88.782357 h -6.42588 v -12.85177 h 6.42588 m 0,25.703533 h -6.42588 v -6.425883 h 6.42588 m -38.5553,16.064713 h 70.68472 L 204.40001,50.227047 Z"
android:strokeWidth="3.21294165"/>
<path
android:fillColor="#000000"
android:pathData="M90.58,50.42A8.19,8.01 0 0,1 98.77,42.42A8.19,8.01 0 0,1 106.96,50.42C106.96,51.46 107.79,52.27 108.85,52.27C109.91,52.27 110.74,51.46 110.74,50.42V48.58H113.99V50.42A5.67,5.54 0 0,1 108.85,55.97A5.67,5.54 0 0,1 103.18,50.42A4.41,4.31 0 0,0 98.77,46.11A4.41,4.31 0 0,0 94.36,50.42H97.35V53.6C104.79,55.71 110.11,62.31 110.11,70.14A17.64,17.25 0 0,1 92.47,87.38A17.64,17.25 0 0,1 74.83,70.14C74.83,62.31 80.15,55.71 87.43,53.6V50.42H90.58M117.67,50.42H122.6V52.89H117.67V50.42M110.11,45.5V40.57H112.57V45.5H110.11M114.92,46.42L118.5,42.92L120.29,44.68L116.71,48.18L114.92,46.42Z" />
</vector>

View File

@@ -16,6 +16,7 @@
app:title="@string/setup_title"
app:titleTextColor="@android:color/white" />
<include layout="@layout/fragment_start" />
<!-- <include layout="@layout/fragment_start" />-->
<include layout="@layout/fragment_new_or_recover" />
</LinearLayout>

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/margin_large"
android:paddingTop="@dimen/margin_medium"
android:paddingRight="@dimen/margin_large"
android:paddingBottom="@dimen/margin_medium"
tools:ignore="VectorDrawableCompat">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:gravity="center"
android:text="@string/remote_wipe_activate_explain_short"
android:textSize="24sp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="16dp" />
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:srcCompat="@drawable/remote_wipe_activate_explain" />
<TextView
android:id="@+id/textViewExplain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:gravity="center"
android:text="@string/remote_wipe_activate_explain_long"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView"
tools:layout_editor_absoluteX="16dp" />
<Button
android:id="@+id/button_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/remote_wipe_activate_button_confirm"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewExplain" />
<Button
android:id="@+id/button_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/remote_wipe_activate_button_cancel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button_confirm" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
@@ -11,25 +10,35 @@
android:paddingBottom="@dimen/margin_medium"
android:layout_height="match_parent">
<TextView
android:id="@+id/textViewThreshold"
android:id="@+id/textViewThresholdRepresentation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="placeholder threshold"
android:textSize="16sp"
android:textSize="64sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textViewCustodians"
android:id="@+id/textViewThreshold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/backup_done_info"
android:textSize="16sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewThreshold" />
app:layout_constraintTop_toBottomOf="@+id/textViewThresholdRepresentation" />
<org.briarproject.briar.android.view.BriarRecyclerView
android:id="@+id/custodianList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textViewThreshold"
app:scrollToEnd="false" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,130 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="@dimen/margin_large"
android:paddingTop="@dimen/margin_medium"
android:paddingRight="@dimen/margin_large"
android:paddingBottom="@dimen/margin_medium">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Backup creation" />
<Button
android:id="@+id/buttonSelectThreshold"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Select Threshold" />
<Button
android:id="@+id/buttonShardsSent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Shards sent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Setup" />
<Button
android:id="@+id/buttonWelcome"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Welcome" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Recovery from secrect owner's point of view" />
<Button
android:id="@+id/buttonOwnerRecoveryExplainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Explainer" />
<Button
android:id="@+id/buttonOwnerRecoveryReceivedShard"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Shard received" />
<Button
android:id="@+id/buttonOwnerRecoveryMain1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Main (0 shards)" />
<Button
android:id="@+id/buttonOwnerRecoveryMain2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Main (1 shard)" />
<Button
android:id="@+id/buttonOwnerRecoveryMain3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Recovering account…" />
<Button
android:id="@+id/buttonOwnerRecoveryAccountRecovered"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Account recovered" />
<Button
android:id="@+id/buttonOwnerRecoveryErrorExplainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Error" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Recovery from custodian's point of view" />
<Button
android:id="@+id/buttonCustodianRecoveryExplainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Explainer" />
<Button
android:id="@+id/buttonCustodianRecoveryErrorExplainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Error" />
<Button
android:id="@+id/buttonCustodianRecoveryDone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_security"
android:text="Done" />
</LinearLayout>
</ScrollView>

View File

@@ -13,22 +13,38 @@
<Button
android:id="@+id/buttonSetupNewAccount"
style="@style/BriarButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_contacts"
android:text="@string/setup_new_account"
android:drawableLeft="@drawable/ic_contacts"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
app:layout_constraintTop_toTopOf="parent"
android:drawableStart="@drawable/ic_contacts" />
<TextView
android:id="@+id/textViewExplain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:gravity="center"
android:text="@string/custodian_recovery_explainer_extra"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/buttonSetupNewAccount"
tools:layout_editor_absoluteX="16dp" />
<Button
android:id="@+id/buttonRestoreAccount"
android:id="@+id/buttonRestoreAccount2"
style="@style/BriarButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/ic_repeat"
android:text="@string/setup_restore_account"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/buttonSetupNewAccount" />
app:layout_constraintTop_toBottomOf="@+id/textViewExplain"
tools:enabled="true"
android:drawableStart="@drawable/ic_repeat" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/margin_large"
android:paddingTop="@dimen/margin_medium"
android:paddingRight="@dimen/margin_large"
android:paddingBottom="@dimen/margin_medium"
tools:ignore="VectorDrawableCompat">
<TextView
android:id="@+id/text_view_explain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:gravity="center"
android:text="@string/remote_wipe_display_explain"
android:textSize="16sp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="16dp" />
<Button
android:id="@+id/button_cancel"
style="@style/BriarButtonFlat.Negative.Tiny"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/remote_wipe_disable"
app:layout_constraintBottom_toBottomOf="@+id/button_change"
app:layout_constraintEnd_toStartOf="@id/button_change"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/text_view_explain" />
<Button
android:id="@+id/button_change"
style="@style/BriarButtonFlat.Positive.Tiny"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/remote_wipe_modify_contacts"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/button_cancel"
app:layout_constraintTop_toBottomOf="@id/text_view_explain" />
<org.briarproject.briar.android.view.BriarRecyclerView
android:id="@+id/wiperList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/button_change"
app:scrollToEnd="false" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/margin_large"
android:paddingTop="@dimen/margin_medium"
android:paddingRight="@dimen/margin_large"
android:paddingBottom="@dimen/margin_medium"
tools:ignore="VectorDrawableCompat">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:gravity="center"
android:text="@string/remote_wipe_setup_explain_title"
android:textSize="24sp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="16dp" />
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:srcCompat="@drawable/remote_wipe_activate_explain" />
<TextView
android:id="@+id/textViewExplain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:gravity="center"
android:text="@string/remote_wipe_setup_explain_long"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView"
tools:layout_editor_absoluteX="16dp" />
<Button
android:id="@+id/button_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/title_select_wipers"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewExplain" />
<Button
android:id="@+id/button_cancel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/remote_wipe_activate_button_cancel"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/button_confirm" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -15,7 +15,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="@string/ok"
android:text="@string/button_confirm"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -27,7 +27,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="@string/custodian_shard_sent"
android:text="@string/remote_wipe_revoke_success"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -48,3 +48,4 @@
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_baseline_done_outline_24" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -45,7 +45,7 @@
app:layout_constraintTop_toBottomOf="@+id/seekBar" />
<TextView
android:id="@+id/textViewmOfn"
android:id="@+id/text_view_m_of_n"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
@@ -55,6 +55,17 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewThresholdRepresentation" />
<org.briarproject.briar.android.login.StrengthMeter
android:id="@+id/strength_meter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:visibility="visible"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_view_m_of_n"
tools:visibility="visible" />
<TextView
android:id="@+id/textViewMessage"
android:layout_width="wrap_content"
@@ -64,6 +75,6 @@
android:textSize="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewmOfn" />
app:layout_constraintTop_toBottomOf="@+id/strength_meter" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -47,14 +47,28 @@
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_activity_horizontal"
android:enabled="false"
android:text="@string/setup_next"
app:layout_constraintBottom_toBottomOf="parent"
android:text="@string/setup_new_account"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/nickname_entry_wrapper"
app:layout_constraintVertical_bias="1.0"
tools:enabled="true" />
<Button
android:id="@+id/buttonRestoreAccount"
style="@style/BriarButtonFlat.Positive.Tiny"
android:textColor="@drawable/button_positive_tiny_disable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_activity_horizontal"
android:text="@string/setup_restore_account"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/next"
app:layout_constraintVertical_bias="1.0"
tools:enabled="true" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View File

@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/margin_large"
android:paddingTop="@dimen/margin_medium"
android:paddingRight="@dimen/margin_large"
android:paddingBottom="@dimen/margin_medium">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="@string/ok"
android:textSize="24sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="@string/backup_done_info"
android:gravity="center"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView2" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_baseline_done_outline_24" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/margin_large"
android:paddingTop="@dimen/margin_medium"
android:paddingRight="@dimen/margin_large"
android:paddingBottom="@dimen/margin_medium"
tools:ignore="VectorDrawableCompat">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:gravity="center"
android:text="@string/social_backup_setup_explainer_title"
android:textSize="24sp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="16dp" />
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView"
app:srcCompat="@drawable/ic_social_backup_group" />
<TextView
android:id="@+id/textViewExplain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center"
android:text="@string/social_backup_setup_explainer_long"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView"
tools:layout_editor_absoluteX="16dp" />
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="@string/social_backup_setup_explainer_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewExplain" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -6,6 +6,7 @@
<ProgressBar
style="?android:attr/progressBarStyleLarge"
android:id="@+id/qr_code_progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />

View File

@@ -33,4 +33,18 @@
android:title="@string/help_recover_account"
android:enabled="false"
app:showAsAction="never"/>
<item
android:id="@+id/action_remote_wipe"
android:icon="@drawable/action_delete_white"
android:title="@string/activate_remote_wipe"
android:enabled="false"
app:showAsAction="never"/>
<item
android:id="@+id/action_revoke_remote_wipe"
android:icon="@drawable/action_delete_white"
android:title="@string/revoke_remote_wipe"
android:enabled="false"
app:showAsAction="never"/>
</menu>

View File

@@ -0,0 +1,524 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<!-- Setup -->
<string name="setup_title">Selamat Datang di Briar</string>
<string name="setup_name_explanation">Nama panggilan Anda akan terlihat pada setiap materi yang Anda unggah. Anda tidak bisa mengubah setelah membuatnya.</string>
<string name="setup_next">Selanjutnya</string>
<string name="setup_password_intro">Pilih Kata Sandi</string>
<string name="setup_password_explanation">Akun Briar Anda tersimpan dalam perangkat terenkripsi, bukan di komputasi awan. Jika lupa kata sandi atau menghapus aplikasi Briar, Anda hanya bisa mengembalikan akun jika sudah membuat pencadangan sosial.\n\nBuatlah kata sandi panjang yang susah ditebak, misalnya empat kata acak atau sepuluh huruf, angka, dan simbol acak.</string>
<string name="setup_doze_title">Sambungan Belakang</string>
<string name="setup_doze_intro">Untuk menerima pesan, Briar perlu tetap terkoneksi dengan sambungan belakang.</string>
<string name="setup_doze_explanation">Untuk menerima pesan, Briar perlu tetap terkoneksi dengan sambungan belakang. Silakan nonaktifkan pengoptimalan baterai agar Briar tetap bisa terkoneksi.</string>
<string name="setup_doze_button">Izinkan Koneksi</string>
<string name="choose_nickname">Pilih nama panggilan Anda</string>
<string name="choose_password">Pilih kata sandi Anda</string>
<string name="confirm_password">Konfirmasi kata sandi Anda</string>
<string name="name_too_long">Nama terlalu panjang</string>
<string name="password_too_weak">Kata sandi terlalu lemah</string>
<string name="passwords_do_not_match">Kata sandi tidak cocok</string>
<string name="create_account_button">Buat Akun</string>
<string name="more_info">Informasi Selanjutnya</string>
<string name="don_t_ask_again">Jangan tanya lagi</string>
<string name="setup_huawei_text">Silakan ketuk tombol di bawah dan pastikan Briar terlindungi di layar \"Aplikasi Terlindungi\".</string>
<string name="setup_huawei_button">Lindungi Briar</string>
<string name="setup_huawei_help">Jika tidak dimasukkan dalam daftar aplikasi terlindungi, Briar tidak akan bisa berfungsi di sambungan belakang.</string>
<string name="warning_dozed">%tidak bisa berfungsi di sambungan belakang</string>
<!-- Login -->
<string name="enter_password">Kata Sandi</string>
<string name="try_again">Kata sandi salah, coba lagi</string>
<string name="dialog_title_cannot_check_password">Tidak Bisa Memeriksa Kata Sandi</string>
<string name="dialog_message_cannot_check_password">Briar tidak bisa memeriksa kata sandi Anda. Silakan booting ulang perangkat untuk memecahkan masalah Anda.</string>
<string name="sign_in_button">Masuk</string>
<string name="forgotten_password">Saya lupa kata sandi</string>
<string name="dialog_title_lost_password">Kata sandi hilang</string>
<string name="dialog_message_lost_password">Akun Briar Anda tersimpan dalam perangkat terenkripsi, bukan di komputasi awan, jadi kami tidak bisa membuat ulang kata sandi Anda. Jika Anda memiliki cadangan sosial, Anda bisa menghapus akun Anda dan membuat kata sandi baru ketika Anda mengembalikan. Apakah Anda mau menghapus akun dan memulai lagi?\n\nPerhatian: Identitas, kontak, dan pesan Anda akan sepenuhnya hilang jika Anda tidak punya cadangan.</string>
<string name="startup_failed_notification_title">Briar tidak bisa memulai</string>
<string name="startup_failed_notification_text">Ketuk untuk informasi selanjutnya.</string>
<string name="startup_failed_activity_title">Briar Gagal Memulai</string>
<string name="startup_failed_db_error">Karena beberapa alasan, pangkalan data Briar Anda rusak dan tidak bisa diperbaiki. Akun, data, dan semua kontak Anda hilang. Sayangnya, Anda perlu memasang ulang Briar atau membuat akun baru dengan memilih \'Saya lupa kata sandi\' pada bagian kata sandi.</string>
<string name="startup_failed_data_too_old_error">Akun Anda dibuat menggunakan versi lama aplikasi ini dan tidak bisa dibuka dengan versi sekarang. Anda harus memasang ulang versi lama atau membuat akun baru dengan memilih \'Saya lupa kata sandi\' pada bagian kata sandi.</string>
<string name="startup_failed_data_too_new_error">Versi aplikasi ini sudah usang. Silakan naikkan ke versi terbaru dan coba lagi.</string>
<string name="startup_failed_service_error">Briar tidak bisa memulai pengaya yang diperlukan. Memasang ulang Briar biasanya memecahkan masalah. Namun, harap diperhatikan bahwa Anda akan kehilangan semua data karena Briar tidak menggunakan peladen terpusat untuk menyimpan data Anda.</string>
<plurals name="expiry_warning">
<item quantity="other">Ini adalah Briar versi percobaan. Akun Anda akan kedaluwarsa pada % hari dan tidak bisa diperbarui.</item>
</plurals>
<string name="expiry_date_reached">Perangkat lunak ini sudah kedaluwarsa.\nTerima kasih sudah mencoba!</string>
<string name="download_briar">Untuk lanjut menggunakan Briar, silakan unduh versi terbaru.</string>
<string name="create_new_account">Anda akan perlu membuat akun baru, tetapi bisa menggunakan nama sama.</string>
<string name="download_briar_button">Unduh Keluaran Terbaru</string>
<string name="startup_open_database">Mendekrip Pangkalan Data…</string>
<string name="startup_migrate_database">Meningkatkan Pangkalan Data…</string>
<string name="startup_compact_database">Meringkas Pangkalan Data…</string>
<!-- Navigation Drawer -->
<string name="nav_drawer_open_description">Buka penarik navigasi</string>
<string name="nav_drawer_close_description">Tutup penarik navigasi</string>
<string name="contact_list_button">Kontak</string>
<string name="groups_button">Group Pribadi</string>
<string name="forums_button">Forum</string>
<string name="blogs_button">Blog</string>
<!-- This is part of the main menu. The app will be locked when this is tapped. -->
<string name="lock_button">Kunci Aplikasi</string>
<string name="settings_button">Pengaturan</string>
<string name="sign_out_button">Keluar</string>
<string name="transports_onboarding_text">Ketuk di sini untuk mengontrol bagaimana Briar tersambung dengan kontak Anda.</string>
<!-- Transports: Tor -->
<string name="transport_tor">Internet</string>
<string name="tor_device_status_online_wifi">Ponsel Anda punya akses Internet lewat Wi-Fi</string>
<string name="tor_device_status_online_mobile">Ponsel Anda punya akses Internet lewat paket data</string>
<string name="tor_device_status_offline">Ponsel Anda tidak punya akses Internet</string>
<string name="tor_plugin_status_enabling">Briar menyambung ke Internet</string>
<string name="tor_plugin_status_active">Briar tersambung Internet</string>
<string name="tor_plugin_status_inactive">Briar tidak bisa menyambung ke Internet</string>
<string name="tor_plugin_status_disabled">Briar dikonfigurasi tidak menggunakan Internet</string>
<string name="tor_plugin_status_disabled_mobile_data">Briar dikonfigurasi tidak menggunakan paket data</string>
<string name="tor_plugin_status_disabled_battery">Briar dikonfigurasi tidak menggunakan Internet ketika menggunakan baterai</string>
<string name="tor_plugin_status_disabled_country_blocked">Briar dikonfigurasi tidak menggunakan Internet di negara ini</string>
<!-- Transports: Wi-Fi -->
<string name="transport_lan">Wi-Fi</string>
<string name="transport_lan_long">Jaringan Wi-Fi Sama</string>
<string name="lan_device_status_on">Ponsel Anda tersambung Wi-Fi</string>
<string name="lan_device_status_off">Ponsel Anda tidak tersambung Wi-Fi</string>
<string name="lan_plugin_status_enabling">Briar menyambung ke Wi-Fi</string>
<string name="lan_plugin_status_active">Briar tersambung Wi-Fi</string>
<string name="lan_plugin_status_inactive">Briar tidak tersambung Wi-Fi</string>
<string name="lan_plugin_status_disabled">Briar dikonfigutasi tidak menggunakan Wi-Fi</string>
<!-- Transports: Bluetooth -->
<string name="transport_bt">Bluetooth</string>
<string name="bt_device_status_on">Bluetooth ponsel Anda hidup</string>
<string name="bt_device_status_off">Bluetooth ponsel Anda mati</string>
<string name="bt_plugin_status_enabling">Briar menyambung ke Bluetooth</string>
<string name="bt_plugin_status_active">Briar tersambung Bluetooth</string>
<string name="bt_plugin_status_inactive">Briar tidak bisa tersambung Bluetooth</string>
<string name="bt_plugin_status_disabled">Briar dikonfigurasi tidak menggunakan Bluetooth</string>
<!-- Notifications -->
<string name="reminder_notification_title">Keluar Briar</string>
<string name="reminder_notification_text">Ketuk untuk masuk kembali.</string>
<string name="reminder_notification_channel_title">Pengingat Masuk Briar</string>
<string name="reminder_notification_dismiss">Singkirkan</string>
<string name="ongoing_notification_title">Masuk Briar</string>
<string name="ongoing_notification_text">Sentuh untuk membuka Briar.</string>
<plurals name="private_message_notification_text">
<item quantity="other">%d Pesan-pesan pribadi baru.</item>
</plurals>
<!-- Misc -->
<string name="now">sekarang</string>
<string name="show">Tunjukkan</string>
<string name="hide">Sembunyikan</string>
<string name="ok">OK</string>
<string name="cancel">Batal</string>
<string name="got_it">Paham</string>
<string name="delete">Hapus</string>
<string name="accept">Terima</string>
<string name="decline">Tolak</string>
<string name="online">Daring</string>
<string name="offline">Luring</string>
<string name="send">Kirim</string>
<string name="allow">Izinkan</string>
<string name="open">Buka</string>
<string name="change">Ubah</string>
<string name="no_data">Tidak Ada Data</string>
<string name="ellipsis"></string>
<string name="text_too_long">Teks yang dimasukkan terlalu panjang</string>
<string name="show_onboarding">Perlihatkan Dialog Bantuan</string>
<string name="fix">Bereskan</string>
<string name="help">Bantu</string>
<string name="sorry">Maaf</string>
<string name="error_start_activity">Tidak tersedia di sistem Anda</string>
<string name="status_heading">Status:</string>
<!-- Contacts and Private Conversations-->
<string name="no_contacts">Tidak ada kontak untuk diperlihatkan</string>
<string name="no_contacts_action">Ketuk ikon + untuk menambah kontak</string>
<string name="date_no_private_messages">Tidak ada pesan.</string>
<string name="no_private_messages">Tidak ada pesan untuk diperlihatkan</string>
<string name="message_hint">Tulisa pesan</string>
<string name="image_caption_hint">Tambahkan keterangan (pilihan)</string>
<string name="image_attach">Lampirkan gambar</string>
<string name="image_attach_error">Tidak bisa melampirkan gambar</string>
<string name="image_attach_error_too_big">Gambar terlalu besar. Batasnya %d MB.</string>
<string name="image_attach_error_invalid_mime_type">Format gambar tidak mendukung: %s</string>
<string name="set_contact_alias">Ubah nama kontak</string>
<string name="set_contact_alias_hint">Nama kontak</string>
<string name="delete_all_messages">Hapus semua pesan</string>
<string name="dialog_title_delete_all_messages">Konfirmasi Penghapusan Pesan</string>
<string name="dialog_message_delete_all_messages">Anda yakin untuk menghapus semua pesan?</string>
<string name="dialog_title_not_all_messages_deleted">Tidak bisa menghapus semua pesan</string>
<string name="delete_contact">Hapus kontak</string>
<string name="dialog_title_delete_contact">Konfirmasi Penghapusan Kontak</string>
<string name="dialog_message_delete_contact">Apakah Anda yakin akan menghapus kontak ini dan semua pesannya?</string>
<string name="contact_deleted_toast">Kontak Dihapus</string>
<!-- This is shown in the action bar when opening an image in fullscreen that the user sent -->
<string name="you">Anda</string>
<string name="save_image">Simpan gambar</string>
<string name="dialog_title_save_image">Simpan gambar?</string>
<string name="save_image_success">Gambar tersimpan</string>
<string name="save_image_error">Tidak bisa menghapus gambar</string>
<string name="dialog_title_no_image_support">Gambar tidak tersedia</string>
<!-- Adding Contacts -->
<string name="add_contact_title">Tambah Kontak Sekitar</string>
<string name="face_to_face">Anda harus bertemu dengan orang yang ingin Anda tambahkan sebagai kontak.\n\nHal ini ubtuk mencegah orang lain membuat akun tiruan atau membaca pesan Anda di kemudian hari.</string>
<string name="continue_button">Lanjut</string>
<string name="try_again_button">Coba Lagi</string>
<string name="waiting_for_contact_to_scan">Menunggu kontak untuk memindai dan menyambung\u2026</string>
<string name="exchanging_contact_details">Bertukar detail kontak\u2026</string>
<string name="contact_added_toast">Kontak ditambahkan: %s</string>
<string name="contact_already_exists">%s kontak sudah ada</string>
<string name="qr_code_invalid">Kode batang salah</string>
<string name="qr_code_too_old">Kode batang yang Anda pindai adalah versi lebih lama %s.\n\nSilakan minta kontak Anda untuk menaikkan ke versi terbaru dan coba lagi.</string>
<string name="qr_code_too_new">Kode batang yang Anda pindai adalah versi lebih mutakhir %s.\n\nSilakan naikkan ke versi terbaru dan coba lagi.</string>
<string name="camera_error">Kamera Rusak</string>
<string name="connecting_to_device">Menyambung ke perangkat\u2026</string>
<string name="authenticating_with_device">Mengautentikasi ke perangkat\u2026</string>
<string name="connection_error_title">Tidak bisa menyambung dengan kontak Anda</string>
<string name="connection_error_feedback">Jika masalah ini berulang, silakan <a href="feedback">kirim umpan balik</a> untuk memperbaiki aplikasi.</string>
<!-- Adding Contacts Remotely -->
<string name="add_contact_remotely_title_case">Tambahkan kontak jarak jauh</string>
<string name="add_contact_nearby_title">Tambahkan kontak di dekat Anda</string>
<string name="add_contact_remotely_title">Tambahkan kontak jarak jauh</string>
<string name="contact_link_intro">Masukkan tautan dari kontak Anda di sini</string>
<string name="contact_link_hint">Tautan kontak</string>
<string name="paste_button">Tempel</string>
<string name="add_contact_button">Tambahkan kontak</string>
<string name="copy_button">Salin</string>
<string name="share_button">Bagi</string>
<string name="send_link_title">Tukar tautan</string>
<string name="add_contact_choose_nickname">Pilih Nama Panggilan</string>
<string name="add_contact_choose_a_nickname">Masukkan Nama Panggilan</string>
<string name="nickname_intro">Berikan kontak Anda nama panggilan. Hanya Anda yang bisa melihat.</string>
<string name="your_link">Beri tautan ini pada kontak yang ingin Anda tambahkan</string>
<string name="link_clip_label">Tautan Briar</string>
<string name="link_copied_toast">Tautan Tersalin</string>
<string name="adding_contact_error">Ada masalah ketika menambah kontak.</string>
<string name="pending_contact_requests_snackbar">Ada permintaan kontak yang tertunda</string>
<string name="pending_contact_requests">Permintaan Kontak Tertunda</string>
<string name="no_pending_contacts">Tidak ada kontak tertunda</string>
<string name="waiting_for_contact_to_come_online">Menunggu kontak untuk daring…</string>
<string name="connecting">Menyambung…</string>
<string name="adding_contact">Menambah kontak…</string>
<string name="adding_contact_failed">Penambahan kontak gagal</string>
<string name="dialog_title_remove_pending_contact">Konfirmasi Penghapusan</string>
<string name="dialog_message_remove_pending_contact">Kontak ini masih sedang ditambahkan. Jika Anda menghapusnya, kontak tidak akan ditambahkan.</string>
<string name="own_link_error">Masukkan tautan kontak Anda, bukan tautan Anda sendiri</string>
<string name="nickname_missing">Masukkan nama panggilan</string>
<string name="invalid_link">Tautan Keliru</string>
<string name="unsupported_link">Tautan ini dari Briar versi lebih mutakhir. Silakan naikkan ke versi terbaru dan coba lagi.</string>
<string name="intent_own_link">Anda membuka tautan Anda sendiri. Gunakan dari kontak yang ingin Anda tambahkan!</string>
<string name="missing_link">Masukkan tautan</string>
<!-- This is a numeral indicating the first step in a series of screens -->
<string name="step_1">1</string>
<!-- This is a numeral indicating the second step in a series of screens -->
<string name="step_2">2</string>
<plurals name="contact_added_notification_text">
<item quantity="other">%d kontak baru ditambahkan.</item>
</plurals>
<string name="offline_state">Tidak ada koneksi Internet</string>
<string name="duplicate_link_dialog_title">Gandakan Tautan</string>
<string name="duplicate_link_dialog_text_1">Anda memiliki kontak tertunda dengan tautan berikut: %s</string>
<string name="duplicate_link_dialog_text_1_contact">Anda sudah memiliki kontak dengan tautan berikut: %s</string>
<!-- This is a question asking whether two nicknames refer to the same person -->
<string name="duplicate_link_dialog_text_2">Apakah %s and %s adalah orang yang sama?</string>
<!-- This is a button for answering that two nicknames do indeed refer to the same person. This
string will be used in a dialog button, so if the translation of this string is longer than 20
characters, please use "Yes" instead, and use "No" for the "Different Person" button -->
<string name="same_person_button">Orang Sama</string>
<!-- This is a button for answering that two nicknames refer to different people. This string
will be used in a dialog button, so if the translation of this string longer than 20 characters,
please use "No" instead, and use "Yes" for the "Same Person" button -->
<string name="different_person_button">Orang Berbeda</string>
<string name="duplicate_link_dialog_text_3">%s dan %s mengirimkan tautan yang sama.\n\nSalah satu dari mereka mungkin sedang mencoba menemukan siapa kontak Anda.\n\nJangan beritahu bahwa Anda menerima tautan sama dari orang lain.</string>
<string name="pending_contact_updated_toast">Menunda pembaruan kontak</string>
<!-- Settings Profile Picture -->
<string name="change_profile_picture">Ketuk untuk mengubah gambar profil Anda</string>
<string name="dialog_confirm_profile_picture_title">Ubah gambar profil Anda</string>
<string name="dialog_confirm_profile_picture_remark">Hanya kontak Anda yang bisa melihat gambar ini</string>
<string name="change_profile_picture_failed_message">Mohon maaf, tetapi ada masalah ketika Anda memutakhirkan gambar profil Anda</string>
<!-- Settings Display -->
<string name="pref_language_title">Bahasa &amp; region</string>
<string name="pref_language_changed">Pengaturan ini akan mempengaruhi ketika Anda memulai ulang Briar. Silakan keluar dan mulai ulang Briar.</string>
<string name="pref_language_default">Bawaan sistem</string>
<string name="display_settings_title">Tampilan</string>
<string name="pref_theme_title">Tema</string>
<string name="pref_theme_light">Terang</string>
<string name="pref_theme_dark">Gelap</string>
<string name="pref_theme_auto">Otomatis (Siang)</string>
<string name="pref_theme_system">Bawaan sistem</string>
<!-- Settings Connections -->
<string name="network_settings_title">Koneksi</string>
<string name="bluetooth_setting">Menyambung kontak lewat Bluetooth</string>
<string name="wifi_setting">Menyambung kontak di Wi-Fi yang Sama</string>
<string name="tor_enable_title">Menyambung kontak lewat Internet</string>
<string name="tor_enable_summary">Semua koneksi melalui jaringan Tor untuk privasi</string>
<string name="tor_network_setting">Metode koneksi untuk jaringan Tor</string>
<string name="tor_network_setting_automatic">Otomatis sesuai lokasi</string>
<string name="tor_network_setting_without_bridges">Gunakan jaringan Tor tanpa jembatan</string>
<string name="tor_network_setting_with_bridges">Gunakan jaringan Tor dengan jembatan</string>
<string name="tor_network_setting_never">Jangan sambungkan ke Internet</string>
<!-- How and when Briar will connect to Tor: E.g. "Don't connect to the Internet (in China)" or "Use Tor network with bridges (in Belarus)" -->
<string name="tor_network_setting_summary">Otomatis: %1$s (di %2$s)</string>
<string name="tor_mobile_data_title">Gunakan paket data</string>
<string name="tor_only_when_charging_title">Sambungkan ke Internet hanya ketika mengisi daya</string>
<string name="tor_only_when_charging_summary">Nonaktifkan koneksi Internet ketika perangkat menggunakan baterai</string>
<!-- Settings Security and Panic -->
<string name="security_settings_title">Keamanan</string>
<string name="pref_lock_title">Kunci Aplikasi</string>
<string name="pref_lock_summary">Gunakan kunci layar perangkat untuk melindungi Briar ketika masuk</string>
<string name="pref_lock_disabled_summary">untuk menggunakan fitur ini, gunakan kunci layar untuk perangkat Anda</string>
<string name="pref_lock_timeout_title">Waktu ketidakaktifan kunci selesai</string>
<!-- The %s placeholder is replaced with the following time spans, e.g. 5 Minutes, 1 Hour -->
<string name="pref_lock_timeout_summary">Ketika tidak menggunakan Briar, otomatis akan mengunci setelah %s</string>
<!-- Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s" -->
<string name="pref_lock_timeout_1">1 menit</string>
<!-- Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s" -->
<string name="pref_lock_timeout_5">5 menit</string>
<!-- Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s" -->
<string name="pref_lock_timeout_15">15 menit</string>
<!-- Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s" -->
<string name="pref_lock_timeout_30">30 menit</string>
<!-- Will be shown in a list of lock times. Should fit into the %s of "automatically lock it after %s" -->
<string name="pref_lock_timeout_60">1 jama</string>
<string name="pref_lock_timeout_never">Tidak Usah</string>
<string name="pref_lock_timeout_never_summary">Jangan pernah kunci Briar secara otomatis</string>
<string name="change_password">Ubah kata sandi</string>
<string name="current_password">Kata sandi saat ini</string>
<string name="choose_new_password">Kata sandi baru</string>
<string name="confirm_new_password">Konfirmasi kata sandi baru</string>
<string name="password_changed">Kata sandi telah diubah.</string>
<string name="panic_setting">Pengaturan tombol darurat</string>
<string name="panic_setting_title">Tombol darurat</string>
<string name="panic_setting_hint">Konfigurasikan bagaimana Briar akan bereaksi ketika Anda menggunakan aplikasi tombol darurat</string>
<string name="panic_app_setting_title">Aplikasi Tombol Darurat</string>
<string name="unknown_app">aplikasi tidak dikenal</string>
<string name="panic_app_setting_summary">Tidak ada aplikasi yang diatur</string>
<string name="panic_app_setting_none">Tidak Ada</string>
<string name="dialog_title_connect_panic_app">Konfirmasi Aplikasi Darurat</string>
<string name="dialog_message_connect_panic_app">Apakah Anda yakin mengizinkan %1$s untuk memicu tindakan merusak tombol darurat?</string>
<string name="panic_setting_destructive_action">Tindak Merusak</string>
<string name="panic_setting_signout_title">Keluar</string>
<string name="panic_setting_signout_summary">Keluar dari Briar jika tombol darurat ditekan</string>
<string name="purge_setting_title">Hapus Akun</string>
<string name="purge_setting_summary">Hapus akun Briar Anda jika tombol darurat ditekan. Perhatian: Tindakan ini akan menghapus semua identitas, kontak, dan pesan Anda.</string>
<!-- Settings Notifications -->
<string name="notification_settings_title">Notifikasi</string>
<string name="notify_sign_in_title">Ingatkan saya untuk masuk</string>
<string name="notify_sign_in_summary">Tunjukkan pengingat ketika ponsel mulai atau aplikasi telah diperbarui</string>
<string name="notify_private_messages_setting_title">Pesan pribadi</string>
<string name="notify_private_messages_setting_summary">Tunjukkan peringatan pesan pribadi</string>
<string name="notify_private_messages_setting_summary_26">Konfigurasi peringatan pesan pribadi</string>
<string name="notify_group_messages_setting_title">Pesan grup</string>
<string name="notify_group_messages_setting_summary">Tunjukkan peringatan pesan grup</string>
<string name="notify_group_messages_setting_summary_26">Konfigurasi peringatan pesan grup</string>
<string name="notify_forum_posts_setting_title">Unggahan forum</string>
<string name="notify_forum_posts_setting_summary">Tunjukkan peringatan unggahan forum</string>
<string name="notify_forum_posts_setting_summary_26">Konfigurasi peringatan unggahan forum</string>
<string name="notify_blog_posts_setting_title">Unggahan blog</string>
<string name="notify_blog_posts_setting_summary">Tunjukkan peringatan unggahan blog</string>
<string name="notify_blog_posts_setting_summary_26">Konfigurasi peringatan unggahan blog</string>
<string name="notify_vibration_setting">Getar</string>
<string name="notify_sound_setting">Suara</string>
<string name="notify_sound_setting_default">Nada dering bawaan</string>
<string name="notify_sound_setting_disabled">Tidak ada</string>
<string name="choose_ringtone_title">Pilih nada dering</string>
<string name="cannot_load_ringtone">Tidak bisa memuat nada dering</string>
<!-- Settings Feedback -->
<string name="feedback_settings_title">Umpan balik</string>
<string name="send_feedback">Kirim umpan balik</string>
<!-- Crash Reporter -->
<string name="crash_report_title">Laporan Kerusakan Briar</string>
<string name="briar_crashed">Maaf, Briar Rusak.</string>
<string name="not_your_fault">Ini bukan kesalahan Anda.</string>
<string name="please_send_report">Silakan bantu kami untuk membuat Briar lebih baik dengan mengirimkan laporan kerusakan.</string>
<string name="report_is_encrypted">Kami berjanji laporan Anda terenkripsi dan dikirim dengan aman.</string>
<string name="feedback_title">Umpan balik</string>
<string name="describe_crash">Jelaskan apa yang terjadi (pilihan)</string>
<string name="enter_feedback">Masukkan masukan Anda</string>
<string name="optional_contact_email">Surel Anda (pilihan)</string>
<string name="include_debug_report_crash">Sertakan data anonimus kerusakan</string>
<string name="include_debug_report_feedback">Sertakan data anonimus perangkat</string>
<string name="dev_report_basic_info">Informasi dasar</string>
<string name="dev_report_device_info">Informasi perangkat</string>
<string name="dev_report_stacktrace">Jejak tumpukan</string>
<string name="dev_report_time_info">Informasi waktu</string>
<string name="dev_report_memory">Memori</string>
<string name="dev_report_storage">Penyimpanan</string>
<string name="dev_report_connectivity">Konektivitas</string>
<string name="dev_report_build_config">Bua konfigurasi</string>
<string name="dev_report_logcat">Catatan aplikasi</string>
<string name="dev_report_device_features">Fitur Perangkat</string>
<string name="send_report">Kirim laporan</string>
<string name="close">Tutup</string>
<string name="dev_report_sending">Mengirim umpan balik…</string>
<string name="dev_report_sent">Kirim balik terkirim</string>
<string name="dev_report_saved">Laporan tersimpan. Akan dikirim pada saat Anda masuk Briar.</string>
<string name="dev_report_error">Masalah: Pengiriman laporan gagal</string>
<!-- Sign Out -->
<string name="progress_title_logout">Keluar dari Briar…</string>
<!-- Permission Requests -->
<string name="permission_camera_title">Izin Kamera</string>
<string name="permission_camera_request_body">Untuk memindai kode batang, Briar memerlukan akses ke kamera.</string>
<string name="permission_location_title">Izin lokasi</string>
<string name="permission_location_request_body">Untuk menemukan Bluetooth perangkat, Briar memerlukan izin untuk mengakses lokasi Anda.\n\nBriar tidak menyimpan lokasi Anda atau membaginya kepada orang lain.</string>
<string name="permission_camera_location_title">Kamera dan lokasi</string>
<string name="permission_camera_location_request_body">Untuk memindai kode batang, Briar memerlukan akses ke kamera.\n\nUntuk menemukan Bluetooth perangkat, Briar memerlukan izin untuk mengakses lokasi Anda.\n\nBriar tidak menyimpan lokasi Anda atau membaginya kepada orang lain.</string>
<string name="permission_camera_denied_body">Anda sudah menolak akses ke kamera, tetapi menambahkan kontak memerlukan penggunaan kamera.\n\nHarap pertimbangkan memberikan akses.</string>
<string name="permission_location_denied_body">Anda sudah menolak akses ke lokasi, tetapi Briar memerlukan izin tersebut untuk menemukan Bluetooth perangkat. Harap pertimbangkan memberikan akses.</string>
<string name="permission_location_setting_title">Pengaturan Lokasi</string>
<string name="permission_location_setting_body">Pengaturan lokasi perangkat Anda harus diaktifkan untuk menemukan perangkat lain melalui Bluetooth. Harap hidupkan lokasi untuk melanjutkan. Anda bisa mematikan setelahnya.</string>
<string name="permission_location_setting_button">Aktifkan Lokasi</string>
<string name="qr_code">Kode Batang</string>
<string name="show_qr_code_fullscreen">Tunjukkan Kode Batang Tampilan Penuh</string>
<!-- App Locking -->
<string name="lock_unlock">Buka Biar</string>
<string name="lock_unlock_verbose">Masukkan PIN, pola, atau kata sandi untuk membuka perangkat Anda</string>
<string name="lock_unlock_password">Gunakan kata sandi</string>
<string name="lock_is_locked">Briar terkunci</string>
<string name="lock_tap_to_unlock">Ketuk untuk membuka</string>
<!-- Connections Screen -->
<string name="transports_help_text">Briar bisa tersambung dengan kontak Anda lewat Internet, Wi-Fi, Bluetooth.\n\nSemua akses Internet menggunakan jaringan Tor untuk privasi.\n\nJika salah satu kontak tidak bisa dijangkau melalui beberapa cara, Briar akan menggunakannya secara bersamaan.</string>
<!-- Social Backup Feature -->
<!-- Settings -->
<string name="pref_distributed_backup_title">Pencadangan Sosial</string>
<string name="pref_distributed_backup_summary">Cadangkan akun Anda menggunakan kontak tepercaya</string>
<string name="pref_distributed_old_backup_title">Cadangan Sosial yang Ada</string>
<string name="pref_distributed_old_backup_summary">Informasi tentang pencadangan sosial terbaru Anda</string>
<!-- Social backup setup -->
<string name="select_custodians">Pilih Kontak Tepercaya:</string>
<string name="select_at_least_n_contacts">Pilih setidaknya %d kontak</string>
<string name="select_at_least_n_more_contacts">Harap pilih setidaknya %d kontak lagi</string>
<string name="threshold">Pilih angka minimal kontak tepercaya yang diperlukan untuk mengembalikan akun Anda</string>
<string name="threshold_disabled">Dua kontak tepercaya diperlukan untuk mengembalikan akun Anda</string>
<string name="threshold_secure">Aman</string>
<string name="threshold_recommended">Aman - jejak tumpukan direkomendasikan</string>
<string name="threshold_low_insecure">Tidak Aman - jejak tumpukan lebih tinggi direkomendasikan</string>
<string name="threshold_high_insecure">Bahaya kehilangan ambang lebih rendah direkomendasikan</string>
<string name="threshold_defined">Pilih Ambang</string>
<string name="threshold_m_of_n">%d dari %d kontak diperlukan untuk memulihkan akun Anda</string>
<string name="backup_done_info">Data cadangan dikirim ke kontak tepercaya</string>
<!-- Recovery from the secret owner's POV -->
<string name="recovery_explainer">Anda perlu bertemu langsung kontak tepercaya Anda untuk menerima data</string>
<string name="recovery_explainer_extra">Kontak tepercaya Anda harus memindai kode batang untuk memulai pemindahan.\n\nAnda berdua harus tersambung melalui Wi-Fi yang sama</string>
<string name="recovery_begin">Mulai</string>
<string name="recovery_failed_to_receive">Gagal menerima data cadangan</string>
<string name="recovery_helpful_suggestions">Pastikan Anda berdua tersambung Wi-Fi yang sama dan coba lagi</string>
<string name="recovery_retry">Ulangi</string>
<string name="recovery_recovered_shards">Data cadangan dikembalikan:</string>
<string name="recovery_scan_qr_code">Tunjukkan kode batang</string>
<string name="recovery_recovering_account">Memulihkan akun…</string>
<string name="recovery_shard_received">Data cadangan akun diterima</string>
<string name="recovery_account_recovered">Akun dipulihkan</string>
<string name="recovery_account_recovered_explain">Anda harus membuat kata sandi baru untuk akun Anda sekarang</string>
<string name="recovery_sending_ack">Mengirim pernyataan</string>
<!-- Recovery from the custodian's POV -->
<string name="custodian_recovery_explainer">Anda harus bertemu langsung untuk memindahkan data cadangan</string>
<string name="custodian_recovery_explainer_extra">Pastikan Anda berdua tersambung Wi-Fi yang sama, dan pindai ulang kode batang di perangkat kontak Anda untuk mulai memindahkan data cadangan</string>
<string name="custodian_recovery_failed_to_send">Gagal mengirim data cadangan</string>
<string name="custodian_scan_code">Memindai kode</string>
<string name="custodian_shard_sent">Data cadangan akun dipindahkan</string>
<!-- Titles for the app bar -->
<string name="title_distributed_backup">Pencadangan Sosial</string>
<string name="title_select_custodians">Pilih Kontak Tepercaya</string>
<string name="title_define_threshold">Ambang Batas</string>
<string name="title_recovery_mode">Model Pemulihan</string>
<string name="title_help_recover">Bantu memulihkan akun</string>
<!-- Conversation action for custodian -->
<string name="help_recover_account">Bantu mengembalikan akun</string>
<!-- Setup screen -->
<string name="setup_new_account">Buat akun baru</string>
<string name="setup_restore_account">Mengembalikan akun dari cadangan</string>
<!-- Symbols for visualising threshold values for social backup -->
<string name="filled_bullet">\u25CF</string>
<string name="linear_bullet">\u25CB</string>
<!-- Activity names -->
<string name="activity_name_distributed_backup">Pencadangan Sosial</string>
<string name="activity_name_restore_account">Mengembalikan Akun</string>
<!-- Conversation -->
<string name="social_backup_shard_received">%1$s mengirimi Anda data cadangan sosial.</string>
<string name="social_backup_shard_sent">Anda sudah mengirim data cadangan ke %1$s.</string>
<string name="activity_name_new_or_recover_account">Buat akun baru atau pulihkan akun yang ada</string>
<string name="activity_name_recovery">Memulihkan Akun</string>
<string name="activity_name_custodian_help_recovery">Bantu memulihkan akun</string>
<string name="existing_backup_explain">%d kontak berikut diperlukan untuk mengembalikan akun Anda:</string>
<string name="social_backup_not_enough_contacts">Untuk membuat pencadangan sosial, Anda harus memilih minimal 2 kontak dari daftar kontak Anda</string>
<string name="reading_contacts_error">Ada masalah ketika membaca daftar kontak Anda</string>
<!-- Remote Wipe Feature -->
<!-- Setup -->
<string name="remote_wipe_setup_success">Penghapusan jarak jauh diaktifkan</string>
<string name="remote_wipe_setup_failed">Gagal mengaktifkan penghapusan jarak jauh</string>
<string name="remote_wipe_setup_explain_title">Mengaktifkan fungsi penghapusan jarak jauh</string>
<string name="remote_wipe_setup_explain_long">Anda bisa memilih sejumlah kontak tepercaya yang akan bisa mengaktifkan penghapusan jarak jauh semua data Briar Anda.\nPengahpusan jarak jauh bisa diaktifkan oleh salah satu dari dua kontak.</string>
<!-- Settings menu -->
<string name="pref_remote_wipe_summary">Izinkan kontak tepercaya untuk mengaktifkan penghapusan akun jarak jauh</string>
<string name="pref_remote_wipe_title">Penghapusan Jarak Jauh</string>
<!-- Titles for the app bar -->
<string name="title_select_wipers">Pilih Kontak Tepercaya</string>
<!-- Conversation -->
<string name="remote_wipe_setup_received">%1$s telah ditambahkan sebagai penghapus jarak jauh Anda.</string>
<string name="remote_wipe_setup_sent">Anda sudah menambahkan %1$s sebagai penghapus jarak jauh.</string>
<string name="remote_wipe_wipe_sent">Anda sudah mengirim sinyal mengaktifkan penghapusan jarak jauh kepada %1$s. Sudah kedaluwarsa </string>
<string name="activity_name_remote_wipe">Penghapusan Jarak Jauh</string>
<string name="assigned_wipers">Kontak tepercaya yang ditentukan</string>
<string name="activate_remote_wipe">Mengaktifkan penghapusan jarak jauh</string>
<string name="remote_wipe_revoke_sent">Anda sudah menghapus %1$s sebagai penghapus jarak jauh.</string>
<string name="remote_wipe_revoke_received">Anda sudah tidak bisa mengaktifkan penghapusan jarak jauh kepada %1$s.</string>
<!-- Activate -->
<string name="activity_name_activate_remote_wipe">Aktifkan Penghapusan Jarak Jauh</string>
<string name="remote_wipe_activate_success">Sinyal penghapusan jarak terkirim</string>
<string name="remote_wipe_activate_failure">Gagal mengirimkan sinyal penghapusan jarak jauh</string>
<string name="remote_wipe_activate_button_confirm">Mengaktifkan penghapusan jarak jauh</string>
<string name="remote_wipe_activate_button_cancel">Batal</string>
<string name="remote_wipe_activate_explain_short">Mengaktifkan penghapusan jarak jauh kepada %1$s</string>
<string name="remote_wipe_activate_explain_long">Jika dikonfirmasi oleh kontak kedua, mengirim sinyal ini akan menghapus semua data Briar dari perangkat %1$s\.</string>
<!-- Revoke -->
<string name="activity_name_revoke_remote_wipe">Cabut Penghapusan Jarak Jauh</string>
<string name="revoke_remote_wipe">Cabut Penghapusan Status Jarak Jauh</string>
<string name="remote_wipe_revoke_success">Penghapusan Status Jarak Jauh Tercabut</string>
<string name="remote_wipe_modify_contacts">Ubah Penghapus Jarak Jauh</string>
<string name="button_confirm">Oke</string>
</resources>

View File

@@ -32,6 +32,7 @@
<item>he</item>
<item>hi</item>
<item>hu</item>
<item>in</item>
<item>is</item>
<item>it</item>
<item>ja</item>

View File

@@ -9,7 +9,7 @@
<string name="setup_name_explanation">Your nickname will be shown next to any content you post. You can\'t change it after creating your account.</string>
<string name="setup_next">Next</string>
<string name="setup_password_intro">Choose a Password</string>
<string name="setup_password_explanation">Your Briar account is stored encrypted on your device, not in the cloud. If you forget your password or uninstall Briar, you can only recover your account if you have made a social backup.\n\nChoose a long password that\'s hard to guess, such as four random words, or ten random letters, numbers and symbols.</string>
<string name="setup_password_explanation">Your Briar account is stored encrypted on your device, not in the cloud. If you forget your password or uninstall Briar, your account will be lost.\n\nTo avoid this, use the \'Social Backup\' feature in settings menu to make a backup.</string>
<string name="setup_doze_title">Background Connections</string>
<string name="setup_doze_intro">To receive messages, Briar needs to stay connected in the background.</string>
<string name="setup_doze_explanation">To receive messages, Briar needs to stay connected in the background. Please disable battery optimizations so Briar can stay connected.</string>
@@ -641,36 +641,41 @@
<!-- This is a message to be used in screenshots. -->
<string name="screenshot_message_3">No problem, hope you like it 😀</string>
<!-- social backup -->
<!-- settings -->
<!-- Social Backup Feature -->
<!-- Settings -->
<string name="pref_distributed_backup_title">Social backup</string>
<string name="pref_distributed_backup_summary">Backup your account using trusted contacts</string>
<string name="pref_distributed_old_backup_title">Existing Social backup</string>
<string name="pref_distributed_old_backup_summary">Information about your most recent social backup</string>
<!-- social backup procedure -->
<string name="select_custodians">Select Trusted Contacts:</string>
<!-- Social backup setup -->
<string name="select_custodians">Select Trusted Contacts</string>
<string name="select_at_least_n_contacts">Please select at least %d contacts</string>
<string name="select_at_least_n_more_contacts">Please select at least %d more contacts</string>
<string name="select_no_more_than_n_contacts">Too many! Please select no more than %d contacts</string>
<string name="threshold">Choose the minimum number of trusted contacts needed to restore your account</string>
<string name="threshold">Set the minimum number of trusted contacts needed</string>
<string name="threshold_disabled">Two trusted contacts will be needed to restore your account</string>
<string name="threshold_secure">Secure</string>
<string name="threshold_recommended">Secure - recommended threshold</string>
<string name="threshold_low_insecure">Insecure higher threshold recommended</string>
<string name="threshold_high_insecure">Danger of loss lower threshold recommended</string>
<string name="threshold_too_few_custodians">Danger of loss - more contacts recommended</string>
<string name="threshold_defined">Choose Threshold</string>
<string name="threshold_defined">Choose Minimum Needed</string>
<string name="threshold_m_of_n">%d of %d contacts needed to recover your account</string>
<!-- Recovery from the secret owner's POV -->
<string name="backup_created">Social Backup created</string>
<string name="backup_done_info">Backup pieces sent to trusted contacts</string>
<string name="backup_created">Backup created 1/6/2020</string>
<string name="social_backup_setup_explainer_title">Backup your Briar identity and contacts list</string>
<string name="social_backup_setup_explainer_long">Choose a set of trusted contacts to send backup pieces to.\n\nYou decide how many of these contacts must help you recover your account.\n\nFor example, you can choose three trusted contacts and that any two of them are needed to recover.</string>
<string name="social_backup_setup_explainer_button">Choose trusted contacts</string>
<string name="social_backup_onboarding_title">Backup your Briar account</string>
<string name="social_backup_onboarding_long">Social backup feature allows you to recover your account with the help of trusted contacts</string>
<!-- recovery from the secret owner's POV -->
@@ -688,48 +693,95 @@
<string name="recovery_account_recovered_explain">You must now set a new password for your account</string>
<string name="recovery_sending_ack">Sending acknowledgement</string>
<!-- recovery from the custodian's POV -->
<!-- Recovery from the custodian's POV -->
<string name="custodian_recovery_explainer">You need to meet in-person to transfer backup piece</string>
<string name="custodian_recovery_explainer_extra">Make sure you are both connected to the same wifi network, and scan the QR code on your contact\'s device to begin transferring the backup piece</string>
<string name="custodian_recovery_failed_to_send">Failed to send backup piece</string>
<string name="custodian_scan_code">Scan code</string>
<string name="custodian_shard_sent">Account backup piece transmitted</string>
<!-- titles for the app bar -->
<!-- Titles for the app bar -->
<string name="title_distributed_backup">Social Backup</string>
<string name="title_select_custodians">Select Trusted Contacts</string>
<string name="title_define_threshold">Threshold</string>
<string name="title_define_threshold">Minimum Needed</string>
<string name="title_recovery_mode">Recovery Mode</string>
<string name="title_help_recover">Help recover account</string>
<!-- conversation action for custodian -->
<!-- Conversation action for custodian -->
<string name="help_recover_account">Help recover account</string>
<!-- setup screen -->
<!-- Setup screen -->
<string name="setup_new_account">Create new account</string>
<string name="setup_restore_account">Restore account from backup</string>
<!-- Symbols for visualising threshold values for social backup -->
<string name="filled_bullet">\u25CF</string>
<string name="linear_bullet">\u25CB</string>
<!-- activity names -->
<!-- Activity names -->
<string name="activity_name_distributed_backup">Social Backup</string>
<string name="activity_name_restore_account">Restore Account</string>
<!-- conversation -->
<!-- Conversation -->
<string name="social_backup_shard_received">%1$s has sent you a social backup piece.</string>
<string name="social_backup_shard_sent">You have sent a social backup piece to %1$s.</string>
<string name="activity_name_new_or_recover_account">Create new account or recover existing account</string>
<string name="activity_name_recovery">Recover Account</string>
<string name="activity_name_custodian_help_recovery">Help recover account</string>
<string name="existing_backup_explain">%d of the following contacts are needed to restore your account:</string>
<string name="existing_backup_explain">Any %d of the following contacts are needed to restore your Briar account, should you lose access to it.</string>
<string name="social_backup_not_enough_contacts">To make a social backup, you need at least 2 contacts in your contacts list</string>
<string name="reading_contacts_error">There was an error reading your contacts list</string>
<!-- Display existing backup -->
<string name="social_backup_trusted_contacts">Trusted Contacts</string>
<!-- Remote Wipe Feature -->
<!-- Setup -->
<string name="remote_wipe_setup_success">Remote wipe is set up</string>
<string name="remote_wipe_setup_failed">Failed to set up remote wipe</string>
<string name="remote_wipe_setup_explain_title">Setup remote wipe function</string>
<string name="remote_wipe_setup_explain_long">You can choose a set of trusted contacts who are able to activate a remote wipe of all Briar data.\nThe wipe may be activated by any two contacts from the set.</string>
<string name="remote_wipe_display_explain">Any two of these trusted contacts may activate a wipe of all Briar data from your device.</string>
<!-- Settings menu -->
<string name="pref_remote_wipe_summary">Allow trusted contacts to activate an account wipe remotely</string>
<string name="pref_remote_wipe_title">Remote Wipe</string>
<!-- Titles for the app bar -->
<string name="title_select_wipers">Select Trusted Contacts</string>
<!-- Conversation -->
<string name="remote_wipe_setup_received">%1$s has added you as a remote wiper.</string>
<string name="remote_wipe_setup_sent">You have added %1$s as a remote wiper.</string>
<string name="remote_wipe_wipe_sent">You have sent an activate remote wipe signal to %1$s. It expires </string>
<string name="activity_name_remote_wipe">Remote Wipe</string>
<string name="assigned_wipers">Your assigned trusted wipers</string>
<string name="activate_remote_wipe">Activate remote wipe</string>
<string name="remote_wipe_revoke_sent">You have removed %1$s as a remote wiper.</string>
<string name="remote_wipe_revoke_received">You can no longer activate a remote wipe for %1$s.</string>
<!-- Activate -->
<string name="activity_name_activate_remote_wipe">Activate Remote Wipe</string>
<string name="remote_wipe_activate_success">Remote wipe signal sent</string>
<string name="remote_wipe_activate_failure">Failed to send remote wipe signal</string>
<string name="remote_wipe_activate_button_confirm">Activate remote wipe</string>
<string name="remote_wipe_activate_button_cancel">Cancel</string>
<string name="remote_wipe_activate_explain_short">Activate a remote wipe for %1$s</string>
<string name="remote_wipe_activate_explain_long">If confirmed by a second contact, sending this signal will remove all Briar data from %1$s\'s device.</string>
<!-- Revoke -->
<string name="activity_name_revoke_remote_wipe">Revoke Remote Wipe</string>
<string name="revoke_remote_wipe">Revoke remote wipe status</string>
<string name="remote_wipe_revoke_success">Remote wipe status revoked</string>
<string name="remote_wipe_modify_contacts">Change remote wipers</string>
<string name="remote_wipe_disable">Disable remote wipe</string>
<string name="remote_wipe_disable_success">Remote wipe is disabled</string>
<string name="remote_wipe_disable_success_explain">None of your contacts are able to activate a wipe.</string>
<string name="remote_wipe_confirm_received">Briar data has been wiped from %1$s\'s device. They will be unreachable until they recover their account.</string>
<string name="button_confirm">Ok</string>
</resources>

View File

@@ -65,6 +65,12 @@
<item name="android:minWidth">@dimen/button_size</item>
</style>
<style name="BriarButtonFlat.Negative.Tiny" parent="BriarButtonFlat.Negative">
<item name="android:textSize">@dimen/text_size_tiny</item>
<item name="android:padding">@dimen/margin_medium</item>
<item name="android:minWidth">@dimen/button_size</item>
</style>
<style name="Divider">
<item name="android:background">@color/divider</item>
</style>

View File

@@ -96,7 +96,18 @@
app:iconSpaceReserved="false">
<intent
android:targetClass="org.briarproject.briar.android.socialbackup.DistributedBackupActivity"
android:targetClass="org.briarproject.briar.android.socialbackup.SocialBackupSetupActivity"
android:targetPackage="@string/app_package" />
</Preference>
<Preference
android:summary="@string/pref_remote_wipe_summary"
android:title="@string/pref_remote_wipe_title"
app:iconSpaceReserved="false">
<intent
android:targetClass="org.briarproject.briar.android.remotewipe.RemoteWipeSetupActivity"
android:targetPackage="@string/app_package" />
</Preference>

View File

@@ -67,36 +67,36 @@ dependencyVerification {
'cglib:cglib:3.2.8:cglib-3.2.8.jar:3f64de999ecc5595dc84ca8ff0879d8a34c8623f9ef3c517a53ed59023fcb9db',
'classworlds:classworlds:1.1-alpha-2:classworlds-1.1-alpha-2.jar:2bf4e59f3acd106fea6145a9a88fe8956509f8b9c0fdd11eb96fee757269e3f3',
'com.almworks.sqlite4java:sqlite4java:0.282:sqlite4java-0.282.jar:9e1d8dd83ca6003f841e3af878ce2dc7c22497493a7bb6d1b62ec1b0d0a83c05',
'com.android.tools.analytics-library:protos:27.1.1:protos-27.1.1.jar:13f77e73762e58ab372d140b3a6be6903aea9775b62dd14fbc62d4cc7069c9a4',
'com.android.tools.analytics-library:shared:27.1.1:shared-27.1.1.jar:82930a52001410e97d809930b670f4de3002286975f046b9de5f6b777b06d366',
'com.android.tools.analytics-library:tracker:27.1.1:tracker-27.1.1.jar:31bc5a00be0055bac89c9b2f34751883e987cd89e3ac1783720645c164f591d9',
'com.android.tools.analytics-library:protos:27.2.2:protos-27.2.2.jar:02482564443c294dfe87c5f2b25387f724a698a09ed58e0cf0127400caa35a19',
'com.android.tools.analytics-library:shared:27.2.2:shared-27.2.2.jar:0efe017ca17ee775c5af386475a09799a1282faa04821d54810c1a34f6348d9c',
'com.android.tools.analytics-library:tracker:27.2.2:tracker-27.2.2.jar:62489d84192dc06219664945c43201654ff85c3b715f46550751512a880d0e39',
'com.android.tools.build:aapt2-proto:4.1.0-alpha01-6193524:aapt2-proto-4.1.0-alpha01-6193524.jar:17e75523e1e92dd4f222c7368ee41df9e964a508232f591e265d0c499baf9dca',
'com.android.tools.build:apksig:4.1.1:apksig-4.1.1.jar:e0a69da9e5a03986d608b45bbf954ef0e6a0b3f58c1b8315bd169ec08b279e72',
'com.android.tools.build:apkzlib:4.1.1:apkzlib-4.1.1.jar:ba4b5e419b6be0130eae7f8301c3a551ad3976f487d2e0c6852ebb175ac41127',
'com.android.tools.build:builder-model:4.1.1:builder-model-4.1.1.jar:e95c99cc298ad67b8deb6ced99c51abc8f59afebedad044b1a10dde14646a4dd',
'com.android.tools.build:builder-test-api:4.1.1:builder-test-api-4.1.1.jar:464f596ab261c051c3847406748e843770dea123f6fa5fee8a9390644e709b7a',
'com.android.tools.build:builder:4.1.1:builder-4.1.1.jar:0f78d4759d2f7b57b95865522ec34596ba419b9982f3b25e3449213f9c98b80d',
'com.android.tools.build:gradle-api:4.1.1:gradle-api-4.1.1.jar:d42e6b539e4c1353ad3546e75ec8ce11a017b97481023e8ea18577eefe374358',
'com.android.tools.build:manifest-merger:27.1.1:manifest-merger-27.1.1.jar:7a45fa143687859bb2e5a961dcf6ee88094d3853de0cb543dc03dbcb0f4b554b',
'com.android.tools.ddms:ddmlib:27.1.1:ddmlib-27.1.1.jar:da6e4bd834b6a85dae8019039849d8bd96933347dfbf460df74913ddade6e40a',
'com.android.tools.external.com-intellij:intellij-core:27.1.1:intellij-core-27.1.1.jar:2591a7363c4443c59bf9f793730acafce9d6ec3076e2f46716edaf53a41b6fb6',
'com.android.tools.external.com-intellij:kotlin-compiler:27.1.1:kotlin-compiler-27.1.1.jar:5054ae770ba788f110303c65abd6b1fa28eccf52dee1274510e201b2b81885c8',
'com.android.tools.external.org-jetbrains:uast:27.1.1:uast-27.1.1.jar:54cd8f6886a9d2f5641659dd5c91f626629672cd48301f7f0bd6aad9bd448714',
'com.android.tools.layoutlib:layoutlib-api:27.1.1:layoutlib-api-27.1.1.jar:8a9a22e3b309521ea83b724e5a89cfdac6076f52d675c0e17d77b05527bc0f8c',
'com.android.tools.lint:lint-api:27.1.1:lint-api-27.1.1.jar:c1d8176094cb0478786070d40533efb578ebc53529a82f6ef5bee879bdca418b',
'com.android.tools.lint:lint-checks:27.1.1:lint-checks-27.1.1.jar:3899c91e00bd059b40c31a9ca00cd0f8303191947608735ae1b657323693fb61',
'com.android.tools.lint:lint-gradle-api:27.1.1:lint-gradle-api-27.1.1.jar:26aa89d38b9825cc73229daa82a68875801c8b8491f30497ce62aff1f206eb0d',
'com.android.tools.lint:lint-gradle:27.1.1:lint-gradle-27.1.1.jar:f7355823ead869f4d28184ba28b7a0c693b507519a2d3705bb9848a0f35b3756',
'com.android.tools.lint:lint-model:27.1.1:lint-model-27.1.1.jar:bc23c0c413bdfca59dac2cd56b870d8360d009e9ec0d365e71f774bcf127971d',
'com.android.tools.lint:lint:27.1.1:lint-27.1.1.jar:2f6038a5398a42bd591883c3f5e5894f4ec52ca1c3683bf94fa8553c1700af81',
'com.android.tools:annotations:27.1.1:annotations-27.1.1.jar:ff28c504d2acb9fd1a5ffbd97ae85cf59ee18c76927525aad250509bccf2cab1',
'com.android.tools:common:27.1.1:common-27.1.1.jar:63d9a2a9ad6d278db319f3749b9f50bdf5457ef7020074a1bebe124e714b535c',
'com.android.tools:dvlib:27.1.1:dvlib-27.1.1.jar:998a54201fc1cefee5f2399215e95c42b1f64f9e1d8f4452eb8255c68ba5440f',
'com.android.tools:repository:27.1.1:repository-27.1.1.jar:d25b74ccabf4d876903efb375e9af6fb380d8ae0445bb74bbdcc225c1e37fa1d',
'com.android.tools:sdk-common:27.1.1:sdk-common-27.1.1.jar:4473ae97d0ef7061ee1de61041d5aa97405ae08e44c09cf7bb278b42e4b97c7c',
'com.android.tools:sdklib:27.1.1:sdklib-27.1.1.jar:08e6b83961ac9724b3c1e3d0eff971f13be6701292c77914b8794480f3391250',
'com.android:signflinger:4.1.1:signflinger-4.1.1.jar:0c66825988873ec2d51057fa463f54a8f18fc7326ff4530b9da363b71e97ce60',
'com.android:zipflinger:4.1.1:zipflinger-4.1.1.jar:0a8c3e52ac13dd031236f9fb5ba4408b1d5dcd12325a05440b36da09d8881446',
'com.android.tools.build:apksig:4.2.2:apksig-4.2.2.jar:632690bf641b429dcb31650e6b2f6a2e87c4ac8afd45a6ba3cbc99fb1612178f',
'com.android.tools.build:apkzlib:4.2.2:apkzlib-4.2.2.jar:3b5167c1265e97f65201c4d2be6a6f72165a3aa2fe9e0594a59b67af9e9e97b9',
'com.android.tools.build:builder-model:4.2.2:builder-model-4.2.2.jar:41868de0cb88ae70b828eee4191c13e0233f433abb1becdf6a2bd391bd446bc0',
'com.android.tools.build:builder-test-api:4.2.2:builder-test-api-4.2.2.jar:2f305c6d3a7b637d736b821bad372dcabd959e979f2065a9f65bac1e7b4d1875',
'com.android.tools.build:builder:4.2.2:builder-4.2.2.jar:40fedd0d16db8f34ddb4eaf812d966b90ef1764f65cf119030442823bcf995cd',
'com.android.tools.build:gradle-api:4.2.2:gradle-api-4.2.2.jar:dd4ef35bbbfb8fc2d20e3311c76b516bc1672e82b61cb3a59fc877da0f9b4f61',
'com.android.tools.build:manifest-merger:27.2.2:manifest-merger-27.2.2.jar:971974756f32d9e94c857d92772b1499b0b0f5d9c70cb8ebbd20d9bbf804a923',
'com.android.tools.ddms:ddmlib:27.2.2:ddmlib-27.2.2.jar:9ab0f9b58737c316af454184705854c75936ca3531f21acc29bd68a3343334d1',
'com.android.tools.external.com-intellij:intellij-core:27.2.2:intellij-core-27.2.2.jar:01619d5dc28ec909cbdee699f1f13056e84462faf6dccf4817561293fb28bef0',
'com.android.tools.external.com-intellij:kotlin-compiler:27.2.2:kotlin-compiler-27.2.2.jar:71bd460199ce7293ecc54b91a115319c1e4b585eca5a5b3699f6a406f29e626c',
'com.android.tools.external.org-jetbrains:uast:27.2.2:uast-27.2.2.jar:efa59302fd433015e993143530cecb456b63d10d0b89bd1d3b1a016904338a65',
'com.android.tools.layoutlib:layoutlib-api:27.2.2:layoutlib-api-27.2.2.jar:f0901f2295d814e82ad95850ea2103dd89d8489e01727fafa55ccccc0dccd163',
'com.android.tools.lint:lint-api:27.2.2:lint-api-27.2.2.jar:1ecb5959c8e624ee49cdf9178de67bb0e823b4382ed253410eb36afe5c458b05',
'com.android.tools.lint:lint-checks:27.2.2:lint-checks-27.2.2.jar:989e545a6b5e398e63a9f3608da02d6111f2241faec1baa0a3b4492cb03aeaf2',
'com.android.tools.lint:lint-gradle-api:27.2.2:lint-gradle-api-27.2.2.jar:2be9c69d6fbbfb012ff6521fdfcb22eb7cfaa57d108e07bb1d4143dae9c1b433',
'com.android.tools.lint:lint-gradle:27.2.2:lint-gradle-27.2.2.jar:742dedd5ccb459a245a35bf4fa16dfecc762da1a6b1741332cfe5228e812301a',
'com.android.tools.lint:lint-model:27.2.2:lint-model-27.2.2.jar:ee31012586462bea2d591b6175934e5f29b6f781a78fda50f79387972364b9ab',
'com.android.tools.lint:lint:27.2.2:lint-27.2.2.jar:7247016af7fba8cabee6ae887515b144f5a2ff7823422654daf23be9202f8fb1',
'com.android.tools:annotations:27.2.2:annotations-27.2.2.jar:9375fb2df5c0cf1b46fef9e65b3a27ac88925ccf90054b19ae0ca0adc7036fe1',
'com.android.tools:common:27.2.2:common-27.2.2.jar:a76f4e10cad39bed317be031fee915d280aa8bc11616c58ab94e051b1e38769d',
'com.android.tools:dvlib:27.2.2:dvlib-27.2.2.jar:9931c6b57460b5f8cc2613ca5ff8596aa089a67655ace13d173f90538ecb4301',
'com.android.tools:repository:27.2.2:repository-27.2.2.jar:ac5f9b19dc5d9d08e80b57da76059f5760ca76c221e40ffd4bf43d7b13991674',
'com.android.tools:sdk-common:27.2.2:sdk-common-27.2.2.jar:b147acc13850808d61fc391ccfeeebdf90841b461a7042acb2d92e466da8e674',
'com.android.tools:sdklib:27.2.2:sdklib-27.2.2.jar:fae0bafbe8b4f546cf64986a22b7d8ed108d45519366ff22f0170a9cf3ea7f34',
'com.android:signflinger:4.2.2:signflinger-4.2.2.jar:4d7aafd9666707b483b1ad2c466824287cf2e379dda1d204dd3b7e453ffcf760',
'com.android:zipflinger:4.2.2:zipflinger-4.2.2.jar:8e4677086c9a8f4a67374a4edc31db7e481f0d9b85907263c51ca72452c23a93',
'com.github.bumptech.glide:annotations:4.11.0:annotations-4.11.0.jar:d219d238006d824962176229d4708abcdddcfe342c6a18a5d0fa48d6f0479b3e',
'com.github.bumptech.glide:compiler:4.11.0:compiler-4.11.0.jar:a98cdf265c36261b1d523448b05c322ec290afa865946425eded6361980e8770',
'com.github.bumptech.glide:gifdecoder:4.11.0:gifdecoder-4.11.0.aar:197a1cd5b76855aa02b230c13974e293229b901dc2b96fab4315201e78baa804',
@@ -110,7 +110,6 @@ dependencyVerification {
'com.google.auto:auto-common:0.8:auto-common-0.8.jar:97db1709f57b91b32edacb596ef4641872f227b7d99ad90e467f0d77f5ba134a',
'com.google.code.findbugs:annotations:3.0.1:annotations-3.0.1.jar:6b47ff0a6de0ce17cbedc3abb0828ca5bce3009d53ea47b3723ff023c4742f79',
'com.google.code.findbugs:jsr305:3.0.2:jsr305-3.0.2.jar:766ad2a0783f2687962c8ad74ceecc38a28b9f72a2d085ee438b7813e928d0c7',
'com.google.code.gson:gson:2.8.5:gson-2.8.5.jar:233a0149fc365c9f6edbd683cfe266b19bdc773be98eabdaf6b3c924b48e7d81',
'com.google.code.gson:gson:2.8.6:gson-2.8.6.jar:c8fb4839054d280b3033f800d1f5a97de2f028eb8ba2eb458ad287e536f3f25f',
'com.google.dagger:dagger-compiler:2.24:dagger-compiler-2.24.jar:3c5afb955fb188da485cb2c048eff37dce0e1530b9780a0f2f7187d16d1ccc1f',
'com.google.dagger:dagger-producers:2.24:dagger-producers-2.24.jar:f10f45b95191954d5d6b043fca9e62fb621d21bf70634b8f8476c7988b504c3a',
@@ -136,13 +135,12 @@ dependencyVerification {
'com.googlecode.json-simple:json-simple:1.1:json-simple-1.1.jar:2d9484f4c649f708f47f9a479465fc729770ee65617dca3011836602264f6439',
'com.ibm.icu:icu4j:53.1:icu4j-53.1.jar:e37a4467bac5cdeb02c5c4b8e5063d2f4e67b69e3c7df6d6b610f13185572bab',
'com.jraska:falcon:2.1.1:falcon-2.1.1.aar:827f06556b7fa599f29a48a5277df39ca3dce5080d4ea6f9ea1f9c7b6b78bb7a',
'com.madgag.spongycastle:core:1.58.0.0:core-1.58.0.0.jar:199617dd5698c5a9312b898c0a4cec7ce9dd8649d07f65d91629f58229d72728',
'com.squareup:javapoet:1.11.1:javapoet-1.11.1.jar:9cbf2107be499ec6e95afd36b58e3ca122a24166cdd375732e51267d64058e90',
'com.squareup:javawriter:2.1.1:javawriter-2.1.1.jar:f699823d0081f69cbb676c1845ea222e0ada79bc88a53e5d22d8bd02d328f57e',
'com.squareup:javawriter:2.5.0:javawriter-2.5.0.jar:fcfb09fb0ea0aa97d3cfe7ea792398081348e468f126b3603cb3803f240197f0',
'com.sun.activation:javax.activation:1.2.0:javax.activation-1.2.0.jar:993302b16cd7056f21e779cc577d175a810bb4900ef73cd8fbf2b50f928ba9ce',
'com.sun.istack:istack-commons-runtime:3.0.7:istack-commons-runtime-3.0.7.jar:6443e10ba2e259fb821d9b6becf10db5316285fc30c53cec9d7b19a3877e7fdf',
'com.sun.xml.fastinfoset:FastInfoset:1.2.15:FastInfoset-1.2.15.jar:785861db11ca1bd0d1956682b974ad73eb19cd3e01a4b3fa82d62eca97210aec',
'com.sun.istack:istack-commons-runtime:3.0.8:istack-commons-runtime-3.0.8.jar:4ffabb06be454a05e4398e20c77fa2b6308d4b88dfbef7ca30a76b5b7d5505ef',
'com.sun.xml.fastinfoset:FastInfoset:1.2.16:FastInfoset-1.2.16.jar:056f3a1e144409f21ed16afc26805f58e9a21f3fce1543c42d400719d250c511',
'com.vanniktech:emoji-google:0.6.0:emoji-google-0.6.0.aar:029d6a954cebfe3f0a5bac0c9539a054fa7db2e1272d006a8f0e850f3794d44b',
'com.vanniktech:emoji:0.6.0:emoji-0.6.0.aar:a5fcde58902305c004f03c6dc2241e718400ac4162226079791d87fac83ef639',
'commons-codec:commons-codec:1.10:commons-codec-1.10.jar:4241dfa94e711d435f29a4604a3e2de5c4aa3c165e23bd066be6fc1fc4309569',
@@ -150,12 +148,12 @@ dependencyVerification {
'de.hdodenhof:circleimageview:3.0.1:circleimageview-3.0.1.aar:7b0f088436ad4dcbb36d779fd09bf2192d9cc1e1a734bb6337904a7648f97617',
'info.guardianproject.panic:panic:1.0:panic-1.0.jar:35116ab95212e67f94577faf67b88c11a6b21cbf9178b3f5b51d3dff45203ffd',
'info.guardianproject.trustedintents:trustedintents:0.2:trustedintents-0.2.jar:6221456d8821a8d974c2acf86306900237cf6afaaa94a4c9c44e161350f80f3e',
'it.unimi.dsi:fastutil:7.2.0:fastutil-7.2.0.jar:74fa208043740642f7e6eb09faba15965218ad2f50ce3020efb100136e4b591c',
'javax.activation:javax.activation-api:1.2.0:javax.activation-api-1.2.0.jar:43fdef0b5b6ceb31b0424b208b930c74ab58fac2ceeb7b3f6fd3aeb8b5ca4393',
'it.unimi.dsi:fastutil:8.4.0:fastutil-8.4.0.jar:2ad2824a4a0a0eb836b52ee2fc84ba2134f44bce7bfa54015ae3f31c710a3071',
'jakarta.activation:jakarta.activation-api:1.2.1:jakarta.activation-api-1.2.1.jar:8b0a0f52fa8b05c5431921a063ed866efaa41dadf2e3a7ee3e1961f2b0d9645b',
'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2:jakarta.xml.bind-api-2.3.2.jar:69156304079bdeed9fc0ae3b39389f19b3cc4ba4443bc80508995394ead742ea',
'javax.annotation:javax.annotation-api:1.3.2:javax.annotation-api-1.3.2.jar:e04ba5195bcd555dc95650f7cc614d151e4bcd52d29a10b8aa2197f3ab89ab9b',
'javax.annotation:jsr250-api:1.0:jsr250-api-1.0.jar:a1a922d0d9b6d183ed3800dfac01d1e1eb159f0e8c6f94736931c1def54a941f',
'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff',
'javax.xml.bind:jaxb-api:2.3.1:jaxb-api-2.3.1.jar:88b955a0df57880a26a74708bc34f74dcaf8ebf4e78843a28b50eae945732b06',
'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
'junit:junit:4.13.1:junit-4.13.1.jar:c30719db974d6452793fe191b3638a5777005485bae145924044530ffa5f6122',
'nekohtml:nekohtml:1.9.6.2:nekohtml-1.9.6.2.jar:fdff6cfa9ed9cc911c842a5d2395f209ec621ef1239d46810e9e495809d3ae09',
@@ -163,7 +161,9 @@ dependencyVerification {
'net.bytebuddy:byte-buddy-agent:1.10.20:byte-buddy-agent-1.10.20.jar:b592a6c43e752bf41659717956c57fbb790394d2ee5f8941876659f9c5c0e7e8',
'net.bytebuddy:byte-buddy:1.10.20:byte-buddy-1.10.20.jar:5fcad05da791e9a22811c255a4a74b7ea094b7243d9dbf3e6fc578c8c94290ac',
'net.i2p.crypto:eddsa:0.2.0:eddsa-0.2.0.jar:a7cb1b85c16e2f0730b9204106929a1d9aaae1df728adc7041a8b8b605692140',
'net.java.dev.jna:jna-platform:5.6.0:jna-platform-5.6.0.jar:9ecea8bf2b1b39963939d18b70464eef60c508fed8820f9dcaba0c35518eabf7',
'net.java.dev.jna:jna:5.5.0:jna-5.5.0.aar:12ef4a3c2ea685c9c816caa6a77ae8f17bb7727d8460f249925409acda270101',
'net.java.dev.jna:jna:5.6.0:jna-5.6.0.jar:5557e235a8aa2f9766d5dc609d67948f2a8832c2d796cea9ef1d6cbe0b3b7eaf',
'net.jcip:jcip-annotations:1.0:jcip-annotations-1.0.jar:be5805392060c71474bf6c9a67a099471274d30b83eef84bfc4e0889a4f1dcc0',
'net.ltgt.gradle.incap:incap:0.2:incap-0.2.jar:b625b9806b0f1e4bc7a2e3457119488de3cd57ea20feedd513db070a573a4ffd',
'net.sf.jopt-simple:jopt-simple:4.9:jopt-simple-4.9.jar:26c5856e954b5f864db76f13b86919b59c6eecf9fd930b96baa8884626baf2f5',
@@ -190,8 +190,8 @@ dependencyVerification {
'org.apache.maven:maven-repository-metadata:2.2.1:maven-repository-metadata-2.2.1.jar:5fe283f47b0e7f7d95a4252af3fa7a0db4d8f080cd9df308608c0472b8f168a1',
'org.apache.maven:maven-settings:2.2.1:maven-settings-2.2.1.jar:9a9f556713a404e770c9dbdaed7eb086078014c989291960c76fdde6db4192f7',
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.52:bcprov-jdk15on-1.52.jar:0dc4d181e4d347893c2ddbd2e6cd5d7287fc651c03648fa64b2341c7366b1773',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.bouncycastle:bcprov-jdk15on:1.65:bcprov-jdk15on-1.65.jar:e78f96eb59066c94c94fb2d6b5eb80f52feac6f5f9776898634f8addec6e2137',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-compat-qual:2.5.5:checker-compat-qual-2.5.5.jar:11d134b245e9cacc474514d2d66b5b8618f8039a1465cdc55bbc0b34e0008b7a',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
@@ -202,31 +202,31 @@ dependencyVerification {
'org.codehaus.plexus:plexus-container-default:1.0-alpha-9-stable-1:plexus-container-default-1.0-alpha-9-stable-1.jar:7c758612888782ccfe376823aee7cdcc7e0cdafb097f7ef50295a0b0c3a16edf',
'org.codehaus.plexus:plexus-interpolation:1.11:plexus-interpolation-1.11.jar:fd9507feb858fa620d1b4aa4b7039fdea1a77e09d3fd28cfbddfff468d9d8c28',
'org.codehaus.plexus:plexus-utils:1.5.15:plexus-utils-1.5.15.jar:2ca121831e597b4d8f2cb22d17c5c041fc23a7777ceb6bfbdd4dfb34bbe7d997',
'org.glassfish.jaxb:jaxb-runtime:2.3.1:jaxb-runtime-2.3.1.jar:45fecfa5c8217ce1f3652ab95179790ec8cc0dec0384bca51cbeb94a293d9f2f',
'org.glassfish.jaxb:txw2:2.3.1:txw2-2.3.1.jar:34975dde1c6920f1a39791142235689bc3cd357e24d05edd8ff93b885bd68d60',
'org.glassfish.jaxb:jaxb-runtime:2.3.2:jaxb-runtime-2.3.2.jar:e6e0a1e89fb6ff786279e6a0082d5cef52dc2ebe67053d041800737652b4fd1b',
'org.glassfish.jaxb:txw2:2.3.2:txw2-2.3.2.jar:4a6a9f483388d461b81aa9a28c685b8b74c0597993bf1884b04eddbca95f48fe',
'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
'org.hamcrest:hamcrest-core:2.1:hamcrest-core-2.1.jar:e09109e54a289d88506b9bfec987ddd199f4217c9464132668351b9a4f00bee9',
'org.hamcrest:hamcrest-integration:1.3:hamcrest-integration-1.3.jar:70f418efbb506c5155da5f9a5a33262ea08a9e4d7fea186aa9015c41a7224ac2',
'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
'org.hamcrest:hamcrest-library:2.1:hamcrest-library-2.1.jar:b7e2b6895b3b679f0e47b6380fda391b225e9b78505db9d8bdde8d3cc8d52a21',
'org.hamcrest:hamcrest:2.1:hamcrest-2.1.jar:ba93b2e3a562322ba432f0a1b53addcc55cb188253319a020ed77f824e692050',
'org.jetbrains.kotlin:kotlin-reflect:1.3.72:kotlin-reflect-1.3.72.jar:a188d9367de1c4ee9479db630985c0597b20709c83161b1430d24edb27e38c40',
'org.jetbrains.intellij.deps:trove4j:1.0.20181211:trove4j-1.0.20181211.jar:affb7c85a3c87bdcf69ff1dbb84de11f63dc931293934bc08cd7ab18de083601',
'org.jetbrains.kotlin:kotlin-reflect:1.4.31:kotlin-reflect-1.4.31.jar:91fad0b42974a7d5811e30a61f05706e176b144235717c6de7e81e3a781028f2',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.50:kotlin-stdlib-common-1.3.50.jar:8ce678e88e4ba018b66dacecf952471e4d7dfee156a8a819760a5a5ff29d323c',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.3.72:kotlin-stdlib-common-1.3.72.jar:5e7d1552863e480c1628b1cc39ce230ef829f5b7230106215a05acda5172203a',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.72:kotlin-stdlib-jdk7-1.3.72.jar:40566c0c08d414b9413ba556ff7f8a0b04b98b9f0f424d122dd2088510efccc4',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72:kotlin-stdlib-jdk8-1.3.72.jar:133da70cfc07b56094282eac5c59bccd59f167ee2ead22e5282876d8bc10bf95',
'org.jetbrains.kotlin:kotlin-stdlib-common:1.4.31:kotlin-stdlib-common-1.4.31.jar:57962f44371a746b678218a0802a8712c6255206de9a69ede215e3aa4b044708',
'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.31:kotlin-stdlib-jdk7-1.4.31.jar:1f966e54e86cf4b7d7014afdce04e0f3ee4625084cda3494edccc7b84af52664',
'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.4.31:kotlin-stdlib-jdk8-1.4.31.jar:b2f8364435ebcb0106ff9d4415a11ffdef8ec7786ee6e5ed465a01556cbd1683',
'org.jetbrains.kotlin:kotlin-stdlib:1.3.50:kotlin-stdlib-1.3.50.jar:e6f05746ee0366d0b52825a090fac474dcf44082c9083bbb205bd16976488d6c',
'org.jetbrains.kotlin:kotlin-stdlib:1.3.72:kotlin-stdlib-1.3.72.jar:3856a7349ebacd6d1be6802b2fed9c4dc2c5a564ea92b6b945ac988243d4b16b',
'org.jetbrains.kotlin:kotlin-stdlib:1.4.31:kotlin-stdlib-1.4.31.jar:76a599d88b167e8ac90879b6daa722c6ad3452ba714c9aba19bd196544b97f1c',
'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.0:kotlinx-coroutines-android-1.3.0.jar:c80aaadf041f044d324a19a73f88879dfd1e4d026b14e3230075ff9081942ae3',
'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.0:kotlinx-coroutines-core-1.3.0.jar:6f3a60fea2403b80385b399952aeb3a4cf0985a45b8da04b6f31825171901a1d',
'org.jetbrains.trove4j:trove4j:20160824:trove4j-20160824.jar:1917871c8deb468307a584680c87a44572f5a8b0b98c6d397fc0f5f86596dbe7',
'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478',
'org.jmock:jmock-imposters:2.12.0:jmock-imposters-2.12.0.jar:3b836269745a137c9b2347e8d7c2104845b126ef04f012d6bfd94f1a7dea7b09',
'org.jmock:jmock-junit4:2.12.0:jmock-junit4-2.12.0.jar:3233062fc889637c151a24f1ee086bad04321ab7d8264fef279daff0fa27205b',
'org.jmock:jmock-legacy:2.12.0:jmock-legacy-2.12.0.jar:dea3a9cca653d082e2fe7e40232e982fe03a9984c7d67ceff24f3e03fe580dcd',
'org.jmock:jmock-testjar:2.12.0:jmock-testjar-2.12.0.jar:efefbcf6cd294d0e29f0c46eb2a3380d4ca4e1763ff719c69e2f2ac62f564a04',
'org.jmock:jmock:2.12.0:jmock-2.12.0.jar:266d07314c0cd343c46ff8a55601272de8cf406807caf55e6f313295f83d10be',
'org.jvnet.staxex:stax-ex:1.8:stax-ex-1.8.jar:95b05d9590af4154c6513b9c5dc1fb2e55b539972ba0a9ef28e9a0c01d83ad77',
'org.jvnet.staxex:stax-ex:1.8.1:stax-ex-1.8.1.jar:20522549056e9e50aa35ef0b445a2e47a53d06be0b0a9467d704e2483ffb049a',
'org.magmacollective.darkcrystal:dark-crystal-key-backup-crypto:1.0.0:dark-crystal-key-backup-crypto-1.0.0.jar:7c808f30314f7bc0c715b53415b07bd7e9a6bbcc55e5f672a296e5298d335f78',
'org.magmacollective.darkcrystal:dark-crystal-secret-sharing-wrapper:1.1.0:dark-crystal-secret-sharing-wrapper-1.1.0.aar:b8cac2348b9e652de413fa587168e9bb6ff36f6eea4bd1c72d3ecd56fc186e09',
'org.magmacollective.darkcrystal:shamir-secret-sharing-jna:1.0.0:shamir-secret-sharing-jna-1.0.0.aar:cdccfaf74dc1fcf30799a45d034c406315ce8507a8f4382eee118a66fb229ced',
@@ -252,5 +252,7 @@ dependencyVerification {
'org.whispersystems:curve25519-java:0.5.0:curve25519-java-0.5.0.jar:0aadd43cf01d11e9b58f867b3c4f25c3194e8b0623d1953d32dfbfbee009e38d',
'tools.fastlane:screengrab:2.0.0:screengrab-2.0.0.aar:15ac15eb7c371db05e721be8d466567c2b7274b767d91478e781b6d89ee5d3d0',
'uk.co.samuelwall:material-tap-target-prompt:3.0.0:material-tap-target-prompt-3.0.0.aar:e4d3c472b2d378e39a6535b7788e6c790fc9dde2d7659974e006ed8c7260911d',
'xerces:xercesImpl:2.12.0:xercesImpl-2.12.0.jar:b50d3a4ca502faa4d1c838acb8aa9480446953421f7327e338c5dda3da5e76d0',
'xml-apis:xml-apis:1.4.01:xml-apis-1.4.01.jar:a840968176645684bb01aed376e067ab39614885f9eee44abe35a5f20ebe7fad',
]
}

View File

@@ -10,6 +10,7 @@ import org.briarproject.briar.api.introduction.IntroductionResponse;
import org.briarproject.briar.api.messaging.PrivateMessageHeader;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationRequest;
import org.briarproject.briar.api.privategroup.invitation.GroupInvitationResponse;
import org.briarproject.briar.api.remotewipe.RemoteWipeMessageHeader;
import org.briarproject.briar.api.socialbackup.ShardMessageHeader;
@NotNullByDefault
@@ -34,4 +35,6 @@ public interface ConversationMessageVisitor<T> {
T visitIntroductionResponse(IntroductionResponse r);
T visitShardMessage(ShardMessageHeader r);
T visitRemoteWipeMessage(RemoteWipeMessageHeader r);
}

View File

@@ -0,0 +1,11 @@
package org.briarproject.briar.api.remotewipe;
public interface MessageEncoder {
byte[] encodeSetupMessage();
byte[] encodeRevokeMessage();
byte[] encodeWipeMessage();
byte[] encodeConfirmMessage();
}

View File

@@ -0,0 +1,12 @@
package org.briarproject.briar.api.remotewipe;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.data.BdfList;
public interface MessageParser {
void parseSetupMessage(BdfList body) throws FormatException;
void parseWipeMessage(BdfList body) throws FormatException;
void parseRevokeMessage(BdfList body) throws FormatException;
}

View File

@@ -0,0 +1,29 @@
package org.briarproject.briar.api.remotewipe;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
@Immutable
@NotNullByDefault
public enum MessageType {
SETUP(0), WIPE(1), REVOKE(2), CONFIRM(3);
private final int value;
MessageType(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static MessageType fromValue(int value) throws
FormatException {
for (MessageType m : values()) if (m.value == value) return m;
throw new FormatException();
}
}

View File

@@ -0,0 +1,14 @@
package org.briarproject.briar.api.remotewipe;
import org.briarproject.bramble.api.event.Event;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.concurrent.Immutable;
/**
* An event which is activated when a critical amount of
* remote wipe messages are received.
*/
@Immutable
@NotNullByDefault
public class RemoteWipeActivatedEvent extends Event {
}

Some files were not shown because too many files have changed in this diff Show More