Compare commits
1058 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b9649a908e | |||
| 2f20f558ad | |||
| 6f868f653a | |||
| 42b529dd4a | |||
| d7eab73687 | |||
| 1deebdf552 | |||
| 20fbb0e1ee | |||
| 6a53e229d1 | |||
| 74ef2d478a | |||
| feeece405d | |||
| 20459a5710 | |||
| a3a8b3581f | |||
| f2571dba91 | |||
| 708ffe617c | |||
| f6ecb94047 | |||
| 2d4b52b037 | |||
| 5257f39aee | |||
| 20f1475856 | |||
| db0295e5a6 | |||
| d019c1bfb5 | |||
| 4542ba1b9a | |||
| 9b982db899 | |||
| a1a72b79b3 | |||
| 0ac9bea63c | |||
| 2bb3ad546e | |||
| 41a6b9a6c9 | |||
| fb7c119afc | |||
| 5910fc245a | |||
| 7d8887eddd | |||
| 37471ae9fa | |||
| 319e2ebe5a | |||
| 49a00f3788 | |||
| 74ee2fb8db | |||
| 29a4a4712c | |||
| 644bd1f594 | |||
| ed6eca8920 | |||
| 47512f786e | |||
| add51186e6 | |||
| 52f63b28ba | |||
| 889c9aab45 | |||
| de5940e709 | |||
| 6e184f735d | |||
| c33ff20d0a | |||
| c67c3c8972 | |||
| f98a5178b3 | |||
| 6dfccdab84 | |||
| 40faa3d43e | |||
| 74f6853815 | |||
| cef6817187 | |||
| 6f547dfb66 | |||
| d6e05f61ac | |||
| 55649b0c4b | |||
| 4d9f8dd244 | |||
| 3880da8a08 | |||
| 5e8666835d | |||
| 2f5619141e | |||
| 4a07d7fd9d | |||
| 1493583db7 | |||
| dc363a0281 | |||
| fcffe3922a | |||
| d546d8041f | |||
| 267caf9b03 | |||
| d55ad1f32a | |||
| be07043b47 | |||
| cc3e6bcd9d | |||
| 43654fdadb | |||
| 774add2380 | |||
| 1133a6e624 | |||
| 0aad1b3d76 | |||
| b58a9d0bab | |||
| 54a74a8586 | |||
| f25474947b | |||
| 9ebd8e4a37 | |||
| 975ad2e149 | |||
| e6350aaec2 | |||
| d373537d6d | |||
| 960581e5f2 | |||
| fccf8f402e | |||
| e0459978f7 | |||
| 72bd7376ca | |||
| 94fbdcde05 | |||
| 89d77e7638 | |||
| d9edee117f | |||
| 6cfdb87924 | |||
| 613940577c | |||
| 43a3e21495 | |||
| b5375b8c0e | |||
| 39aec04fea | |||
| 94e2c8dbed | |||
| da45c7bc1c | |||
| d180704d52 | |||
| 653c8688b7 | |||
| 9a382a4948 | |||
| dcaa19b29d | |||
| 11845da65f | |||
| 82262cb166 | |||
| e85ae5247a | |||
| 74e14bd0ea | |||
| 40cdeee47a | |||
| 844231e5e7 | |||
| 0ccf0a9309 | |||
| 5040fb4634 | |||
| a57122a902 | |||
| 4313e8824b | |||
| 464cba299a | |||
| 102c3fd82a | |||
| dc31eee4bc | |||
| 875f0e5c86 | |||
| 2b36e2dc26 | |||
| 6a9c3ab8ca | |||
| 2ab544b18e | |||
| 2630e22421 | |||
| 1b7e32ab44 | |||
| 8436909977 | |||
| 9dd44c24b3 | |||
| 5d0e85b30d | |||
| 5193dfa412 | |||
| 96490e23f8 | |||
| 7959b07d45 | |||
| c4ae7927ad | |||
| ba0515ebc5 | |||
| 655ed8cad4 | |||
| 349bab9510 | |||
| e26f803d1f | |||
| 60ab7f2826 | |||
| 67d2c89bcc | |||
| e511237e5e | |||
| f249fd6174 | |||
| 6db45c1911 | |||
| 06a1114744 | |||
| 3afff5625b | |||
| cef8ddeedb | |||
| 2f0ac973c0 | |||
| 9465776715 | |||
| 39685a575d | |||
| 8601736387 | |||
| 98d8572baf | |||
| 917e764b6f | |||
| 52263150c8 | |||
| c2aba94b34 | |||
| 1278dfd395 | |||
| 44a688470f | |||
| e9a09d9c72 | |||
| abc49a3b95 | |||
| cdd4e5eccd | |||
| fa8ed2b881 | |||
| 0731fe9447 | |||
| d3567d9f0c | |||
| 66ab1f8051 | |||
| 872fd17f5e | |||
| af49018911 | |||
| f870e9c8fd | |||
| d5982ba09f | |||
| 1d94fe8bca | |||
| 22d70d7bd4 | |||
| 09bdc32a9c | |||
| 7763ba17bf | |||
| 965204c46f | |||
| 815e4def6f | |||
| dc3ca8ff70 | |||
| 3bccb3fb84 | |||
| 402d93b5a4 | |||
| 927dc46431 | |||
| 87c32b1904 | |||
| bb97213460 | |||
| 9ca9bf1acd | |||
| 885c902b14 | |||
| dc4ee3f686 | |||
| 61bf5aaad4 | |||
| 18595cbee1 | |||
| 5d76586ac1 | |||
| dc78307df7 | |||
| 86a9cbfb45 | |||
| 623b20f713 | |||
| 5f4eae798f | |||
| 4a8609822d | |||
| 89ddc1e01f | |||
| 0ce42578fa | |||
| faa7ad0a35 | |||
| 38e8ceb253 | |||
| a32460f253 | |||
| 198268a4c3 | |||
| 71158970ae | |||
| 1383b06e86 | |||
| 24165e311b | |||
| 5ec892db34 | |||
| caef7eda29 | |||
| cf53af4778 | |||
| 415e0c2b5f | |||
| 9a22597473 | |||
| beb45af440 | |||
| 87a21eb0f2 | |||
| dea51cd356 | |||
| ed540e5584 | |||
| 9f80c9f35f | |||
| 5dec1b24cd | |||
| acb4eb2ae1 | |||
| 20c0354938 | |||
| eac112d602 | |||
| 9b4f659f67 | |||
| 0166d4e656 | |||
| 92b3761d2d | |||
| 484cee21c6 | |||
| 0e40318050 | |||
| b2cc76ff2e | |||
| 96acaaf000 | |||
| 400e5ea671 | |||
| 4fac460926 | |||
| 94a5631566 | |||
| ea91075107 | |||
| 0c7b82b9e4 | |||
| d765d3ddeb | |||
| 094fb1e2a4 | |||
| f7244c2152 | |||
| 2b5d1005e3 | |||
| b1eadf0716 | |||
| c001c13053 | |||
| ea4ec343bc | |||
| 5642e86f6a | |||
| 46db14fc3e | |||
| 0f6d9670ff | |||
| 4c3c24ae5a | |||
| eeb558d94d | |||
| 5e08f56dd3 | |||
| d99f150dd2 | |||
| 82b3100570 | |||
| 348b6fd3c1 | |||
| c2f492463f | |||
| 38239b2644 | |||
| 4b996c95de | |||
| 89d90efcef | |||
| d5b4bae502 | |||
| c3ec163e1a | |||
| a927a32909 | |||
| 9aab4517ef | |||
| 727e68edc7 | |||
| 9047de85c2 | |||
| 29c313ba58 | |||
| 487f601c09 | |||
| 7589b5ac37 | |||
| 8a9ce2ddd1 | |||
| be449f5afc | |||
| ac832a617e | |||
| 4fd2832370 | |||
| 52b072a7f3 | |||
| 55862757d6 | |||
| cbdf495c5f | |||
| a9d0d2e179 | |||
| d0cbf169dd | |||
| 833bc14405 | |||
| fb3620d0e3 | |||
| 02466e09fe | |||
| e39134faad | |||
| fa90b167ef | |||
| f5f20399ac | |||
| 659152dfcf | |||
| f34e87a593 | |||
| a172441155 | |||
| 90ca85ae9c | |||
| 40c0612412 | |||
| 5de79e3b0b | |||
| 39369aadd7 | |||
| b1e709d5bc | |||
| f760573fe4 | |||
| 4263ece65b | |||
| 217c45c102 | |||
| 3b2145ec79 | |||
| 566d1a1c13 | |||
| 09dab94807 | |||
| 6e3ddb8d96 | |||
| 8d7bb437eb | |||
| 392b43e8f7 | |||
| 32201a60c4 | |||
| bb114c570f | |||
| 42c52c10c7 | |||
| ade21a2cb8 | |||
| aced181d92 | |||
| 92cd1fc31c | |||
| 743138a100 | |||
| bebda06160 | |||
| f581930a40 | |||
| 70d4844dc6 | |||
| d3dd50dcac | |||
| ab8fdbad78 | |||
| 174bd9e986 | |||
| ab6f7ec97f | |||
| 6288463ddb | |||
| d700353ed8 | |||
| e979873bb3 | |||
| 331c77d317 | |||
| f9792615b7 | |||
| a94dc9336e | |||
| 6f1e11e860 | |||
| e720b4cef8 | |||
| 10f4534ee8 | |||
| 28c02a767d | |||
| 98f2ae5430 | |||
| 00c61133d5 | |||
| e457ab431d | |||
| b854fb6689 | |||
| 7c3a80296a | |||
| 4328bdd698 | |||
| e5f45df59a | |||
| 9dd270172b | |||
| 310f1fb921 | |||
| 5f14f0792f | |||
| fb3b43426a | |||
| 62b66d93ee | |||
| 6b12ff335d | |||
| ea522be8f4 | |||
| 44441f1ff9 | |||
| 3fca807356 | |||
| 4dc377233a | |||
| aabc60d36f | |||
| a653ac6382 | |||
| df7cc90da9 | |||
| eeb56a4630 | |||
| 713a87993e | |||
| 8ff55f3cf3 | |||
| 0fd72d2415 | |||
| 3c7f12c7b8 | |||
| 56abaa7c20 | |||
| 9335eedd04 | |||
| c13536031e | |||
| 57581634c4 | |||
| 4fa2535118 | |||
| 0ac0276dea | |||
| ed72a60f24 | |||
| 656aca7d1f | |||
| 3594847d8e | |||
| c17ac1d090 | |||
| 93ba86a779 | |||
| 738f5b2cc8 | |||
| 71a473d3e3 | |||
| d64d094de3 | |||
| 41df4eb03d | |||
| dde82ccb2f | |||
| c89f9ce875 | |||
| fc1adc4863 | |||
| d68c32ff26 | |||
| b67e9d795e | |||
| 87ac24124a | |||
| 138dcd7bdf | |||
| ae7be8a841 | |||
| 0d51e097d5 | |||
| abff1c0c55 | |||
| 1894425ad2 | |||
| 08643d3389 | |||
| 3460e7e405 | |||
| 36249777e0 | |||
| ca40ae7869 | |||
| cb05abb85f | |||
| b878ed4df3 | |||
| 16a02a5e4f | |||
| c614c5f004 | |||
| 8a76f99701 | |||
| fd5a3b9f8e | |||
| c7a542aac7 | |||
| 6cab1d1cf4 | |||
| be8009c950 | |||
| f6c1fa2f5c | |||
| e76f445985 | |||
| 6949be6fd8 | |||
| 69e18a009b | |||
| 64ef656544 | |||
| f95a6e8db7 | |||
| b81757d579 | |||
| 30c0026840 | |||
| efb4bf0536 | |||
| cd2fc0df0f | |||
| 51380cf906 | |||
| ded0c44ce3 | |||
| 61f5064929 | |||
| f316ebea20 | |||
| dc1a029e4a | |||
| 6bbacae54d | |||
| 972d372bd4 | |||
| fe7fb19adf | |||
| 5112389dae | |||
| c190a7b50a | |||
| 7ce8ccff78 | |||
| 7eb0a99fc7 | |||
| cbdd8f19ed | |||
| 5fdf319cda | |||
| 837e2313dd | |||
| e45fd2545e | |||
| 15537ea4b2 | |||
| df97f4069a | |||
| dea8b2bed9 | |||
| 0d130a4218 | |||
| b4ee89c1e8 | |||
| b2e7b8fdb6 | |||
| a494feb272 | |||
| 5efce4345a | |||
| b7703ce71f | |||
| c0ed32b645 | |||
| 7e4f408059 | |||
| a1993426de | |||
| bbb6ce8def | |||
| c601595477 | |||
| f909174119 | |||
| b0762a8b46 | |||
| 545f987f31 | |||
| b625c57d2d | |||
| 022d24bc5f | |||
| c5c09008a6 | |||
| 7679cc8bba | |||
| 4807d05861 | |||
| 34eedf5f07 | |||
| 941c186142 | |||
| b54ac50ea5 | |||
| b99426b7c6 | |||
| de1eedc63f | |||
| c3dac043cb | |||
| 00b52d4fe6 | |||
| b66bf595e2 | |||
| 7c24e836fe | |||
| 694f3bf013 | |||
| f6f42991e8 | |||
| 23f6803be9 | |||
| cdcb7fab4b | |||
| 5ee3607312 | |||
| 4b9642f51f | |||
| 4abbf3091f | |||
| ec4db3e58f | |||
| 0d2175b641 | |||
| a821ee363a | |||
| f43083acef | |||
| 7aed78a935 | |||
| 26c30fe3dc | |||
| 5550b8b1f5 | |||
| c94512fb24 | |||
| d1db6e5a8a | |||
| d352583237 | |||
| c8469be136 | |||
| 97620b8a3c | |||
| 24317b38bf | |||
| 6b28ed15e3 | |||
| b8b203e517 | |||
| e5c1e477f0 | |||
| 64752d3bae | |||
| 6145e0d2df | |||
| b365284743 | |||
| af62041c14 | |||
| 910dbf56fd | |||
| 4eca0dea4a | |||
| a76c17fd45 | |||
| b00aeec03a | |||
| ffe147fde8 | |||
| 02a5bb06a9 | |||
| a8997738bf | |||
| 202690d02e | |||
| 6d14bbdbc7 | |||
| b0699ab9be | |||
| 03a0b53eee | |||
| a044181a75 | |||
| e9ae9dc5bf | |||
| cbfa3b7e58 | |||
| 499f4aafc8 | |||
| bf57d3bd73 | |||
| 6200f354ca | |||
| c8dfb08dcb | |||
| 543e9d91e4 | |||
| dec5879919 | |||
| a1d21d8562 | |||
| 253ed877e5 | |||
| b809d24ab1 | |||
| 78aee0a487 | |||
| d16254c146 | |||
| 7ab3ef8453 | |||
| 4b695a3293 | |||
| da4c382c9a | |||
| 80973960f5 | |||
| 7be75f7008 | |||
| 6fa114c6c0 | |||
| 767b5f2bae | |||
| ed3a21b992 | |||
| 899c2b5647 | |||
| 61e616a53b | |||
| 3bf4504de9 | |||
| cd0740d895 | |||
| 9f99edc159 | |||
| 60568f23f5 | |||
| 6dc8bd7ba8 | |||
| ff4ecb3bda | |||
| c71e71359a | |||
| d5a09fa25e | |||
| f52c2be2c2 | |||
| 2233b93108 | |||
| d76eb3239a | |||
| a982bd2bbb | |||
| 9ef3edcc0e | |||
| de7c54b886 | |||
| 9c9f966597 | |||
| 12e77789d3 | |||
| bd640072ab | |||
| 0a9c46fbfc | |||
| 1cc4f11484 | |||
| 9386f2f9cb | |||
| 45d73d4604 | |||
| a5892330dd | |||
| 8a0e2d72a4 | |||
| 2629c65564 | |||
| 10694a6809 | |||
| aa3d177243 | |||
| 4d35d4edeb | |||
| bbaba3cd33 | |||
| d1f002a132 | |||
| 9ce9a91c95 | |||
| 7844e146b1 | |||
| eb997eca00 | |||
| 30124de2a8 | |||
| 1dcf7e4860 | |||
| 9ffc904ae5 | |||
| 2704749b44 | |||
| 1c174b5b70 | |||
| 8b5dd70d75 | |||
| f022316ad7 | |||
| 3386f5c5f7 | |||
| 57eead3a34 | |||
| 2868b51835 | |||
| 82118db71b | |||
| 14f55ca6b1 | |||
| cebfa12142 | |||
| 96c8c21b78 | |||
| 9ab1b1f3a7 | |||
| 94a0e426f8 | |||
| 006f8ae826 | |||
| 2889266522 | |||
| 5e6fccf143 | |||
| 3847e20d18 | |||
| fc69212a51 | |||
| 8999f54ba2 | |||
| f470e92300 | |||
| 3ac49e3e58 | |||
| 8dd9cfec5b | |||
| 0588214ee7 | |||
| 4ec49a031c | |||
| a31d7d6d3e | |||
| 64bbe9866d | |||
| 5d7ab84efc | |||
| 11f73a88e8 | |||
| dd0e847976 | |||
| 71ed333468 | |||
| 41d94ae3ee | |||
| b66bc1f863 | |||
| df7d80319c | |||
| 134145d166 | |||
| 688a103c10 | |||
| e2efa1f913 | |||
| aebd5c66f7 | |||
| 15c60c6b12 | |||
| f319ba2b83 | |||
| 93f12e7367 | |||
| 10acb07f82 | |||
| ee9a8dd53a | |||
| 0a55023bdb | |||
| fec9f8b4d3 | |||
| 13374df709 | |||
| 7fa04dc3c0 | |||
| 9d4e0e4e21 | |||
| 473c28ab07 | |||
| de47feac40 | |||
| 84894ff538 | |||
| f254c35749 | |||
| 1ff4e069ea | |||
| d574d33596 | |||
| f6756fc34b | |||
| 7c27eb47fc | |||
| 8d5a55c24c | |||
| 2e9aa79b02 | |||
| 1f9264225b | |||
| 18e145faaf | |||
| 47cf70120a | |||
| 86451a00ff | |||
| 34be7aab17 | |||
| 59139ed242 | |||
| 11f3964bdc | |||
| 7683408d18 | |||
| b74e793654 | |||
| 4bd74324d2 | |||
| 9a121b3039 | |||
| a9832c9c53 | |||
| 1e4c8bc291 | |||
| c45a47e53c | |||
| a07723d515 | |||
| 02d7a6fb1f | |||
| d62e8fa864 | |||
| a03fd337ef | |||
| 27c0f45430 | |||
| a0f1232261 | |||
| 5640d31080 | |||
| 1542fc67ca | |||
| a99a4ec85b | |||
| fa17b134cf | |||
| 6898a37704 | |||
| 45b6a5c565 | |||
| 7330e6ba39 | |||
| 8f405914a2 | |||
| 6d09a6f318 | |||
| b349a7e601 | |||
| 0d610895d2 | |||
| a65c677ecc | |||
| db93aeacc0 | |||
| 09ff0d888b | |||
| b9c5e741e8 | |||
| 620d86c903 | |||
| 14e31650e7 | |||
| 9848cb5847 | |||
| bf7db005ef | |||
| aa032dbb37 | |||
| 9e1b9775e2 | |||
| fcd16d9e32 | |||
| 2a4bd2a001 | |||
| eacd089c8f | |||
| 9ed355efd1 | |||
| d1bb25004d | |||
| 8d1b010d1b | |||
| 8a9b76af3a | |||
| 4bbd9428e3 | |||
| 83646003b6 | |||
| 947887f335 | |||
| 69631cd857 | |||
| 0722426425 | |||
| 98d54bbe6a | |||
| c1dc0cf127 | |||
| 44a1ce42f0 | |||
| a0c6cef0fa | |||
| f96e89956c | |||
| ce9ded9d8b | |||
| cb2d9f16ac | |||
| c2a13ae9dd | |||
| f8c2403e61 | |||
| 616b495426 | |||
| a22baa7fc3 | |||
| 0b9bb9ff76 | |||
| ef96192d8b | |||
| 13c34d9480 | |||
| 610f4cebc2 | |||
| d4d15eee7c | |||
| ee3886285b | |||
| a32c20473f | |||
| db956d93cf | |||
| 6a5a75131e | |||
| a676a47ed4 | |||
| 2067122d2c | |||
| 8a0fe892f4 | |||
| 29a6f4eb31 | |||
| f610592bff | |||
| 898008e2a1 | |||
| 9eaa3ca182 | |||
| c98818e5cf | |||
| 7643ecd90a | |||
| e4993bd302 | |||
| 32ee198128 | |||
| ab0d33b3c0 | |||
| 2c8b781817 | |||
| e59655c456 | |||
| 2ce7e5a3c7 | |||
| 79c7419b71 | |||
| 2efaf1df93 | |||
| 814ac7d976 | |||
| b0e5c1c634 | |||
| bae998f811 | |||
| 1b0d3f8583 | |||
| d81cb238df | |||
| 220ae351ee | |||
| 4b09158535 | |||
| e3c423cdd4 | |||
| 7840f5c577 | |||
| 87091c4214 | |||
| 4996ca9d93 | |||
| 9b8511b7f2 | |||
| a66fc7bf10 | |||
| 75cad1ab9c | |||
| be974b3fc8 | |||
| 777ef609ff | |||
| 224964db95 | |||
| 5bfc91de1b | |||
| b9d1aa4338 | |||
| e296dad260 | |||
| 4e372511fb | |||
| e0a71d0fff | |||
| 5bcdd4cf16 | |||
| 68b0b365da | |||
| 227046a739 | |||
| f9127341e7 | |||
| 184da9c20e | |||
| 96b5cabeb6 | |||
| 4a8706b9e3 | |||
| 94a10afac2 | |||
| a0660faf07 | |||
| 26170fc147 | |||
| 8d6147761b | |||
| 9d6abfd979 | |||
| 46f4324478 | |||
| bfeab57744 | |||
| 2e99926e82 | |||
| c28148b843 | |||
| b6b3fe12b6 | |||
| 56c00a7c43 | |||
| 4803bcccdd | |||
| 92f17d5156 | |||
| 5310c41694 | |||
| a54f3ed1a2 | |||
| 8ceb12370f | |||
| 0a7839fb7d | |||
| 76e4c59119 | |||
| 33b69b9f3a | |||
| b4f5e2d124 | |||
| 6853d797f2 | |||
| fa7a3c9c32 | |||
| a70c76f7f3 | |||
| 87a6a12367 | |||
| 9bcdcd918e | |||
| 7454454b63 | |||
| 69a5e42640 | |||
| 1e86ed225d | |||
| 4cd7977ced | |||
| 8d0f1a6602 | |||
| 0ce10cbb35 | |||
| 7decf02fd3 | |||
| 114731f722 | |||
| 2a7025ef17 | |||
| 257003ba09 | |||
| ca110c6d74 | |||
| 09f66caadc | |||
| 4a73ac19c2 | |||
| 9c3281e182 | |||
| a84e17635a | |||
| af7d915d14 | |||
| f679376445 | |||
| 4f32b994fa | |||
| dbb9115024 | |||
| af640044c9 | |||
| bece13d75e | |||
| 1b9c619739 | |||
| ccd8df85e4 | |||
| 1195945637 | |||
| 2e77ae8f4d | |||
| c8fefca916 | |||
| 6acb2203ef | |||
| 46c627dde1 | |||
| 1366bc3571 | |||
| 20c487be7a | |||
| ef674746d9 | |||
| e65268979c | |||
| e289432a09 | |||
| 8509049791 | |||
| d1b490a02d | |||
| 64d33bebbd | |||
| 0a44d00451 | |||
| 353b2c0488 | |||
| 85c68d0485 | |||
| 12c2237e00 | |||
| 68f9533392 | |||
| e93efa318a | |||
| fbc01ff0a2 | |||
| b0ca48740a | |||
| fa795dd149 | |||
| 0a4f1ded54 | |||
| b2e88d50fd | |||
| 2a54867724 | |||
| 210e5c7fbc | |||
| a5818c7cba | |||
| 059d517d0d | |||
| 5c3eb0ac82 | |||
| efa04fce18 | |||
| fb9771adde | |||
| 2930d0dc2d | |||
| e6e85ed812 | |||
| 7837a99e7b | |||
| 8c546dc358 | |||
| f0c75ec3c6 | |||
| 658283c4e8 | |||
| 0ef4d645df | |||
| 91713911ee | |||
| 1c0a54d75e | |||
| 0f82b3ca93 | |||
| 1a80187c07 | |||
| e315d0505c | |||
| 10b966a7c8 | |||
| 3c65408f25 | |||
| 1e31b479e8 | |||
| 6f1f446aa8 | |||
| e5149ac255 | |||
| 403539da35 | |||
| 443501112d | |||
| bea2effb89 | |||
| b2d875cc61 | |||
| e94f571744 | |||
| cf91468f65 | |||
| 69c6fdd070 | |||
| 1b9bfc37ad | |||
| 8cb1c195b1 | |||
| 41f963332c | |||
| dc6dee6a1a | |||
| 35becfc63b | |||
| 6c31d8cf85 | |||
| f6c25a2015 | |||
| 4c8d27f4bb | |||
| 87c49dc680 | |||
| f0d5695729 | |||
| be01c3b14f | |||
| bf435f4303 | |||
| 0289f47adc | |||
| 1f455c435f | |||
| db8d4b5daf | |||
| 5ac7f9ee11 | |||
| 6c80f85290 | |||
| 744bca93e8 | |||
| 601a65a1cb | |||
| 9f2523da21 | |||
| c936d51bac | |||
| b77862c290 | |||
| c495c3936b | |||
| a5a5819eec | |||
| 429c3fb57c | |||
| 0c9bec1d3d | |||
| 51771669d3 | |||
| f32651cd9d | |||
| 07a2663591 | |||
| fe9ee4c484 | |||
| 1425815467 | |||
| eea4a1b124 | |||
| 72c7772e89 | |||
| c4f0dc2f2d | |||
| 2d0645465e | |||
| 5031993289 | |||
| 8e944552b3 | |||
| 342b071189 | |||
| 32248b4635 | |||
| 89b4be49c8 | |||
| b3230abd68 | |||
| e26ac3d264 | |||
| fcc98e81d5 | |||
| bd4fa0b032 | |||
| d4675f25ec | |||
| a2a440e57b | |||
| f24b2e2540 | |||
| f8d2cd7bf3 | |||
| 1ff99ddbe4 | |||
| 13bf0d6f9f | |||
| d24f53895e | |||
| 66e8fa9d9e | |||
| 230fb79584 | |||
| 9181a9c398 | |||
| 2f05b20b0f | |||
| 115ffae588 | |||
| 7455e56f11 | |||
| d4b8e4bafa | |||
| 67a2e3fcd9 | |||
| f12d6855e9 | |||
| 56459e7e7a | |||
| d5244f5f96 | |||
| c8722ddcc6 | |||
| 5874001ec2 | |||
| b94a4cbe8b | |||
| 5d0b5f7947 | |||
| a193ee6cdf | |||
| ff438731d8 | |||
| 08913a5e76 | |||
| e7d2656613 | |||
| f3210f2626 | |||
| 0b1fa7c7d1 | |||
| 6b6d48f5da | |||
| 3b9e989195 | |||
| 4af065aad9 | |||
| b0e918caab | |||
| a6384dc679 | |||
| 838db45a74 | |||
| 44328f1086 | |||
| 2064a2f0ea | |||
| 6b066d9428 | |||
| d68508c0cf | |||
| 5f5f303a93 | |||
| 71bb0105ab | |||
| 796c81af61 | |||
| 329c7a52a7 | |||
| b19d39b794 | |||
| b4d8f1e04f | |||
| febf2cb105 | |||
| ef00e04638 | |||
| 1042f4b4f8 | |||
| 0180d63821 | |||
| 8b8c6b6bbb | |||
| fe8ad85f89 | |||
| c938c4dcd9 | |||
| 35f6a06406 | |||
| db7365c3b3 | |||
| 51d7e5df62 | |||
| 28f7fbf806 | |||
| d6d3dd8930 | |||
| 83571ba0bf | |||
| 34fc888c5e | |||
| 0a7be040c3 | |||
| 448334a8a2 | |||
| 5141116f38 | |||
| 310500b8d7 | |||
| 7bc0ab858a | |||
| ca438ca3a3 | |||
| 2a2cb7c26e | |||
| 9e5a2d30ed | |||
| 5b8c0db287 | |||
| 08864ae250 | |||
| ea6bd9283c | |||
| 83dfca249d | |||
| c7d41d1b84 | |||
| b09838f033 | |||
| 10164032f0 | |||
| 7829ff0a83 | |||
| aaa8a07511 | |||
| cd2aedcc6b | |||
| 553610cfa4 | |||
| ceea00e2cc | |||
| ef512b0f14 | |||
| 83a7e4df3f | |||
| d4aa90cc0c | |||
| 342d820095 | |||
| 18d9c00d13 | |||
| 8df792a8e3 | |||
| 0693f8ad60 | |||
| c6ff66ba51 | |||
| eaa6a68e4f | |||
| 6cf044d7c9 | |||
| 174170ee4f | |||
| 3ee2c3f0be | |||
| 339ab13f64 | |||
| 777e6f40cb | |||
| 577ec92c53 | |||
| d41679f2c0 | |||
| 2bfb2ae58f | |||
| ca56ca2dd1 | |||
| ca35a0635b | |||
| 127f29a17e | |||
| 9f40d84a51 | |||
| 21eab6dfe9 | |||
| d8ea2ad273 | |||
| a66b4d8923 | |||
| 3c9a289e2d | |||
| 29daa1ee89 | |||
| 769a07449f | |||
| 0993745c33 | |||
| f1d9ddeed6 | |||
| 2218ae91e0 | |||
| 21a8ba9674 | |||
| 153fe5f1e7 | |||
| ec49ac8eb6 | |||
| da1e71b2d2 | |||
| 00027ad8f3 | |||
| 81e7f37d61 | |||
| 4e6c1e3eaf | |||
| 77eda90923 | |||
| 0a7b9e7ea2 | |||
| 718bf0d74b | |||
| 82c963c38f | |||
| 999a33e77c | |||
| e96b4db126 | |||
| 118d4f864f | |||
| d6259f112e | |||
| f9eb55170d | |||
| 2bb104a234 | |||
| b75b29cf08 | |||
| 2a3934cbd7 | |||
| 9a6abed1e4 | |||
| baf5f97e96 | |||
| 3426d9cb37 | |||
| 53f401caf5 | |||
| 4950d0be55 | |||
| 57ac9d6b91 | |||
| 8723adbfcd | |||
| 8c5038c20f | |||
| 6518c22b79 | |||
| 0027e2c93b | |||
| 0b8eaad68a | |||
| 16738f053a | |||
| bed9a4d8d4 | |||
| 1ee3d40f37 | |||
| 1c6e9fc391 | |||
| 31c8e8d46b | |||
| ff6e0d9fbf | |||
| a92ccd6d43 | |||
| 32bdce147a | |||
| 1e6d1ed917 | |||
| 0f9e378923 | |||
| 5aaa11a445 | |||
| e77f266da5 | |||
| dc1be8e07b | |||
| d9daae7f41 | |||
| b30ae06dde | |||
| 488ba08e05 | |||
| 7a1db99daa | |||
| 8450349e19 | |||
| 50a6389b75 | |||
| aa4b65dbb0 | |||
| 96154422c1 | |||
| bc82f56353 | |||
| 1d9c9bb1b6 | |||
| 037a468332 | |||
| df41fa7cba | |||
| a48f595cf7 | |||
| f221321e6c | |||
| bf9842e414 | |||
| 0ee54460ba | |||
| 83a6fc531a | |||
| 8989737c71 | |||
| 56f89af121 | |||
| 97ee01eac1 | |||
| 8c7e430d4d | |||
| 2b36b69251 | |||
| acf8f10f76 | |||
| e5b890a765 | |||
| 3da97acdfd | |||
| 75fc7c48e9 | |||
| 7bdefeab37 | |||
| f71097f2d2 | |||
| 90e2229543 | |||
| e8e9987eb3 | |||
| 68b5383dc4 | |||
| 5ab215489a | |||
| 8f401e2a09 | |||
| 572932e92d | |||
| f924a407b3 | |||
| adcbf118b6 | |||
| 0e185eff4c | |||
| ad5df50eb9 | |||
| 22921e72e9 | |||
| 199881e3b2 | |||
| 12ec74e835 | |||
| 42d0a40f58 | |||
| 68e8b64b47 | |||
| a06f77b5f8 | |||
| b809fc007b | |||
| 334893071b | |||
| 306064e260 | |||
| 85f679c69f | |||
| f23e3d4e22 | |||
| 59d4c8fbd8 | |||
| 5f33c8a56d | |||
| 45ba604820 | |||
| 780df4df46 | |||
| 01ac637142 | |||
| 147de536f7 | |||
| 9f0596de0a | |||
| 750fbaa6cc | |||
| c623343b04 | |||
| b216274b37 | |||
| 843e813593 | |||
| 9eb0608c89 | |||
| 560a993972 | |||
| 8701c72d43 | |||
| 454f8a4628 | |||
| 03cc658e7e | |||
| e12081642d | |||
| 9cbdd8d553 | |||
| 65b1d93c70 | |||
| 085eace0cf | |||
| 552f6e2975 |
@@ -0,0 +1,314 @@
|
||||
# GitHub Copilot Instructions for ArcaneChat Android
|
||||
|
||||
## Project Overview
|
||||
|
||||
ArcaneChat is a Delta Chat Android client built on top of the official Delta Chat client with several improvements. It is a messenger app that uses email infrastructure for secure communication.
|
||||
|
||||
**Technology Stack:**
|
||||
- **Language:** Java (Java 8 compatibility)
|
||||
- **Build System:** Gradle with Android Gradle Plugin 8.11.1
|
||||
- **Min SDK:** 21 (Android 5.0)
|
||||
- **Target SDK:** 36 (Android 16)
|
||||
- **NDK Version:** 27.0.12077973
|
||||
- **Native Components:** Rust (deltachat-core-rust submodule)
|
||||
- **UI Framework:** Android SDK, Material Design Components
|
||||
- **Testing:** JUnit 4, Espresso, Mockito, PowerMock, AssertJ
|
||||
|
||||
## Repository Structure
|
||||
|
||||
- `src/main/` - Main application source code
|
||||
- `src/main/java/org/thoughtcrime/securesms/` - Main UI components
|
||||
- `src/main/java/com/b44t/messenger/` - Delta Chat core integration
|
||||
- `src/main/java/chat/delta/rpc/` - JSON-RPC bindings (generated, don't edit manually)
|
||||
- `src/main/res/` - Android resources (layouts, strings, drawables)
|
||||
- `src/androidTest/` - Instrumented tests (UI tests, benchmarks)
|
||||
- `src/androidTest/java/com/b44t/messenger/uitests/` - UI tests
|
||||
- `src/androidTest/java/com/b44t/messenger/uibenchmarks/` - Performance benchmarks
|
||||
- `src/gplay/` - Google Play flavor-specific code
|
||||
- `src/foss/` - F-Droid/FOSS flavor-specific code
|
||||
- `jni/deltachat-core-rust/` - Native Rust core library (submodule, **don't edit directly**)
|
||||
- `scripts/` - Build and helper scripts
|
||||
- `scripts/ndk-make.sh` - Build native libraries
|
||||
- `scripts/install-toolchains.sh` - Install Rust cross-compilation toolchains
|
||||
- `scripts/generate-rpc-bindings.sh` - Generate JSON-RPC bindings
|
||||
- `docs/` - Documentation
|
||||
- `fastlane/` - App store metadata and screenshots
|
||||
- `.github/workflows/` - CI/CD workflows (GitHub Actions)
|
||||
|
||||
## Build Instructions
|
||||
|
||||
### Prerequisites
|
||||
|
||||
1. **Initialize submodules:**
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
This MUST be done first before any build attempts.
|
||||
|
||||
2. **Set up environment variables:**
|
||||
```bash
|
||||
export ANDROID_NDK_ROOT=/path/to/ndk/27.0.12077973
|
||||
export PATH=${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/:${ANDROID_NDK_ROOT}
|
||||
```
|
||||
Note: Path format varies by OS (linux-x86_64, darwin-x86_64, etc.)
|
||||
|
||||
3. **Install Rust toolchains:**
|
||||
```bash
|
||||
scripts/install-toolchains.sh
|
||||
```
|
||||
Required for building the native Rust components.
|
||||
|
||||
4. **Build native libraries:**
|
||||
```bash
|
||||
scripts/ndk-make.sh
|
||||
```
|
||||
**IMPORTANT:** First run takes 30-60 minutes as it builds for all architectures (armeabi-v7a, arm64-v8a, x86, x86_64).
|
||||
For faster development builds, build for a single architecture:
|
||||
```bash
|
||||
scripts/ndk-make.sh armeabi-v7a
|
||||
```
|
||||
|
||||
5. **Build APK:**
|
||||
```bash
|
||||
./gradlew assembleDebug
|
||||
```
|
||||
Build time: ~2-5 minutes after native libraries are built.
|
||||
|
||||
### Build Flavors
|
||||
|
||||
- **gplay:** Google Play version with Firebase Cloud Messaging (applicationId: `com.github.arcanechat`)
|
||||
- **foss:** F-Droid version without proprietary services (applicationId: `chat.delta.lite`)
|
||||
|
||||
### Build Outputs
|
||||
|
||||
- Debug APKs: `build/outputs/apk/gplay/debug/` and `build/outputs/apk/fat/debug/`
|
||||
- Release APKs require signing configuration in `~/.gradle/gradle.properties`
|
||||
|
||||
### Common Build Issues
|
||||
|
||||
1. **Missing NDK or incorrect version:**
|
||||
- Error: `ANDROID_NDK_ROOT not set` or native library missing
|
||||
- Solution: Install NDK 27.0.12077973 and set ANDROID_NDK_ROOT environment variable
|
||||
|
||||
2. **Submodules not initialized:**
|
||||
- Error: Missing deltachat-core-rust files
|
||||
- Solution: Run `git submodule update --init --recursive`
|
||||
|
||||
3. **Gradle wrapper validation:**
|
||||
- Always validate gradle wrapper before building: `./gradlew wrapper --gradle-version=current`
|
||||
- Wrapper is validated in CI via `gradle/actions/wrapper-validation@v4`
|
||||
|
||||
4. **Clean build issues:**
|
||||
- If build fails, try: `./gradlew clean && scripts/ndk-make.sh && ./gradlew assembleDebug`
|
||||
- Remove `build/` directory if clean doesn't work
|
||||
|
||||
## Testing
|
||||
|
||||
### Running Unit Tests
|
||||
|
||||
```bash
|
||||
./gradlew test
|
||||
```
|
||||
Expected duration: 1-3 minutes
|
||||
|
||||
### Running Instrumented Tests
|
||||
|
||||
1. **Disable animations** on your device/emulator:
|
||||
- Developer Options → Set "Window animation scale", "Transition animation scale", and "Animator duration scale" to 0x
|
||||
- **CRITICAL:** Tests will fail if animations are enabled
|
||||
|
||||
2. **Run tests:**
|
||||
```bash
|
||||
./gradlew connectedAndroidTest
|
||||
```
|
||||
Expected duration: 10-30 minutes depending on device/emulator
|
||||
|
||||
### Online Tests
|
||||
|
||||
Some tests require real email credentials. Configure in `~/.gradle/gradle.properties`:
|
||||
```properties
|
||||
TEST_ADDR=youraccount@yourdomain.org
|
||||
TEST_MAIL_PW=yourpassword
|
||||
```
|
||||
|
||||
### UI Tests and Benchmarks
|
||||
|
||||
- Located in `src/androidTest/java/com/b44t/messenger/`
|
||||
- Test categories: `uitests/online/`, `uitests/offline/`, `uibenchmarks/`
|
||||
- Run via Android Studio: Run → Edit Configurations → Android Instrumented Test
|
||||
|
||||
## Coding Conventions
|
||||
|
||||
### General Guidelines
|
||||
|
||||
1. **Embrace existing style:** Match the coding style of the file you're editing
|
||||
2. **Minimize changes:** Don't refactor or rename in the same PR as bug fixes/features
|
||||
3. **Readable over paradigmatic:** Favor readability over strict Java patterns
|
||||
4. **Avoid premature optimization:** Keep things simple and on point
|
||||
5. **No excessive abstraction:** Avoid unnecessary factories, one-liner functions, or abstraction layers
|
||||
6. **Comments:** Only add comments if they match existing style or explain complex logic
|
||||
|
||||
### Architecture
|
||||
|
||||
- **UI/Model Separation:** Delta Chat Core (Rust) handles the model layer
|
||||
- **High-level interface:** Core provides data in UI-ready form; avoid additional transformations in UI layer
|
||||
- **Direct approach:** Prefer direct implementation over excessive class hierarchies
|
||||
|
||||
### Key Principles
|
||||
|
||||
- Work hard to avoid options and up-front choices
|
||||
- Avoid speaking about keys/encryption in primary UI
|
||||
- App must work offline and with poor network
|
||||
- Users don't read much text
|
||||
- Consistency matters
|
||||
- Primary UI should only show highly useful features
|
||||
|
||||
## Common Development Tasks
|
||||
|
||||
### Adding New Features
|
||||
|
||||
1. Consider the UX philosophy (minimal options, offline-first, simplicity)
|
||||
2. Check if core library changes are needed before implementing in UI
|
||||
3. Match existing code style in modified files
|
||||
4. Add instrumented tests for UI changes when appropriate
|
||||
5. Update relevant documentation
|
||||
|
||||
### Modifying Core Integration
|
||||
|
||||
- Core library is in `jni/deltachat-core-rust/` submodule
|
||||
- Java bindings are in `src/main/java/com/b44t/messenger/Dc*.java`
|
||||
- JSON-RPC bindings in `chat.delta.rpc.*` package (generated via dcrpcgen)
|
||||
|
||||
### Generating JSON-RPC Bindings
|
||||
|
||||
To regenerate JSON-RPC bindings after core changes:
|
||||
```bash
|
||||
./scripts/generate-rpc-bindings.sh
|
||||
```
|
||||
**Note:** Requires Rust tooling and [dcrpcgen tool](https://github.com/chatmail/dcrpcgen) installed
|
||||
|
||||
### Working with Translations
|
||||
|
||||
- Translations managed via Transifex (not in repository)
|
||||
- English source strings: `res/values/strings.xml`
|
||||
- Don't mix string changes with refactoring
|
||||
|
||||
### Debugging Native Code
|
||||
|
||||
Decode crash symbols:
|
||||
```bash
|
||||
$ANDROID_NDK_ROOT/ndk-stack --sym obj/local/armeabi-v7a --dump crash.txt > decoded.txt
|
||||
```
|
||||
|
||||
## Validation and Quality Checks
|
||||
|
||||
### Pre-commit Checks
|
||||
|
||||
Before committing changes, always run:
|
||||
|
||||
1. **Gradle wrapper validation:**
|
||||
```bash
|
||||
./gradlew wrapper --gradle-version=current
|
||||
```
|
||||
|
||||
2. **Build verification:**
|
||||
```bash
|
||||
./gradlew assembleDebug
|
||||
```
|
||||
|
||||
3. **Unit tests:**
|
||||
```bash
|
||||
./gradlew test
|
||||
```
|
||||
|
||||
4. **Code style:** Match existing code style in modified files (no automatic formatter configured)
|
||||
|
||||
### When to Rebuild Native Libraries
|
||||
|
||||
Rebuild native libraries (`scripts/ndk-make.sh`) when:
|
||||
- Updating deltachat-core-rust submodule
|
||||
- Modifying anything in `jni/` directory
|
||||
- Changing NDK version
|
||||
- After `git clean -fdx` or fresh clone
|
||||
|
||||
**DO NOT** rebuild native libraries for:
|
||||
- Pure Java/Kotlin code changes
|
||||
- Resource file changes
|
||||
- Gradle configuration changes (unless changing native library linking)
|
||||
- Documentation updates
|
||||
|
||||
## WebXDC Support
|
||||
|
||||
ArcaneChat has extended WebXDC support:
|
||||
- `window.webxdc.arcanechat` - Version detection
|
||||
- `sendToChat()` - Extra properties: `subject`, `html`, `type` (sticker/image/audio/video/file)
|
||||
- External link support in apps
|
||||
- `manifest.toml` - `orientation` field for landscape mode
|
||||
|
||||
## Important Files
|
||||
|
||||
- `build.gradle` - Main build configuration (Android Gradle Plugin 8.11.1, Java 8 compatibility)
|
||||
- `CONTRIBUTING.md` - Contribution guidelines
|
||||
- `BUILDING.md` - Detailed build setup instructions
|
||||
- `RELEASE.md` - Release process
|
||||
- `proguard-rules.pro` - ProGuard configuration (enabled for both debug and release)
|
||||
- `google-services.json` - Firebase configuration (gplay flavor only)
|
||||
- `settings.gradle` - Gradle settings
|
||||
- `.github/workflows/` - CI/CD configuration
|
||||
|
||||
## Dependencies and Constraints
|
||||
|
||||
- **Java Version:** Java 8 compatibility (do not use Java 9+ features)
|
||||
- **Gradle:** Use wrapper (`./gradlew`) to ensure correct Gradle version
|
||||
- **NDK:** Must use version 27.0.12077973 (specified in build.gradle)
|
||||
- **Min SDK:** 21 (Android 5.0) - code must be compatible
|
||||
- **Target SDK:** 36 (Android 16) - test on this API level when possible
|
||||
- **ProGuard:** Always enabled - ensure ProGuard rules are correct for new dependencies
|
||||
- **Multi-dex:** Enabled - app exceeds 65k method limit
|
||||
|
||||
## Package Structure
|
||||
|
||||
- `org.thoughtcrime.securesms.*` - Main UI components (legacy namespace from Signal)
|
||||
- `com.b44t.messenger.*` - Delta Chat core integration
|
||||
- `chat.delta.rpc.*` - JSON-RPC bindings (generated)
|
||||
|
||||
## Notes for AI Assistants
|
||||
|
||||
- This is a fork of Delta Chat Android with ArcaneChat-specific improvements
|
||||
- Maintain compatibility with Delta Chat core library
|
||||
- Test on both gplay and foss flavors when making changes
|
||||
- Native library must be rebuilt after core changes
|
||||
- ProGuard is enabled in both debug and release builds
|
||||
- Multi-dex is enabled due to app size
|
||||
|
||||
## CI/CD Workflows
|
||||
|
||||
### Preview APK Workflow (.github/workflows/preview-apk.yml)
|
||||
|
||||
Runs on every pull request to build and upload a preview APK:
|
||||
|
||||
1. **Setup steps:**
|
||||
- Checks out repository with submodules
|
||||
- Validates Fastlane metadata
|
||||
- Sets up Rust cache (working-directory: jni/deltachat-core-rust)
|
||||
- Sets up Java 17 (Temurin distribution)
|
||||
- Sets up Android SDK
|
||||
- Caches Gradle dependencies
|
||||
- Sets up NDK r27
|
||||
|
||||
2. **Build process:**
|
||||
```bash
|
||||
scripts/install-toolchains.sh && scripts/ndk-make.sh armeabi-v7a
|
||||
./gradlew --no-daemon -PABI_FILTER=armeabi-v7a assembleFossDebug
|
||||
```
|
||||
Note: Builds only armeabi-v7a for faster CI builds
|
||||
|
||||
3. **Output:** Uploads APK artifact to GitHub Actions
|
||||
|
||||
### Important CI Considerations
|
||||
|
||||
- Always validate Gradle wrapper before committing changes
|
||||
- Fastlane metadata must be valid (validated in CI)
|
||||
- Use `--no-daemon` flag for Gradle in CI environments
|
||||
- CI builds use FOSS flavor to avoid Google Services dependencies
|
||||
- Expected CI build time: 15-25 minutes for full workflow
|
||||
@@ -1,20 +0,0 @@
|
||||
name: add artifact links to pull request
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Upload Preview APK"]
|
||||
types: [completed]
|
||||
|
||||
jobs:
|
||||
artifacts-url-comments:
|
||||
name: add artifact links to pull request
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
steps:
|
||||
- name: add artifact links to pull request
|
||||
uses: tonyhallett/artifacts-url-comments@v1.1.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
prefix: "**To test the changes in this pull request, install this apk:**"
|
||||
format: "[📦 {name}]({url})"
|
||||
addTo: pull
|
||||
@@ -0,0 +1,53 @@
|
||||
name: Core Cache
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'jni/deltachat-core-rust'
|
||||
- 'jni/Android.mk'
|
||||
- 'jni/Application.mk'
|
||||
- 'jni/dc_wrapper.c'
|
||||
- 'scripts/ndk-make.sh'
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
submodules: recursive
|
||||
persist-credentials: false
|
||||
|
||||
- uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
||||
- uses: nttld/setup-ndk@ed92fe6cadad69be94a966a7ee3271275e62f779 # v1.6.0
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r27
|
||||
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
with:
|
||||
workspaces: jni/deltachat-core-rust
|
||||
|
||||
- name: Get deltachat-core-rust submodule hash
|
||||
id: core-hash
|
||||
run: echo "hash=$(git rev-parse HEAD:jni/deltachat-core-rust)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache compiled core
|
||||
id: cache-core
|
||||
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: |
|
||||
jni/arm64-v8a
|
||||
libs/arm64-v8a
|
||||
key: core-arm64-v8a-${{ steps.core-hash.outputs.hash }}-${{ hashFiles('jni/Android.mk', 'jni/Application.mk', 'jni/dc_wrapper.c', 'scripts/ndk-make.sh') }}-ndk-r27
|
||||
|
||||
- name: Compile core
|
||||
if: steps.cache-core.outputs.cache-hit != 'true'
|
||||
env:
|
||||
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||
run: |
|
||||
export PATH="${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/"
|
||||
scripts/install-toolchains.sh && scripts/ndk-make.sh arm64-v8a
|
||||
@@ -0,0 +1,49 @@
|
||||
name: Code Format
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
|
||||
permissions: {}
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
jobs:
|
||||
spotless:
|
||||
name: Check code format (Spotless)
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: temurin
|
||||
- name: Restore Gradle cache
|
||||
id: gradle-cache
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
|
||||
- name: Check formatting
|
||||
run: ./gradlew spotlessCheck
|
||||
- name: Save Gradle cache
|
||||
if: github.event_name == 'push' && steps.gradle-cache.outputs.cache-hit != 'true'
|
||||
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
~/.gradle/wrapper
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
@@ -6,25 +6,31 @@ concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Upload Preview APK
|
||||
if: github.event.pull_request.head.repo.full_name == github.repository
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
submodules: recursive
|
||||
persist-credentials: false
|
||||
|
||||
- name: Validate Fastlane Metadata
|
||||
uses: ashutoshgngwr/validate-fastlane-supply-metadata@v2
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
working-directory: jni/deltachat-core-rust
|
||||
- uses: actions/setup-java@v5
|
||||
uses: ashutoshgngwr/validate-fastlane-supply-metadata@c8857fdbbd3e00f9a5cbe8604bcecfa95ce8fef8 # v2.1.0
|
||||
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: 'temurin'
|
||||
- uses: android-actions/setup-android@v3
|
||||
- uses: actions/cache@v4
|
||||
|
||||
- uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: |
|
||||
~/.gradle/caches
|
||||
@@ -32,26 +38,61 @@ jobs:
|
||||
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
- uses: nttld/setup-ndk@v1
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/actions/wrapper-validation@50e97c2cd7a37755bbfafc9c5b7cafaece252f6e # v6.1.0
|
||||
|
||||
- uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
||||
- uses: nttld/setup-ndk@ed92fe6cadad69be94a966a7ee3271275e62f779 # v1.6.0
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r27
|
||||
|
||||
- name: Validate Gradle Wrapper
|
||||
uses: gradle/actions/wrapper-validation@v4
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
with:
|
||||
workspaces: jni/deltachat-core-rust
|
||||
|
||||
- name: Get deltachat-core-rust submodule hash
|
||||
id: core-hash
|
||||
run: echo "hash=$(git rev-parse HEAD:jni/deltachat-core-rust)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore compiled core
|
||||
id: core-cache
|
||||
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
|
||||
with:
|
||||
path: |
|
||||
jni/arm64-v8a
|
||||
libs/arm64-v8a
|
||||
key: core-arm64-v8a-${{ steps.core-hash.outputs.hash }}-${{ hashFiles('jni/Android.mk', 'jni/Application.mk', 'jni/dc_wrapper.c', 'scripts/ndk-make.sh') }}-ndk-r27
|
||||
|
||||
- name: Compile core
|
||||
if: steps.core-cache.outputs.cache-hit != 'true'
|
||||
env:
|
||||
ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||
run: |
|
||||
export PATH="${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/"
|
||||
scripts/install-toolchains.sh && scripts/ndk-make.sh armeabi-v7a
|
||||
scripts/install-toolchains.sh && scripts/ndk-make.sh arm64-v8a
|
||||
|
||||
- name: Build APK
|
||||
run: ./gradlew --no-daemon -PABI_FILTER=armeabi-v7a assembleFossDebug
|
||||
run: ./gradlew --no-daemon -PABI_FILTER=arm64-v8a assembleFossDebug
|
||||
|
||||
- name: Upload APK
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: app-preview.apk
|
||||
path: 'build/outputs/apk/foss/debug/*.apk'
|
||||
|
||||
- name: Add artifact links to PR
|
||||
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
|
||||
env:
|
||||
ARTIFACT_URL: ${{ steps.upload.outputs.artifact-url }}
|
||||
with:
|
||||
script: |
|
||||
const url = process.env.ARTIFACT_URL;
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: `**To test the changes in this pull request, install this apk:**\n\n[📦 app-preview.apk](${url})`,
|
||||
});
|
||||
|
||||
@@ -23,18 +23,18 @@ jobs:
|
||||
name: Upload Release APK
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
with:
|
||||
working-directory: jni/deltachat-core-rust
|
||||
- uses: actions/setup-java@v3
|
||||
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
|
||||
with:
|
||||
java-version: 17
|
||||
distribution: 'temurin'
|
||||
- uses: android-actions/setup-android@v3
|
||||
- uses: nttld/setup-ndk@v1
|
||||
- uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4.0.1
|
||||
- uses: nttld/setup-ndk@ed92fe6cadad69be94a966a7ee3271275e62f779 # v1.6.0
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r27
|
||||
@@ -59,12 +59,16 @@ jobs:
|
||||
rm build/outputs/apk/foss/release/*universal*
|
||||
./gradlew assembleGplayRelease
|
||||
mv build/outputs/apk/gplay/release/*universal* build/outputs/apk/foss/release/ArcaneChat-gplay.apk
|
||||
mv build/outputs/mapping/fossRelease/mapping.txt build/outputs/mapping/fossRelease/mapping-foss.txt
|
||||
mv build/outputs/mapping/gplayRelease/mapping.txt build/outputs/mapping/fossRelease/mapping-gplay.txt
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
- name: Release on GitHub
|
||||
uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0
|
||||
with:
|
||||
token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
body: '[<img src="store/get-it-on-gplay.png" alt="Get it on Google Play" height="48">](https://play.google.com/store/apps/details?id=com.github.arcanechat) [<img src="store/get-it-on-fdroid.png" alt="Get it on F-Droid" height="48">](https://f-droid.org/packages/chat.delta.lite) [<img src="store/get-it-on-github.png" alt="Get it on GitHub" height="48">](https://github.com/ArcaneChat/android/releases/latest/download/ArcaneChat-gplay.apk)'
|
||||
prerelease: ${{ contains(github.event.ref, '-beta') }}
|
||||
fail_on_unmatched_files: true
|
||||
files: build/outputs/apk/foss/release/*.apk
|
||||
files: |
|
||||
build/outputs/apk/foss/release/*.apk
|
||||
build/outputs/mapping/fossRelease/mapping-*.txt
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
name: GitHub Actions Security Analysis with zizmor
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
branches: ["**"]
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
zizmor:
|
||||
name: Run zizmor
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files.
|
||||
contents: read
|
||||
actions: read
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Run zizmor
|
||||
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
|
||||
@@ -0,0 +1,6 @@
|
||||
rules:
|
||||
unpinned-uses:
|
||||
config:
|
||||
policies:
|
||||
actions/*: ref-pin
|
||||
dependabot/*: ref-pin
|
||||
@@ -22,24 +22,12 @@ subproject _deltachat-core-rust_:
|
||||
|
||||
## Generate JSON-RPC bindings
|
||||
|
||||
To generate the JSON-RPC bindings (ex. `chat.delta.rpc.*` package)
|
||||
install the [dcrpcgen tool](https://github.com/chatmail/dcrpcgen)
|
||||
then generate the `schema.json` file:
|
||||
To generate/update the JSON-RPC bindings (ex. `chat.delta.rpc.*` package)
|
||||
install Rust tooling (read sections below) and the [dcrpcgen tool](https://github.com/chatmail/dcrpcgen)
|
||||
then generate the code running the script:
|
||||
|
||||
```
|
||||
# install deltachat-rpc-server program:
|
||||
cargo install --path ./jni/deltachat-core-rust/deltachat-rpc-server
|
||||
# check the version of core matches:
|
||||
deltachat-rpc-server --version
|
||||
# generate the schema:
|
||||
deltachat-rpc-server --openrpc > schema.json
|
||||
```
|
||||
|
||||
then pass the schema file to the `dcrpcgen` tool to generate the
|
||||
code:
|
||||
|
||||
```
|
||||
dcrpcgen java --schema schema.json -o ./src/main/java/
|
||||
./scripts/update-rpc-bindings.sh
|
||||
```
|
||||
|
||||
## Build Using Nix
|
||||
@@ -255,3 +243,15 @@ $ANDROID_NDK_ROOT/ndk-stack --sym obj/local/armeabi-v7a --dump crash.txt > decod
|
||||
`obj/local/armeabi-v7a` is the extracted path from `deltachat-gplay-release-X.X.X.apk-symbols.zip` file from https://download.delta.chat/android/symbols/
|
||||
|
||||
Replace `armeabi-v7a` by the correct architecture the logs come from (can be guessed by trial and error)
|
||||
|
||||
|
||||
### Deobfuscating Java Stack Traces
|
||||
|
||||
Because the app uses code minification (ProGuard/R8), Java stack traces in crash reports are obfuscated.
|
||||
To decode them, use `retrace` with the `mapping.txt` file that is included in the symbols zip:
|
||||
|
||||
```
|
||||
retrace mapping.txt crash.txt > decoded-crash.txt
|
||||
```
|
||||
|
||||
`mapping.txt` is extracted from the same `deltachat-gplay-release-X.X.X.apk-symbols.zip` file available at https://download.delta.chat/android/symbols/
|
||||
|
||||
@@ -1,5 +1,166 @@
|
||||
# Delta Chat Android Changelog
|
||||
|
||||
## 2.51.0
|
||||
2026-05
|
||||
|
||||
* Better incoming call system integration
|
||||
* Calls are not experimental anymore and don't need to be manually enabled
|
||||
* Calls can be answered by tapping messages
|
||||
* Notify the user when they try to make a call while the device is offline
|
||||
* Channels are no longer experimental and are available by default
|
||||
* Display a permanent notification when doing location streaming and get rid of dangerous "Access Location in Background" permission
|
||||
* Autoplay all voice messages in a chat
|
||||
* Allow to share location for 24 hours
|
||||
* Allow mini-apps to play audio without user interaction
|
||||
* Allow to paste and open invitation links from search
|
||||
* Mark chats as unread (long tap a chat and select the corresponding option from the three-dot-menu)
|
||||
* Add "Mark all as read" option to profile menu in the profile switcher
|
||||
* Fix process of upgrading from a very old version of the app
|
||||
* Show more recent added stickers at the top of the sticker picker
|
||||
* Allow to open links in messages via actions in TalkBack menu
|
||||
* Allow to open map if user clicks "Location streaming enabled" system message
|
||||
* Allow to disable incoming calls notifications
|
||||
* Add an option to process unencrypted messages; by default, only encrypted messages can be sent or received
|
||||
* Fix: do not accidentally set draft in chats that don't allow sending messages
|
||||
* Fix swipe navigation between tabs in RTL languages
|
||||
* Remove "Move to DeltaChat folder", in case you are using the option, a device message shows how to proceed
|
||||
* Remove "Only fetch from DeltaChat folder" option, the functionality is preserved for existing profiles
|
||||
* Remove "Delete Messages from Server" option, this is now up to the server:
|
||||
Chatmail handles that automatically, classic email servers used as relay often have lots of storage or options themselves
|
||||
* Remove "Show Email" options, all messages are shown by default, shared usage of email account is not supported
|
||||
* Allow otherwise invalid TLS connections if the key is unchanged
|
||||
* Adapt quota warning to automatic cleanup.
|
||||
* Don't show non-delivery-notfications in broadcast channels
|
||||
* Resend the last 10 messages to new broadcast channel member
|
||||
* Enable PQC (Post-Quantum Cryptography) support. We do not generate PQC keys yet, this step is needed for forward compatibility
|
||||
* Improve avatar quality
|
||||
* Add new webxdc.isAppSender and webxdc.isBroadcast APIs for mini-apps
|
||||
* Fix: avoid invalid empty "~" notifications when some peer is streaming location
|
||||
* Fix: Improve detection of stickers
|
||||
* Fix text direction issues for RTL languages in "Show full message" view
|
||||
* Fix: Reconnect when removing a relay
|
||||
* Fix: Location streaming now works correctly with multiple accounts
|
||||
* Fix debouncing in chatlist and search
|
||||
* Fix sharing contact across profiles
|
||||
* Fix: Reset scroll location after switching account
|
||||
* Update to core 2.51.0
|
||||
|
||||
## v2.49.0
|
||||
2026-04
|
||||
|
||||
* Fix file sharing to certain apps (e.g. Material Files, etc.)
|
||||
* Fix problem with calls when microphone permission is not granted
|
||||
* Fix taking pictures and videos in devices with SD cards
|
||||
* Fix flipped orientation for some images
|
||||
* Fix: avoid empty contact request chats when using invite links in a multi-device setup
|
||||
* Remove proxy toggle from profile editing to avoid confusion
|
||||
* Updated translations
|
||||
* Update to core 2.49.0
|
||||
|
||||
## v2.48.0
|
||||
2026-03
|
||||
|
||||
* Add a warning when editing relays
|
||||
* Fix message reordering problems in multi-relay setups
|
||||
* Some more bug fixes and updated translations
|
||||
* Update to core 2.48.0
|
||||
|
||||
## v2.47.0
|
||||
2026-03
|
||||
|
||||
* Allow to set chat description
|
||||
* Unified date display in call bubbles
|
||||
* Explain at "Settings / Chats / Outgoing Media Quality" how to send original quality
|
||||
* Add a basic sticker picker
|
||||
* Leave groups and channels before deletion
|
||||
* Further minimize metadata in messages and while getting in contact.
|
||||
* Increase resilience of multi-relay usage: if on relay goes down, messages are still received in the others.
|
||||
* Allow to hide a relay from contacts instead of removing, allowing smoother relay changes
|
||||
* HTML emails: allow to review and copy links before opening them
|
||||
* Mark call message as seen when accepting/declining a call
|
||||
* Fix: keep original sent timestamp for resent messages
|
||||
* Fix: make clicking on broadcast member-added messages work always
|
||||
* Fix: remove notification when a message is deleted by sender
|
||||
* Fix: avoid "reply privately" not quoting the selected message sometimes
|
||||
* Fix: properly hide the calls button
|
||||
* Some more bug fixes and updated translations
|
||||
* Update to core 2.47.0
|
||||
|
||||
## v2.43.0
|
||||
2026-02
|
||||
|
||||
* Improve switch speed when changing profiles
|
||||
* Allow to switch profile when sharing or forwarding
|
||||
* Display message views count for channel owners
|
||||
* Don't notify notification-to-all from in-chat apps if the chat is muted
|
||||
* Allow to see inbox quota for all relays in connectivity screen
|
||||
* Truncate file names in the middle, not at the end; important information are more often at the end
|
||||
* Remove email address from user profile
|
||||
* Mark external links with " ↗" to make them clear
|
||||
* Make QR code larger on "Add Second Device" screen
|
||||
* Add indication for blocked contacts in user profile
|
||||
* Allow to start calls with video disabled
|
||||
* Show hint for empty contact search results
|
||||
* Add background playing for voice messages and other audio files
|
||||
* Allow scanning Invitation Code when creating a new profile
|
||||
* Add context menu in long-pressing relays items instead of showing buttons
|
||||
* Enhanced video player UI
|
||||
* Fix: Show dialog if pasted QR codes are invalid
|
||||
* Fix: Refresh chat list when returning from conversation if selected profile changed
|
||||
* Fix: Update menu when using "select all" in contact selection
|
||||
* Fix: Avoid empty profiles after using "add as second device" from welcome screen
|
||||
* Fix: Remove from group deselected members in the contact selection list
|
||||
* Fix multi-device seen messages synchronization when using multiple relays
|
||||
* Fix mailto handling
|
||||
* Fix layout problems inside in-chat apps
|
||||
* Fix real-time for in-chat apps that need it
|
||||
* Avoid crash when the app is minimized with profile switcher or reactions dialogs open
|
||||
* Remove "trash icon" option from contact selection list when adding members to group
|
||||
* Update to core 2.43.0
|
||||
|
||||
## v2.35.0
|
||||
2026-01
|
||||
|
||||
* Protect profile deletion and relays management with system lock/pin
|
||||
* Fix: Remove address from profile switcher
|
||||
* Fix: Avoid crash if the system doesn't allow to start foreground service
|
||||
* Remove deprecated "real-time apps" switch
|
||||
* Update to core 2.35.0
|
||||
|
||||
## v2.34.0
|
||||
2025-12
|
||||
|
||||
* Allow to add relay from clipboard or image if camera permission is not granted
|
||||
* Avoid crash in the "View Log" screen
|
||||
* Update to core 2.34.0
|
||||
|
||||
## v2.33.1
|
||||
2025-12
|
||||
|
||||
* Target Android 16
|
||||
* Change color of links in text messages
|
||||
* Improve edge-to-edge support
|
||||
* Add the option (opt-in) to send anonymous statistics to Delta Chat's developers
|
||||
* Metadata protection: protect message recipients
|
||||
* Allow to withdraw channel invite links and QR codes
|
||||
* Allow to open externally links clicked inside in-chat apps
|
||||
* Do not show "1 member" when the process of joining the group is not finished
|
||||
* Make search case-insensitive for non-ASCII chat and contact names
|
||||
* Improve handling of video recoding
|
||||
* Send .webm videos as file, they are not supported by all platforms
|
||||
* Tweak advanced section and wording of some advanced options
|
||||
* Fix: avoid crash in push notifications handling
|
||||
* Fix: avoid freezing in background
|
||||
* Fix: clean up web storage of deleted in-chat apps
|
||||
* Fix: avoid crash when exporting some files with wrong image MIME type
|
||||
* Expose new "Multi-device mode" option instead of "Delete from server" for chatmail profiles
|
||||
* Opened in-chat apps got a 'About Apps' menu item
|
||||
* Avoid gray avatar on profile creation
|
||||
* Avoid last item in chat list being covered by the floating button
|
||||
* Add disk usage statistics to log
|
||||
* New experimental feature: several addresses per profile
|
||||
* Update to core 2.33.0
|
||||
|
||||
## v2.25.0
|
||||
2025-11
|
||||
|
||||
|
||||
@@ -73,18 +73,15 @@ esp. before/after screenshots.
|
||||
|
||||
### Coding Conventions
|
||||
|
||||
Source files are partly derived from different other open source projects
|
||||
and may follow different coding styles and conventions.
|
||||
|
||||
If you do a PR fixing a bug or adding a feature,
|
||||
please embrace the coding convention you see in the corresponding files,
|
||||
so that the result fits well together.
|
||||
|
||||
Do not refactor or rename things in the same PR
|
||||
to make the diff small and the PR easy to review.
|
||||
|
||||
Project language is Java.
|
||||
|
||||
Code formatting is enforced via [Spotless](https://github.com/diffplug/spotless) Gradle plugin.
|
||||
Auto-format all files by running `./gradlew spotlessApply` before opening a PR.
|
||||
CI will fail if files are not formatted correctly so make sure to run the formatter before pushing.
|
||||
|
||||
If you do a PR fixing a bug or adding a feature, do not refactor or rename things in the same PR
|
||||
to make the diff small and the PR easy to review.
|
||||
|
||||
By using [Delta Chat Core](https://github.com/deltachat/deltachat-core-rust)
|
||||
there is already a strong separation between "UI" and "Model".
|
||||
Further separations and abstraction layers are often not helpful
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
## Generate APKs
|
||||
|
||||
### Update core and translations
|
||||
|
||||
on the command-line, in a PR called "update-core-and-stuff-DATE":
|
||||
|
||||
1. update core:
|
||||
@@ -21,12 +23,19 @@ a) Update `CHANGELOG.md`
|
||||
as `update to core 1.2.3` or `using core 1.2.3`
|
||||
|
||||
|
||||
2. update translations and local help:
|
||||
2. update JSON-RPC bindings:
|
||||
```
|
||||
./scripts/update-rpc-bindings.sh
|
||||
```
|
||||
|
||||
3. update translations and local help:
|
||||
```
|
||||
./scripts/tx-pull-translations.sh
|
||||
./scripts/create-local-help.sh # requires deltachat-pages checked out at ../deltachat-pages
|
||||
```
|
||||
|
||||
### Prepare release
|
||||
|
||||
the following steps are done in a PR called `prep-VERSION` (no leading "v"):
|
||||
|
||||
3. Update `CHANGELOG.md`:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '8.11.1'
|
||||
id 'com.google.gms.google-services' version '4.4.1'
|
||||
id 'com.diffplug.spotless' version '8.3.0'
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -21,7 +22,7 @@ android {
|
||||
}
|
||||
namespace "org.thoughtcrime.securesms"
|
||||
flavorDimensions "none"
|
||||
compileSdk 35
|
||||
compileSdk 36
|
||||
|
||||
// Set NDK version to strip native libraries.
|
||||
// Even though we compile our libraries outside Gradle with `scripts/ndk-make.sh`,
|
||||
@@ -33,14 +34,14 @@ android {
|
||||
useLibrary 'org.apache.http.legacy'
|
||||
|
||||
defaultConfig {
|
||||
versionCode 30000732
|
||||
versionName "2.25.0"
|
||||
versionCode 30000744
|
||||
versionName "2.51.0"
|
||||
|
||||
applicationId "chat.delta.lite"
|
||||
multiDexEnabled true
|
||||
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 35
|
||||
targetSdkVersion 36
|
||||
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
@@ -72,10 +73,20 @@ android {
|
||||
packagingOptions {
|
||||
jniLibs {
|
||||
doNotStrip '**/*.so'
|
||||
keepDebugSymbols += ['*/mips/*.so', '*/mips64/*.so']
|
||||
keepDebugSymbols += [
|
||||
'*/mips/*.so',
|
||||
'*/mips64/*.so'
|
||||
]
|
||||
}
|
||||
resources {
|
||||
excludes += ['LICENSE.txt', 'LICENSE', 'NOTICE', 'asm-license.txt', 'META-INF/LICENSE', 'META-INF/NOTICE']
|
||||
excludes += [
|
||||
'LICENSE.txt',
|
||||
'LICENSE',
|
||||
'NOTICE',
|
||||
'asm-license.txt',
|
||||
'META-INF/LICENSE',
|
||||
'META-INF/NOTICE'
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +210,31 @@ android {
|
||||
renderScript true
|
||||
aidl true
|
||||
}
|
||||
}
|
||||
|
||||
spotless {
|
||||
java {
|
||||
target 'src/*/java/**/*.java'
|
||||
targetExclude 'src/main/java/chat/delta/**' // ignore auto-generated code
|
||||
googleJavaFormat() // Google style = 2-space indent, matches Android Studio defaults
|
||||
removeUnusedImports()
|
||||
trimTrailingWhitespace()
|
||||
endWithNewline()
|
||||
}
|
||||
format 'xml', {
|
||||
target 'src/*/res/**/*.xml', 'src/*/AndroidManifest.xml'
|
||||
targetExclude 'src/*/res/values*/strings*.xml' // line-break changes invalidate translations
|
||||
eclipseWtp('xml').configFile('spotless/eclipse-wtp-xml.prefs')
|
||||
trimTrailingWhitespace()
|
||||
endWithNewline()
|
||||
}
|
||||
groovyGradle {
|
||||
target '*.gradle'
|
||||
greclipse()
|
||||
leadingTabsToSpaces(4)
|
||||
trimTrailingWhitespace()
|
||||
endWithNewline()
|
||||
}
|
||||
}
|
||||
|
||||
final def markwon_version = '4.6.2'
|
||||
@@ -211,6 +246,14 @@ dependencies {
|
||||
implementation "io.noties.markwon:inline-parser:$markwon_version"
|
||||
implementation 'com.airbnb.android:lottie:4.2.2' // Lottie animations support.
|
||||
|
||||
def media3_version = "1.8.0" // 1.9.0 need minSdkVersion 23
|
||||
|
||||
implementation 'androidx.concurrent:concurrent-futures:1.3.0'
|
||||
implementation 'androidx.core:core:1.17.0'
|
||||
implementation 'androidx.core:core-telecom:1.0.1'
|
||||
implementation 'im.conversations.webrtc:webrtc-android:129.0.0'
|
||||
// For Kotlin->Java interpolation
|
||||
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.9.4'
|
||||
implementation 'androidx.sharetarget:sharetarget:1.2.0'
|
||||
implementation 'androidx.webkit:webkit:1.14.0'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
@@ -230,8 +273,11 @@ dependencies {
|
||||
implementation 'androidx.work:work-runtime:2.9.1'
|
||||
implementation 'androidx.emoji2:emoji2-emojipicker:1.5.0'
|
||||
implementation 'com.google.guava:guava:31.1-android'
|
||||
implementation 'com.google.android.exoplayer:exoplayer-core:2.19.1' // plays video and audio
|
||||
implementation 'com.google.android.exoplayer:exoplayer-core:2.19.1' // FIXME: exoplayer dependencies kept for Video, but we shall migrate them at some point
|
||||
implementation 'com.google.android.exoplayer:exoplayer-ui:2.19.1'
|
||||
implementation "androidx.media3:media3-exoplayer:$media3_version"
|
||||
implementation "androidx.media3:media3-session:$media3_version"
|
||||
implementation "androidx.media3:media3-ui:$media3_version"
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
|
||||
implementation 'com.google.zxing:core:3.3.0' // fixed version to support SDK<24
|
||||
implementation ('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false } // QR Code scanner
|
||||
@@ -245,7 +291,8 @@ dependencies {
|
||||
implementation 'com.github.amulyakhare:TextDrawable:558677ea31' // number of unread messages,
|
||||
// the one-letter circle for the contacts (when there is not avatar) and a white background.
|
||||
implementation 'com.googlecode.mp4parser:isoparser:1.0.6' // MP4 recoding; upgrading eg. to 1.1.22 breaks recoding, however, i have not investigated further, just reset to 1.0.6
|
||||
implementation ('com.davemorrissey.labs:subsampling-scale-image-view:3.10.0') { // for the zooming on photos / media
|
||||
implementation ('com.davemorrissey.labs:subsampling-scale-image-view:3.10.0') {
|
||||
// for the zooming on photos / media
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
}
|
||||
|
||||
@@ -254,11 +301,13 @@ dependencies {
|
||||
// <https://github.com/cketti/SafeContentResolver>
|
||||
implementation 'de.cketti.safecontentresolver:safe-content-resolver-v21:1.0.0'
|
||||
|
||||
gplayImplementation('com.google.firebase:firebase-messaging:24.1.2') { // for PUSH notifications, don't upgrade: v25.0.0 requires minSdk>=23
|
||||
gplayImplementation('com.google.firebase:firebase-messaging:24.1.2') {
|
||||
// for PUSH notifications, don't upgrade: v25.0.0 requires minSdk>=23
|
||||
exclude group: 'com.google.firebase', module: 'firebase-core'
|
||||
exclude group: 'com.google.firebase', module: 'firebase-analytics'
|
||||
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
|
||||
}
|
||||
gplayImplementation 'com.google.android.gms:play-services-location:21.3.0'
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.assertj:assertj-core:3.27.3'
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
ArcaneChat is a decentralized and secure instant messenger that is easy to use for friends and family.
|
||||
|
||||
• Anonymous. Instant onboarding without a phone number, e-mail or other private data.
|
||||
• Private. Instant on-boarding without a phone number or other private data.
|
||||
|
||||
• Friends & Family: Only chat with people you know. Unknown users cannot message or follow you without mutual consent.
|
||||
|
||||
• Flexible. Supports multiple chat profiles and is easy to setup on multiple devices.
|
||||
|
||||
@@ -23,12 +25,11 @@ ArcaneChat is a Delta Chat client and was created with a focus on usability, goo
|
||||
<li>Multiple color themes/skins</li>
|
||||
<li>It is possible to disable profiles to completely disconnect them saving data/bandwidth</li>
|
||||
<li>You can easily see the connection status of all your profiles in the profile switcher</li>
|
||||
<li>A videochat instance is set by default</li>
|
||||
<li>Extra option to share location for 12 hours</li>
|
||||
<li>Extra option to share location for 24 hours</li>
|
||||
<li>Clicking on a message with a POI location, will open the POI on the map</li>
|
||||
<li>Last-seen status of contacts is shown in your contact list, like in WhatsApp, Telegram, etc.</li>
|
||||
<li>Videos are played in loop, useful for short GIF videos</li>
|
||||
<li>Verified icon is shown in the chat list for the "Device Messages" chat</li>
|
||||
<li>Verified icon is shown in the chat list for the "Device Messages" and "Saved Messages" chat to avoid fishing attempts by scammer pretending to be the official chats</li>
|
||||
<li>Voice messages have more aggressive compression in "worse quality" mode to save data plan</li>
|
||||
<li>Automatic download of messages limited to 640KB by default</li>
|
||||
<li>Profile's display name is always shown in the app's title bar instead of the name of the app</li>
|
||||
|
||||
|
Before Width: | Height: | Size: 137 KiB After Width: | Height: | Size: 135 KiB |
|
Before Width: | Height: | Size: 287 KiB After Width: | Height: | Size: 283 KiB |
|
Before Width: | Height: | Size: 256 KiB After Width: | Height: | Size: 250 KiB |
|
Before Width: | Height: | Size: 447 KiB After Width: | Height: | Size: 446 KiB |
@@ -0,0 +1,36 @@
|
||||
ArcaneChat — децентрализованный и защищённый мессенджер, удобный для друзей и семьи.
|
||||
|
||||
• Анонимность. Мгновенный вход без номера телефона, e-mail или других личных данных.
|
||||
|
||||
• Гибкость. Поддерживает несколько профилей чатов и легко настраивается на нескольких устройствах.
|
||||
|
||||
• Расширяемость. В чатах можно использовать мини-приложения: списки покупок, календари или игры.
|
||||
|
||||
• Надёжность. Работает даже при плохом соединении и в сложных сетевых условиях.
|
||||
|
||||
• Безопасность. Проверенное сквозное шифрование, защищённое от сетевых и серверных атак.
|
||||
|
||||
• Самостоятельность. Может работать с вашим собственным e-mail-адресом или сервером.
|
||||
|
||||
ArcaneChat — клиент Delta Chat, разработанный с акцентом на удобство, качественный UX и экономию трафика. Также приложение часто экспериментирует с новыми функциями, которые со временем могут быть добавлены в официальный клиент Delta Chat.
|
||||
|
||||
<b>Основные отличия от официального клиента Delta Chat:</b>
|
||||
|
||||
<ul>
|
||||
<li>Поддержка некоторых стилей markdown в текстовых сообщениях (жирный, курсив, зачёркнутый и т.д.)</li>
|
||||
<li>Поддержка отображения анимированных стикеров Telegram (.tgs-файлы)</li>
|
||||
<li>Поддержка предпросмотра SVG-изображений</li>
|
||||
<li>Несколько цветовых тем/скинов</li>
|
||||
<li>Возможность отключать профили, полностью отключая им доступ в сеть для экономии трафика</li>
|
||||
<li>На панели переключения профилей видно состояние подключения каждого профиля</li>
|
||||
<li>Дополнительная опция для обмена местоположением на 12 часов</li>
|
||||
<li>Нажатие на сообщение с POI открывает его на карте</li>
|
||||
<li>Статус «был(а) в сети» отображается в списке контактов, как в WhatsApp, Telegram и т.д.</li>
|
||||
<li>Видео воспроизводятся по кругу — удобно для коротких GIF-видео</li>
|
||||
<li>У чата «Device Messages» в списке чатов отображается значок подтверждения</li>
|
||||
<li>В режиме «низкое качество» голосовые сообщения сжимаются сильнее для экономии трафика</li>
|
||||
<li>Автоматическая загрузка сообщений по умолчанию ограничена 640KB</li>
|
||||
<li>Отображаемое имя профиля всегда видно в заголовке приложения вместо названия приложения</li>
|
||||
<li>Для разработчиков мини-приложений: доступны дополнительные возможности WebXDC API, см. https://github.com/ArcaneChat/android/#webxdc</li>
|
||||
<li>Более удобная организация настроек с дополнительным разделом «Privacy»</li>
|
||||
</ul>
|
||||
@@ -0,0 +1 @@
|
||||
⚡ Быстрые зашифрованные чаты для семьи 🎉
|
||||
@@ -0,0 +1 @@
|
||||
ArcaneChat
|
||||
@@ -7,11 +7,11 @@
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1756239746,
|
||||
"narHash": "sha256-0ibN685tT+u/Nbmbrrq9G3mRUzct2Votyv/a7Wwv26s=",
|
||||
"lastModified": 1775939535,
|
||||
"narHash": "sha256-Zq1U7Vhw5ctvhJQy+3ShqIv7Mplf3XkgJY+QJnhfUGQ=",
|
||||
"owner": "tadfisher",
|
||||
"repo": "android-nixpkgs",
|
||||
"rev": "256631d162ec883b2341ee59621516e1f65f0f6b",
|
||||
"rev": "d2e16192309bf3101e4998ffa62e914819dee077",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -28,11 +28,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1741473158,
|
||||
"narHash": "sha256-kWNaq6wQUbUMlPgw8Y+9/9wP0F8SHkjy24/mN3UAppg=",
|
||||
"lastModified": 1768818222,
|
||||
"narHash": "sha256-460jc0+CZfyaO8+w8JNtlClB2n4ui1RbHfPTLkpwhU8=",
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"rev": "7c9e793ebe66bcba8292989a68c0419b737a22a0",
|
||||
"rev": "255a2b1725a20d060f566e4755dbf571bbbb5f76",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -79,11 +79,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1756125398,
|
||||
"narHash": "sha256-XexyKZpf46cMiO5Vbj+dWSAXOnr285GHsMch8FBoHbc=",
|
||||
"lastModified": 1775710090,
|
||||
"narHash": "sha256-ar3rofg+awPB8QXDaFJhJ2jJhu+KqN/PRCXeyuXR76E=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "3b9f00d7a7bf68acd4c4abb9d43695afb04e03a5",
|
||||
"rev": "4c1018dae018162ec878d42fec712642d214fdfa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -95,11 +95,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1756159630,
|
||||
"narHash": "sha256-ohMvsjtSVdT/bruXf5ClBh8ZYXRmD4krmjKrXhEvwMg=",
|
||||
"lastModified": 1775823930,
|
||||
"narHash": "sha256-ALT447J7FcxP/97J01A/gp/hgdO5lXRsm+zLMt+gIjc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "84c256e42600cb0fdf25763b48d28df2f25a0c8b",
|
||||
"rev": "8c11f88bb9573a10a7d6bf87161ef08455ac70b9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -138,11 +138,11 @@
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1756197489,
|
||||
"narHash": "sha256-S16rPaBH1TnMbDyL5NlGSJcYd7wPlOEWTStdBDL7BHw=",
|
||||
"lastModified": 1775877051,
|
||||
"narHash": "sha256-wpSQm2PD/w4uRo2wb8utk0b5hOBkkg/CZ1xICY+qB7M=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "8ec04f46f1edeeed3f870da62191745b93975da7",
|
||||
"rev": "08b4f3633471874c8894632ade1b78d75dbda002",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
build-tools-35-0-0
|
||||
cmdline-tools-latest
|
||||
platform-tools
|
||||
platforms-android-35
|
||||
platforms-android-36
|
||||
ndk-27-2-12479018
|
||||
]);
|
||||
rust-version = pkgs.lib.removeSuffix "\n"
|
||||
|
||||
@@ -153,6 +153,42 @@ static uint32_t* jintArray2uint32Pointer(JNIEnv* env, jintArray ja, int* ret_icn
|
||||
}
|
||||
|
||||
|
||||
/************************************************************
|
||||
* DcEventChannel
|
||||
************************************************************/
|
||||
|
||||
static dc_event_channel_t* get_dc_event_channel(JNIEnv *env, jobject obj)
|
||||
{
|
||||
static jfieldID fid = 0;
|
||||
if (fid==0) {
|
||||
jclass cls = (*env)->GetObjectClass(env, obj);
|
||||
fid = (*env)->GetFieldID(env, cls, "eventChannelCPtr", "J" /*Signature, J=long*/);
|
||||
}
|
||||
if (fid) {
|
||||
return (dc_event_channel_t*)(*env)->GetLongField(env, obj, fid);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_DcEventChannel_createEventChannelCPtr(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jlong)dc_event_channel_new();
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcEventChannel_unrefEventChannelCPtr(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_event_channel_unref(get_dc_event_channel(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_DcEventChannel_getEventEmitterCPtr(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jlong)dc_event_channel_get_event_emitter(get_dc_event_channel(env, obj));
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* DcAccounts
|
||||
******************************************************************************/
|
||||
@@ -172,11 +208,11 @@ static dc_accounts_t* get_dc_accounts(JNIEnv *env, jobject obj)
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_DcAccounts_createAccountsCPtr(JNIEnv *env, jobject obj, jstring dir)
|
||||
JNIEXPORT jlong Java_com_b44t_messenger_DcAccounts_createAccountsCPtr(JNIEnv *env, jobject obj, jstring dir, jobject chanObj)
|
||||
{
|
||||
CHAR_REF(dir);
|
||||
int writable = 1;
|
||||
jlong accountsCPtr = (jlong)dc_accounts_new(dirPtr, writable);
|
||||
jlong accountsCPtr = (jlong)dc_accounts_new_with_event_channel(dirPtr, writable, get_dc_event_channel(env, chanObj));
|
||||
CHAR_UNREF(dir);
|
||||
return accountsCPtr;
|
||||
}
|
||||
@@ -231,6 +267,12 @@ JNIEXPORT jboolean Java_com_b44t_messenger_DcAccounts_backgroundFetch(JNIEnv *en
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcAccounts_stopBackgroundFetch(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_accounts_stop_background_fetch(get_dc_accounts(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcAccounts_migrateAccount(JNIEnv *env, jobject obj, jstring dbfile)
|
||||
{
|
||||
CHAR_REF(dbfile);
|
||||
@@ -904,18 +946,6 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcContext_getContactEncrInfo(JNIEnv *e
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcContext_initiateKeyTransfer(JNIEnv *env, jobject obj)
|
||||
{
|
||||
jstring setup_code = NULL;
|
||||
char* temp = dc_initiate_key_transfer(get_dc_context(env, obj));
|
||||
if (temp) {
|
||||
setup_code = JSTRING_NEW(temp);
|
||||
dc_str_unref(temp);
|
||||
}
|
||||
return setup_code;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_imex(JNIEnv *env, jobject obj, jint what, jstring dir)
|
||||
{
|
||||
CHAR_REF(dir);
|
||||
@@ -1363,6 +1393,7 @@ JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getId(JNIEnv *env, jobject obj)
|
||||
return dc_msg_get_id(get_dc_msg(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getText(JNIEnv *env, jobject obj)
|
||||
{
|
||||
char* temp = dc_msg_get_text(get_dc_msg(env, obj));
|
||||
@@ -1588,15 +1619,6 @@ JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_hasHtml(JNIEnv *env, jobject ob
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getSetupCodeBegin(JNIEnv *env, jobject obj)
|
||||
{
|
||||
char* temp = dc_msg_get_setupcodebegin(get_dc_msg(env, obj));
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
dc_str_unref(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setSubject(JNIEnv *env, jobject obj, jstring text)
|
||||
{
|
||||
CHAR_REF(text);
|
||||
@@ -1621,12 +1643,6 @@ JNIEXPORT void Java_com_b44t_messenger_DcMsg_setHtml(JNIEnv *env, jobject obj, j
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcMsg_forceSticker(JNIEnv *env, jobject obj)
|
||||
{
|
||||
dc_msg_force_sticker(get_dc_msg(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getPOILocation(JNIEnv *env, jobject obj)
|
||||
{
|
||||
char* temp = dc_msg_get_poi_location(get_dc_msg(env, obj));
|
||||
@@ -1951,7 +1967,7 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcBackupProvider_getQr(JNIEnv *env, jo
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcBackupProvider_getQrSvg(JNIEnv *env, jobject obj)
|
||||
{
|
||||
char* temp = dc_backup_provider_get_qr_svg(get_dc_backup_provider(env, obj));
|
||||
char* temp = dc_create_qr_svg(dc_backup_provider_get_qr(get_dc_backup_provider(env, obj)));
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
dc_str_unref(temp);
|
||||
return ret;
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
.PHONY: apk
|
||||
apk:
|
||||
./scripts/rebrand.sh
|
||||
./gradlew --offline assembleGplayRelease
|
||||
./scripts/undo_rebrand.sh
|
||||
|
||||
.PHONY: aab
|
||||
aab:
|
||||
./scripts/rebrand.sh
|
||||
sed -i 's/signingConfigs.releaseApk/signingConfigs.releaseBundle/g' build.gradle
|
||||
./gradlew --offline bundleGplayRelease
|
||||
sed -i 's/signingConfigs.releaseBundle/signingConfigs.releaseApk/g' build.gradle
|
||||
./scripts/undo_rebrand.sh
|
||||
|
||||
.PHONY: foss
|
||||
foss:
|
||||
./scripts/rebrand.sh
|
||||
./gradlew --offline assembleFossRelease
|
||||
./scripts/undo_rebrand.sh
|
||||
|
||||
.PHONY: install
|
||||
install:
|
||||
adb -d install -r build/outputs/apk/gplay/release/*universal*.apk
|
||||
|
||||
.PHONY: emulator-install
|
||||
emulator-install:
|
||||
adb install -r build/outputs/apk/gplay/release/*universal*.apk
|
||||
|
||||
.PHONY: fetch
|
||||
fetch:
|
||||
git fetch upstream
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
./gradlew --offline clean
|
||||
|
||||
|
||||
# CORE:
|
||||
|
||||
.PHONY: fetch-core
|
||||
fetch-core:
|
||||
cd ../core && git fetch upstream
|
||||
|
||||
.PHONY: core
|
||||
core:
|
||||
rmdir jni/deltachat-core-rust; mv ../core jni/deltachat-core-rust; true
|
||||
./scripts/ndk-make.sh; true
|
||||
./scripts/undo_rebrand.sh
|
||||
mv jni/deltachat-core-rust ../core
|
||||
mkdir jni/deltachat-core-rust
|
||||
|
||||
.PHONY: core-fast
|
||||
core-fast:
|
||||
rmdir jni/deltachat-core-rust; mv ../core jni/deltachat-core-rust; true
|
||||
./scripts/ndk-make.sh arm64-v8a; true
|
||||
./scripts/undo_rebrand.sh
|
||||
mv jni/deltachat-core-rust ../core
|
||||
mkdir jni/deltachat-core-rust
|
||||
|
||||
.PHONY: core-v7
|
||||
core-v7:
|
||||
rmdir jni/deltachat-core-rust; mv ../core jni/deltachat-core-rust; true
|
||||
./scripts/ndk-make.sh armeabi-v7a; true
|
||||
./scripts/undo_rebrand.sh
|
||||
mv jni/deltachat-core-rust ../core
|
||||
mkdir jni/deltachat-core-rust
|
||||
|
||||
.PHONY: core-x86
|
||||
core-x86:
|
||||
rmdir jni/deltachat-core-rust; mv ../core jni/deltachat-core-rust; true
|
||||
./scripts/ndk-make.sh x86; true
|
||||
./scripts/undo_rebrand.sh
|
||||
mv jni/deltachat-core-rust ../core
|
||||
mkdir jni/deltachat-core-rust
|
||||
|
||||
.PHONY: link
|
||||
link:
|
||||
rmdir jni/deltachat-core-rust; mv ../core jni/deltachat-core-rust; true
|
||||
|
||||
.PHONY: unlink
|
||||
unlink:
|
||||
mv jni/deltachat-core-rust ../core
|
||||
mkdir jni/deltachat-core-rust
|
||||
@@ -13,3 +13,8 @@
|
||||
-keep class org.thoughtcrime.securesms.crypto.KeyStoreHelper* { *; }
|
||||
|
||||
-dontwarn com.google.firebase.analytics.connector.AnalyticsConnector
|
||||
|
||||
# Keep WebRTC classes
|
||||
-keep class org.webrtc.** { *; }
|
||||
-keepclassmembers class org.webrtc.** { *; }
|
||||
-keepattributes InnerClasses
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
rm src/main/assets/help/*.png
|
||||
../deltachat-pages/tools/create-local-help.py ../deltachat-pages/result src/main/assets/help
|
||||
|
||||
@@ -6,3 +6,4 @@ find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/Delta Chat
|
||||
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/get.delta.chat/github.com\/ArcaneChat/g'
|
||||
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/delta.chat\/donate/arcanechat.me\/#contribute/g'
|
||||
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/Delta Chat/ArcaneChat/g'
|
||||
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/❤️/💜/g'
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.86.0
|
||||
1.91.1
|
||||
|
||||
@@ -6,6 +6,7 @@ find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/ArcaneChat
|
||||
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/github.com\/ArcaneChat/get.delta.chat/g'
|
||||
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/arcanechat.me\/#contribute/delta.chat\/donate/g'
|
||||
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/ArcaneChat/Delta Chat/g'
|
||||
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/💜/❤️/g'
|
||||
|
||||
# don't revert the app name
|
||||
sed -i 's/>Delta Chat</>ArcaneChat</g' ./src/main/res/values/strings.xml
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/bin/sh
|
||||
# you need to have dcrpcgen
|
||||
|
||||
# generate schema.json
|
||||
ROOT_DIR=$PWD
|
||||
cd ./jni/deltachat-core-rust/deltachat-rpc-server
|
||||
cargo run -- --openrpc > "$ROOT_DIR/schema.json"
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
# generate code
|
||||
dcrpcgen java --schema schema.json -o ./src/main/java/
|
||||
rm schema.json
|
||||
@@ -34,6 +34,7 @@ cd ../..
|
||||
SYMBOLS_ZIP="$APK-symbols.zip"
|
||||
rm $SYMBOLS_ZIP
|
||||
zip -r $SYMBOLS_ZIP obj
|
||||
zip $SYMBOLS_ZIP build/outputs/mapping/gplayRelease/mapping.txt
|
||||
ls -l $SYMBOLS_ZIP
|
||||
rsync --progress $SYMBOLS_ZIP jekyll@download.delta.chat:/var/www/html/download/android/symbols/
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
eclipse.preferences.version=1
|
||||
lineWidth=100
|
||||
splitMultiAttrs=true
|
||||
indentMultipleAttributes=true
|
||||
indentationChar=space
|
||||
indentationSize=4
|
||||
spaceBeforeEmptyCloseTag=true
|
||||
@@ -11,7 +11,6 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.test.espresso.NoMatchingViewException;
|
||||
import androidx.test.espresso.UiController;
|
||||
@@ -19,7 +18,6 @@ import androidx.test.espresso.ViewAction;
|
||||
import androidx.test.espresso.ViewInteraction;
|
||||
import androidx.test.espresso.util.TreeIterables;
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||
|
||||
import org.hamcrest.Matcher;
|
||||
import org.thoughtcrime.securesms.ConversationListActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
@@ -60,10 +58,12 @@ public class TestUtils {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ActivityScenarioRule<ConversationListActivity> getOfflineActivityRule(boolean useExistingChats) {
|
||||
public static ActivityScenarioRule<ConversationListActivity> getOfflineActivityRule(
|
||||
boolean useExistingChats) {
|
||||
Intent intent =
|
||||
Intent.makeMainActivity(
|
||||
new ComponentName(getInstrumentation().getTargetContext(), ConversationListActivity.class));
|
||||
new ComponentName(
|
||||
getInstrumentation().getTargetContext(), ConversationListActivity.class));
|
||||
if (!useExistingChats) {
|
||||
createOfflineAccount();
|
||||
}
|
||||
@@ -72,18 +72,22 @@ public class TestUtils {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static <T extends Activity> ActivityScenarioRule<T> getOnlineActivityRule(Class<T> activityClass) {
|
||||
public static <T extends Activity> ActivityScenarioRule<T> getOnlineActivityRule(
|
||||
Class<T> activityClass) {
|
||||
Context context = getInstrumentation().getTargetContext();
|
||||
AccountManager.getInstance().beginAccountCreation(context);
|
||||
prepare();
|
||||
return new ActivityScenarioRule<>(new Intent(getInstrumentation().getTargetContext(), activityClass));
|
||||
return new ActivityScenarioRule<>(
|
||||
new Intent(getInstrumentation().getTargetContext(), activityClass));
|
||||
}
|
||||
|
||||
private static void prepare() {
|
||||
Prefs.setBooleanPreference(getInstrumentation().getTargetContext(), Prefs.DOZE_ASKED_DIRECTLY, true);
|
||||
Prefs.setBooleanPreference(
|
||||
getInstrumentation().getTargetContext(), Prefs.DOZE_ASKED_DIRECTLY, true);
|
||||
if (!AccessibilityUtil.areAnimationsDisabled(getInstrumentation().getTargetContext())) {
|
||||
throw new RuntimeException("To run the tests, disable animations at Developer options' " +
|
||||
"-> 'Window/Transition/Animator animation scale' -> Set all 3 to 'off'");
|
||||
throw new RuntimeException(
|
||||
"To run the tests, disable animations at Developer options' "
|
||||
+ "-> 'Window/Transition/Animator animation scale' -> Set all 3 to 'off'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,18 +128,14 @@ public class TestUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform action of implicitly waiting for a certain view.
|
||||
* This differs from EspressoExtensions.searchFor in that,
|
||||
* upon failure to locate an element, it will fetch a new root view
|
||||
* in which to traverse searching for our @param match
|
||||
* Perform action of implicitly waiting for a certain view. This differs from
|
||||
* EspressoExtensions.searchFor in that, upon failure to locate an element, it will fetch a new
|
||||
* root view in which to traverse searching for our @param match
|
||||
*
|
||||
* @param viewMatcher ViewMatcher used to find our view
|
||||
*/
|
||||
public static ViewInteraction waitForView(
|
||||
Matcher<View> viewMatcher,
|
||||
int waitMillis,
|
||||
int waitMillisPerTry
|
||||
) {
|
||||
Matcher<View> viewMatcher, int waitMillis, int waitMillisPerTry) {
|
||||
|
||||
// Derive the max tries
|
||||
int maxTries = (int) (waitMillis / waitMillisPerTry);
|
||||
@@ -164,12 +164,11 @@ public class TestUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Normally, you would do
|
||||
* onView(withId(R.id.send_button)).perform(click());
|
||||
* to send the draft message. However, in order to change the send button to the attach button
|
||||
* while there is no draft, the send button is made invisible and the attach button is made
|
||||
* visible instead. This confuses the test framework.<br/><br/>
|
||||
*
|
||||
* Normally, you would do onView(withId(R.id.send_button)).perform(click()); to send the draft
|
||||
* message. However, in order to change the send button to the attach button while there is no
|
||||
* draft, the send button is made invisible and the attach button is made visible instead. This
|
||||
* confuses the test framework.<br>
|
||||
* <br>
|
||||
* So, this is a workaround for pressing the send button.
|
||||
*/
|
||||
public static void pressSend() {
|
||||
|
||||
@@ -10,14 +10,11 @@ import static androidx.test.espresso.matcher.ViewMatchers.withId;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.test.espresso.contrib.RecyclerViewActions;
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
|
||||
import com.b44t.messenger.TestUtils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
@@ -34,18 +31,19 @@ public class EnterChatsBenchmark {
|
||||
// ==============================================================================================
|
||||
// Set this to true if you already have at least 10 chats on your existing DeltaChat installation
|
||||
// and want to traverse through them instead of 10 newly created chats
|
||||
private final static boolean USE_EXISTING_CHATS = false;
|
||||
private static final boolean USE_EXISTING_CHATS = false;
|
||||
// ==============================================================================================
|
||||
private final static int GO_THROUGH_ALL_CHATS_N_TIMES = 8;
|
||||
private static final int GO_THROUGH_ALL_CHATS_N_TIMES = 8;
|
||||
|
||||
// ==============================================================================================
|
||||
// PLEASE BACKUP YOUR ACCOUNT BEFORE RUNNING THIS!
|
||||
// ==============================================================================================
|
||||
|
||||
private final static String TAG = EnterChatsBenchmark.class.getSimpleName();
|
||||
private static final String TAG = "EnterChatsBenchmark";
|
||||
|
||||
@Rule
|
||||
public ActivityScenarioRule<ConversationListActivity> activityRule = TestUtils.getOfflineActivityRule(USE_EXISTING_CHATS);
|
||||
public ActivityScenarioRule<ConversationListActivity> activityRule =
|
||||
TestUtils.getOfflineActivityRule(USE_EXISTING_CHATS);
|
||||
|
||||
@Test
|
||||
public void createAndEnter10FilledChats() {
|
||||
@@ -55,7 +53,9 @@ public class EnterChatsBenchmark {
|
||||
for (int i = 0; i < GO_THROUGH_ALL_CHATS_N_TIMES; i++) {
|
||||
times[i] = "" + timeGoToNChats(10); // 10 group chats were created
|
||||
}
|
||||
Log.i(TAG, "MEASURED RESULTS (Benchmark) - Going thorough all 10 chats: " + String.join(",", times));
|
||||
Log.i(
|
||||
TAG,
|
||||
"MEASURED RESULTS (Benchmark) - Going thorough all 10 chats: " + String.join(",", times));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -66,13 +66,17 @@ public class EnterChatsBenchmark {
|
||||
for (int i = 0; i < GO_THROUGH_ALL_CHATS_N_TIMES; i++) {
|
||||
times[i] = "" + timeGoToNChats(1);
|
||||
}
|
||||
Log.i(TAG, "MEASURED RESULTS (Benchmark) - Entering and leaving 1 empty chat: " + String.join(",", times));
|
||||
Log.i(
|
||||
TAG,
|
||||
"MEASURED RESULTS (Benchmark) - Entering and leaving 1 empty chat: "
|
||||
+ String.join(",", times));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void enterFilledChat() {
|
||||
if (!USE_EXISTING_CHATS) {
|
||||
createChatAndGoBack("Group #1", true, "Hello!", "Some links: https://testrun.org", "And a command: /help");
|
||||
createChatAndGoBack(
|
||||
"Group #1", true, "Hello!", "Some links: https://testrun.org", "And a command: /help");
|
||||
}
|
||||
|
||||
String[] times = new String[50];
|
||||
@@ -82,7 +86,18 @@ public class EnterChatsBenchmark {
|
||||
long end = System.currentTimeMillis();
|
||||
long diff = end - start;
|
||||
pressBack();
|
||||
Log.i(TAG, "Measured (Benchmark) " + (i+1) + "/" + times.length + ": Entering 1 filled chat took " + diff + "ms " + "(going back took " + (System.currentTimeMillis() - end) + "ms)");
|
||||
Log.i(
|
||||
TAG,
|
||||
"Measured (Benchmark) "
|
||||
+ (i + 1)
|
||||
+ "/"
|
||||
+ times.length
|
||||
+ ": Entering 1 filled chat took "
|
||||
+ diff
|
||||
+ "ms "
|
||||
+ "(going back took "
|
||||
+ (System.currentTimeMillis() - end)
|
||||
+ "ms)");
|
||||
|
||||
times[i] = "" + diff;
|
||||
}
|
||||
@@ -91,16 +106,37 @@ public class EnterChatsBenchmark {
|
||||
|
||||
private void create10Chats(boolean fillWithMsgs) {
|
||||
if (!USE_EXISTING_CHATS) {
|
||||
createChatAndGoBack("Group #1", fillWithMsgs, "Hello!", "Some links: https://testrun.org", "And a command: /help");
|
||||
createChatAndGoBack("Group #2", fillWithMsgs, "example.org, alice@example.org", "aaaaaaa", "bbbbbb");
|
||||
createChatAndGoBack("Group #3", fillWithMsgs, repeat("Some string ", 600), repeat("Another string", 200), "Hi!!!");
|
||||
createChatAndGoBack(
|
||||
"Group #1",
|
||||
fillWithMsgs,
|
||||
"Hello!",
|
||||
"Some links: https://testrun.org",
|
||||
"And a command: /help");
|
||||
createChatAndGoBack(
|
||||
"Group #2", fillWithMsgs, "example.org, alice@example.org", "aaaaaaa", "bbbbbb");
|
||||
createChatAndGoBack(
|
||||
"Group #3",
|
||||
fillWithMsgs,
|
||||
repeat("Some string ", 600),
|
||||
repeat("Another string", 200),
|
||||
"Hi!!!");
|
||||
createChatAndGoBack("Group #4", fillWithMsgs, "xyzabc", "Hi!!!!", "Let's meet!");
|
||||
createChatAndGoBack("Group #5", fillWithMsgs, repeat("aaaa", 40), "bbbbbbbbbbbbbbbbbb", "ccccccccccccccc");
|
||||
createChatAndGoBack("Group #6", fillWithMsgs, "aaaaaaaaaaa", repeat("Hi! ", 1000), "bbbbbbbbbb");
|
||||
createChatAndGoBack("Group #7", fillWithMsgs, repeat("abcdefg ", 500), repeat("xxxxx", 100), "yrrrrrrrrrrrrr");
|
||||
createChatAndGoBack("Group #8", fillWithMsgs, "and a number: 037362/384756", "ccccc", "Nice!");
|
||||
createChatAndGoBack("Group #9", fillWithMsgs, "ddddddddddddddddd", "zuuuuuuuuuuuuuuuu", "ccccc");
|
||||
createChatAndGoBack("Group #10", fillWithMsgs, repeat("xxxxxxyyyyy", 100), repeat("String!!", 10), "abcd");
|
||||
createChatAndGoBack(
|
||||
"Group #5", fillWithMsgs, repeat("aaaa", 40), "bbbbbbbbbbbbbbbbbb", "ccccccccccccccc");
|
||||
createChatAndGoBack(
|
||||
"Group #6", fillWithMsgs, "aaaaaaaaaaa", repeat("Hi! ", 1000), "bbbbbbbbbb");
|
||||
createChatAndGoBack(
|
||||
"Group #7",
|
||||
fillWithMsgs,
|
||||
repeat("abcdefg ", 500),
|
||||
repeat("xxxxx", 100),
|
||||
"yrrrrrrrrrrrrr");
|
||||
createChatAndGoBack(
|
||||
"Group #8", fillWithMsgs, "and a number: 037362/384756", "ccccc", "Nice!");
|
||||
createChatAndGoBack(
|
||||
"Group #9", fillWithMsgs, "ddddddddddddddddd", "zuuuuuuuuuuuuuuuu", "ccccc");
|
||||
createChatAndGoBack(
|
||||
"Group #10", fillWithMsgs, repeat("xxxxxxyyyyy", 100), repeat("String!!", 10), "abcd");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,10 +166,10 @@ public class EnterChatsBenchmark {
|
||||
onView(withContentDescription(R.string.group_create_button)).perform(click());
|
||||
|
||||
if (fillWithMsgs) {
|
||||
for (String t: texts) {
|
||||
for (String t : texts) {
|
||||
sendText(t);
|
||||
}
|
||||
for (String t: texts) {
|
||||
for (String t : texts) {
|
||||
sendText(t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,10 @@ import androidx.test.espresso.contrib.RecyclerViewActions;
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.TestUtils;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
@@ -29,8 +28,6 @@ import org.thoughtcrime.securesms.ConversationListActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class ForwardingTest {
|
||||
@@ -43,7 +40,8 @@ public class ForwardingTest {
|
||||
}
|
||||
|
||||
@Rule
|
||||
public final ActivityScenarioRule<ConversationListActivity> activityRule = TestUtils.getOfflineActivityRule(false);
|
||||
public final ActivityScenarioRule<ConversationListActivity> activityRule =
|
||||
TestUtils.getOfflineActivityRule(false);
|
||||
|
||||
@Before
|
||||
public void createChats() {
|
||||
@@ -51,10 +49,13 @@ public class ForwardingTest {
|
||||
dcContext.createChatByContactId(DcContact.DC_CONTACT_ID_SELF);
|
||||
// Disable bcc_self so that DC doesn't try to send messages to the server.
|
||||
// If we didn't do this, messages would stay in DC_STATE_OUT_PENDING forever.
|
||||
// The thing is, DC_STATE_OUT_PENDING show a rotating circle animation, and Espresso doesn't work
|
||||
// The thing is, DC_STATE_OUT_PENDING show a rotating circle animation, and Espresso doesn't
|
||||
// work
|
||||
// with animations, and the tests would hang and never finish.
|
||||
dcContext.setConfig("bcc_self", "0");
|
||||
activityRule.getScenario().onActivity(a -> createdGroupId = DcHelper.getContext(a).createGroupChat( "group"));
|
||||
activityRule
|
||||
.getScenario()
|
||||
.onActivity(a -> createdGroupId = DcHelper.getContext(a).createGroupChat("group"));
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -68,7 +69,8 @@ public class ForwardingTest {
|
||||
// The group is at position 0, self chat is at position 1, device talk is at position 2
|
||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(2, click()));
|
||||
onView(withId(R.id.title)).check(matches(withText(R.string.device_talk)));
|
||||
onView(withId(android.R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, longClick()));
|
||||
onView(withId(android.R.id.list))
|
||||
.perform(RecyclerViewActions.actionOnItemAtPosition(0, longClick()));
|
||||
onView(withId(R.id.menu_context_forward)).perform(click());
|
||||
// Send it to self chat (which is sorted to the top because we're forwarding)
|
||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
|
||||
@@ -77,11 +79,13 @@ public class ForwardingTest {
|
||||
|
||||
pressBack();
|
||||
|
||||
onView(withId(R.id.toolbar_title)).check(matches(withText(R.string.connectivity_not_connected)));
|
||||
onView(withId(R.id.toolbar_title))
|
||||
.check(matches(withText(R.string.connectivity_not_connected)));
|
||||
// Self chat moved up because we sent a message there
|
||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
|
||||
onView(withId(R.id.title)).check(matches(withText(R.string.saved_messages)));
|
||||
onView(withId(android.R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, longClick()));
|
||||
onView(withId(android.R.id.list))
|
||||
.perform(RecyclerViewActions.actionOnItemAtPosition(0, longClick()));
|
||||
onView(withId(R.id.menu_context_forward)).perform(click());
|
||||
// Send it to the group
|
||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(1, click()));
|
||||
@@ -89,6 +93,7 @@ public class ForwardingTest {
|
||||
onView(withId(R.id.title)).check(matches(withText("group")));
|
||||
|
||||
pressBack();
|
||||
onView(withId(R.id.toolbar_title)).check(matches(withText(R.string.connectivity_not_connected)));
|
||||
onView(withId(R.id.toolbar_title))
|
||||
.check(matches(withText(R.string.connectivity_not_connected)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,13 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
|
||||
import androidx.test.espresso.contrib.RecyclerViewActions;
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.TestUtils;
|
||||
|
||||
import java.io.File;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
@@ -34,9 +32,6 @@ import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.ShareActivity;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@LargeTest
|
||||
public class SharingTest {
|
||||
@@ -48,16 +43,22 @@ public class SharingTest {
|
||||
private static int createdSingleChatId;
|
||||
|
||||
@Rule
|
||||
public final ActivityScenarioRule<ConversationListActivity> activityRule = TestUtils.getOfflineActivityRule(false);
|
||||
public final ActivityScenarioRule<ConversationListActivity> activityRule =
|
||||
TestUtils.getOfflineActivityRule(false);
|
||||
|
||||
@Before
|
||||
public void createGroup() {
|
||||
activityRule.getScenario().onActivity(a -> createdGroupId = DcHelper.getContext(a).createGroupChat( "group"));
|
||||
activityRule
|
||||
.getScenario()
|
||||
.onActivity(a -> createdGroupId = DcHelper.getContext(a).createGroupChat("group"));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void createSingleChat() {
|
||||
activityRule.getScenario().onActivity(a -> {
|
||||
activityRule
|
||||
.getScenario()
|
||||
.onActivity(
|
||||
a -> {
|
||||
int contactId = DcHelper.getContext(a).createContact("", "abc@example.org");
|
||||
createdSingleChatId = DcHelper.getContext(a).createChatByContactId(contactId);
|
||||
});
|
||||
@@ -67,7 +68,9 @@ public class SharingTest {
|
||||
public void testNormalSharing() {
|
||||
Intent i = new Intent(Intent.ACTION_SEND);
|
||||
i.putExtra(Intent.EXTRA_TEXT, "Hello!");
|
||||
i.setComponent(new ComponentName(getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
||||
i.setComponent(
|
||||
new ComponentName(
|
||||
getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
||||
activityRule.getScenario().onActivity(a -> a.startActivity(i));
|
||||
|
||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItemAtPosition(0, click()));
|
||||
@@ -77,9 +80,9 @@ public class SharingTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test direct sharing from a screenshot.
|
||||
* Also, this is the regression test for https://github.com/deltachat/deltachat-android/issues/2040
|
||||
* where network changes during sharing lead to a bug
|
||||
* Test direct sharing from a screenshot. Also, this is the regression test for
|
||||
* https://github.com/deltachat/deltachat-android/issues/2040 where network changes during sharing
|
||||
* lead to a bug
|
||||
*/
|
||||
@Test
|
||||
public void testShareFromScreenshot() {
|
||||
@@ -92,20 +95,25 @@ public class SharingTest {
|
||||
pngImage = file;
|
||||
}
|
||||
}
|
||||
Uri uri = Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".attachments/" + Uri.encode(pngImage));
|
||||
Uri uri =
|
||||
Uri.parse(
|
||||
"content://" + BuildConfig.APPLICATION_ID + ".attachments/" + Uri.encode(pngImage));
|
||||
DcHelper.sharedFiles.put(pngImage, "image/png");
|
||||
|
||||
Intent i = new Intent(Intent.ACTION_SEND);
|
||||
i.setType("image/png");
|
||||
i.putExtra(Intent.EXTRA_SUBJECT, "Screenshot (Sep 27, 2021 00:00:00");
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
|
||||
i.setFlags(
|
||||
Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET
|
||||
| Intent.FLAG_ACTIVITY_FORWARD_RESULT
|
||||
| Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP
|
||||
| Intent.FLAG_RECEIVER_FOREGROUND
|
||||
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
i.putExtra(Intent.EXTRA_STREAM, uri);
|
||||
i.putExtra(ShareActivity.EXTRA_CHAT_ID, createdGroupId);
|
||||
i.setComponent(new ComponentName(getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
||||
i.setComponent(
|
||||
new ComponentName(
|
||||
getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
||||
activityRule.getScenario().onActivity(a -> a.startActivity(i));
|
||||
|
||||
TestUtils.waitForView(withId(R.id.send_button), 10000, 50);
|
||||
@@ -121,16 +129,32 @@ public class SharingTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests https://github.com/deltachat/interface/blob/master/user-testing/mailto-links.md#mailto-links:
|
||||
* Tests
|
||||
* https://github.com/deltachat/interface/blob/master/user-testing/mailto-links.md#mailto-links:
|
||||
*
|
||||
* <ul dir="auto">
|
||||
* <li><a href="mailto:abc@example.org">Just an email address</a> - should open a chat with <code>abc@example.org</code> (and maybe ask whether a chat should be created if it does not exist already)</li>
|
||||
* <li><a href="mailto:abc@example.org?subject=testing%20mailto%20uris">email address with subject</a> - should open a chat with <code>abc@example.org</code> and fill <code>testing mailto uris</code>; as we created the chat in the previous step, it should not ask <code>Chat with …</code> but directly open the chat</li>
|
||||
* <li><a href="mailto:abc@example.org?body=this%20is%20a%20test">email address with body</a> - should open a chat with <code>abc@example.org</code>, draft <code>this is a test</code></li>
|
||||
* <li><a href="mailto:abc@example.org?subject=testing%20mailto%20uris&body=this%20is%20a%20test">email address with subject and body</a> - should open a chat with <code>abc@example.org</code>, draft <code>testing mailto uris</code> <newline> <code>this is a test</code></li>
|
||||
* <li><a href="mailto:%20info@example.org">HTML encoding</a> - should open a chat with <code>info@example.org</code></li>
|
||||
* <li><a href="mailto:simplebot@example.org?body=!web%20https%3A%2F%2Fduckduckgo.com%2Flite%3Fq%3Dduck%2520it">more HTML encoding</a> - should open a chat with <code>simplebot@example.org</code>, draft <code>!web https://duckduckgo.com/lite?q=duck%20it</code></li>
|
||||
* <li><a href="mailto:?subject=bla&body=blub">no email, just subject&body</a> - this should let you choose a chat and create a draft <code>bla</code> <newline> <code>blub</code> there</li>
|
||||
* <li><a href="mailto:abc@example.org">Just an email address</a> - should open a chat with
|
||||
* <code>abc@example.org</code> (and maybe ask whether a chat should be created if it does
|
||||
* not exist already)
|
||||
* <li><a href="mailto:abc@example.org?subject=testing%20mailto%20uris">email address with
|
||||
* subject</a> - should open a chat with <code>abc@example.org</code> and fill <code>
|
||||
* testing mailto uris</code>; as we created the chat in the previous step, it should not
|
||||
* ask <code>Chat with …</code> but directly open the chat
|
||||
* <li><a href="mailto:abc@example.org?body=this%20is%20a%20test">email address with body</a> -
|
||||
* should open a chat with <code>abc@example.org</code>, draft <code>this is a test</code>
|
||||
* <li><a
|
||||
* href="mailto:abc@example.org?subject=testing%20mailto%20uris&body=this%20is%20a%20test">email
|
||||
* address with subject and body</a> - should open a chat with <code>abc@example.org</code>,
|
||||
* draft <code>testing mailto uris</code> <newline> <code>this is a test</code>
|
||||
* <li><a href="mailto:%20info@example.org">HTML encoding</a> - should open a chat with <code>
|
||||
* info@example.org</code>
|
||||
* <li><a
|
||||
* href="mailto:simplebot@example.org?body=!web%20https%3A%2F%2Fduckduckgo.com%2Flite%3Fq%3Dduck%2520it">more
|
||||
* HTML encoding</a> - should open a chat with <code>simplebot@example.org</code>, draft
|
||||
* <code>!web https://duckduckgo.com/lite?q=duck%20it</code>
|
||||
* <li><a href="mailto:?subject=bla&body=blub">no email, just subject&body</a> - this
|
||||
* should let you choose a chat and create a draft <code>bla</code> <newline> <code>
|
||||
* blub</code> there
|
||||
* </ul>
|
||||
*/
|
||||
@Test
|
||||
@@ -140,7 +164,8 @@ public class SharingTest {
|
||||
|
||||
openLink("mailto:abc@example.org?subject=testing%20mailto%20uris");
|
||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("testing mailto uris")));
|
||||
onView(withHint(R.string.chat_input_placeholder))
|
||||
.check(matches(withText("testing mailto uris")));
|
||||
|
||||
openLink("mailto:abc@example.org?body=this%20is%20a%20test");
|
||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||
@@ -148,17 +173,22 @@ public class SharingTest {
|
||||
|
||||
openLink("mailto:abc@example.org?subject=testing%20mailto%20uris&body=this%20is%20a%20test");
|
||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("testing mailto uris\nthis is a test")));
|
||||
onView(withHint(R.string.chat_input_placeholder))
|
||||
.check(matches(withText("testing mailto uris\nthis is a test")));
|
||||
|
||||
openLink("mailto:%20abc@example.org");
|
||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||
|
||||
openLink("mailto:abc@example.org?body=!web%20https%3A%2F%2Fduckduckgo.com%2Flite%3Fq%3Dduck%2520it");
|
||||
openLink(
|
||||
"mailto:abc@example.org?body=!web%20https%3A%2F%2Fduckduckgo.com%2Flite%3Fq%3Dduck%2520it");
|
||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("!web https://duckduckgo.com/lite?q=duck%20it")));
|
||||
onView(withHint(R.string.chat_input_placeholder))
|
||||
.check(matches(withText("!web https://duckduckgo.com/lite?q=duck%20it")));
|
||||
|
||||
openLink("mailto:?subject=bla&body=blub");
|
||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||
onView(withId(R.id.list))
|
||||
.perform(
|
||||
RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||
onView(withId(R.id.subtitle)).check(matches(withText("abc@example.org")));
|
||||
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("bla\nblub")));
|
||||
}
|
||||
@@ -170,49 +200,61 @@ public class SharingTest {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <ul dir="auto">
|
||||
* <li>Open Saved Messages chat (could be any other chat too)</li>
|
||||
* <li>Go to another app and share some text to DC</li>
|
||||
* <li>In DC select Saved Messages. Edit the shared text if you like. <em>Don't</em> hit the Send button.</li>
|
||||
* <li>Leave DC</li>
|
||||
* <li>Open DC again from the "Recent apps"</li>
|
||||
* <li>Check that your draft is still there</li>
|
||||
* <li>Open Saved Messages chat (could be any other chat too)
|
||||
* <li>Go to another app and share some text to DC
|
||||
* <li>In DC select Saved Messages. Edit the shared text if you like. <em>Don't</em> hit the
|
||||
* Send button.
|
||||
* <li>Leave DC
|
||||
* <li>Open DC again from the "Recent apps"
|
||||
* <li>Check that your draft is still there
|
||||
* </ul>
|
||||
*/
|
||||
@Test
|
||||
public void testOpenAgainFromRecents() {
|
||||
// Open a chat
|
||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||
onView(withId(R.id.list))
|
||||
.perform(
|
||||
RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||
|
||||
// Share some text to DC
|
||||
Intent i = new Intent(Intent.ACTION_SEND);
|
||||
i.putExtra(Intent.EXTRA_TEXT, "Veeery important draft");
|
||||
i.setComponent(new ComponentName(getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
||||
i.setComponent(
|
||||
new ComponentName(
|
||||
getInstrumentation().getTargetContext().getApplicationContext(), ShareActivity.class));
|
||||
activityRule.getScenario().onActivity(a -> a.startActivity(i));
|
||||
|
||||
// In DC, select the same chat you opened before
|
||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||
onView(withId(R.id.list))
|
||||
.perform(
|
||||
RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||
|
||||
// Leave DC and go back to the previous activity
|
||||
pressBack();
|
||||
|
||||
// Here, we can't exactly replicate the "steps to reproduce". Previously, the other activity
|
||||
// stayed open in the background, but since it doesn't anymore, we need to open it again:
|
||||
onView(withId(R.id.list)).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||
onView(withId(R.id.list))
|
||||
.perform(
|
||||
RecyclerViewActions.actionOnItem(hasDescendant(withText("abc@example.org")), click()));
|
||||
|
||||
// Check that the draft is still there
|
||||
// Util.sleep(2000); // Uncomment for debugging
|
||||
onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("Veeery important draft")));
|
||||
onView(withHint(R.string.chat_input_placeholder))
|
||||
.check(matches(withText("Veeery important draft")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Regression test:
|
||||
*
|
||||
* If you save your contacts's emails in the contacts app of the phone, there are buttons to call
|
||||
* them and also to write an email to them.
|
||||
* <p>If you save your contacts's emails in the contacts app of the phone, there are buttons to
|
||||
* call them and also to write an email to them.
|
||||
*
|
||||
* If you click the email button, ArcaneChat opened but instead of opening a chat with that contact,
|
||||
* the chat list was show and "share with" was displayed at the top
|
||||
* <p>If you click the email button, Delta Chat opened but instead of opening a chat with that
|
||||
* contact, the chat list was show and "share with" was displayed at the top
|
||||
*/
|
||||
@Test
|
||||
public void testOpenChatFromContacts() {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.b44t.messenger.uitests.online;
|
||||
|
||||
|
||||
import static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.action.ViewActions.replaceText;
|
||||
@@ -11,13 +10,10 @@ import static androidx.test.espresso.matcher.ViewMatchers.withHint;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.LargeTest;
|
||||
|
||||
import com.b44t.messenger.TestUtils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
@@ -30,18 +26,20 @@ import org.thoughtcrime.securesms.WelcomeActivity;
|
||||
@LargeTest
|
||||
public class OnboardingTest {
|
||||
@Rule
|
||||
public ActivityScenarioRule<WelcomeActivity> activityRule = TestUtils.getOnlineActivityRule(WelcomeActivity.class);
|
||||
public ActivityScenarioRule<WelcomeActivity> activityRule =
|
||||
TestUtils.getOnlineActivityRule(WelcomeActivity.class);
|
||||
|
||||
@Test
|
||||
public void testAccountCreation() {
|
||||
if (TextUtils.isEmpty(BuildConfig.TEST_ADDR) || TextUtils.isEmpty(BuildConfig.TEST_MAIL_PW)) {
|
||||
throw new RuntimeException("You need to set TEST_ADDR and TEST_MAIL_PW; " +
|
||||
"either in gradle.properties or via an environment variable. " +
|
||||
"See README.md for more details.");
|
||||
throw new RuntimeException(
|
||||
"You need to set TEST_ADDR and TEST_MAIL_PW; "
|
||||
+ "either in gradle.properties or via an environment variable. "
|
||||
+ "See README.md for more details.");
|
||||
}
|
||||
onView(withText(R.string.scan_invitation_code)).check(matches(isClickable()));
|
||||
onView(withText(R.string.import_backup_title)).check(matches(isClickable()));
|
||||
onView(withText(R.string.login_header)).perform(click());
|
||||
onView(withText(R.string.manual_account_setup_option)).perform(click());
|
||||
onView(withHint(R.string.email_address)).perform(replaceText(BuildConfig.TEST_ADDR));
|
||||
onView(withHint(R.string.existing_password)).perform(replaceText(BuildConfig.TEST_MAIL_PW));
|
||||
onView(withContentDescription(R.string.ok)).perform(click());
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="228"
|
||||
android:viewportHeight="280">
|
||||
<group
|
||||
android:scaleX="0.35014287"
|
||||
android:scaleY="0.43"
|
||||
android:translateX="74.08372"
|
||||
android:translateY="79.8">
|
||||
<path
|
||||
android:pathData="m10.03,234.14c0.3,-0.01 0.6,-0.02 0.9,-0.04 -0.07,-0.49 -0.14,-0.97 -0.2,-1.46 -0.15,-1.34 -0.26,-2.69 -0.25,-4.04 -0.02,-0.86 -0.05,-1.71 -0.07,-2.57 -0.09,-0.06 -0.18,-0.13 -0.27,-0.19 -0.02,-0.02 -0.04,-0.03 -0.07,-0.05zM44.87,232.95c11.71,-8.35 26.86,-14.79 46.21,-15.9 0,0 39.93,-0.27 47.91,-3.53 7.98,-3.26 68.68,-14.69 82.94,-98.43 14.26,-83.74 -1.06,-115.09 -1.06,-115.09 0,0 -21.14,55.68 -81.02,59.81 0,0 -14.5,1.03 -38.82,1.42 -24.32,0.39 -75.77,20.65 -90.55,85.62l-0.22,43.44c2.5,4.22 5.49,8.12 8.91,11.66 3.99,4.11 8.11,8.12 12.79,11.45 2.26,1.65 4.65,3.2 6.51,5.33 1.94,2.34 3.33,5 4.2,7.93 0.71,2.1 1.45,4.2 2.2,6.28z"
|
||||
android:fillColor="@color/ic_launcher_background" />
|
||||
<path
|
||||
android:pathData="m217.97,45.86c-0.3,0.01 -0.6,0.02 -0.9,0.04 0.07,0.49 0.14,0.97 0.2,1.46 0.15,1.34 0.26,2.69 0.25,4.04 0.02,0.86 0.05,1.71 0.07,2.57 0.09,0.06 0.18,0.13 0.27,0.19 0.02,0.02 0.04,0.03 0.07,0.05zM183.13,47.05c-11.71,8.35 -26.86,14.79 -46.21,15.9 0,0 -39.93,0.27 -47.91,3.53 -7.98,3.26 -68.68,14.69 -82.94,98.43 -14.26,83.74 1.06,115.09 1.06,115.09 0,0 21.14,-55.68 81.02,-59.81 0,0 14.5,-1.03 38.82,-1.42 24.32,-0.39 75.77,-20.65 90.55,-85.62l0.22,-43.44c-2.5,-4.22 -5.49,-8.12 -8.91,-11.66 -3.99,-4.11 -8.11,-8.12 -12.79,-11.45 -2.26,-1.65 -4.65,-3.2 -6.51,-5.33 -1.94,-2.34 -3.33,-5 -4.2,-7.93 -0.71,-2.1 -1.45,-4.2 -2.2,-6.28z"
|
||||
android:fillColor="@color/ic_launcher_background" />
|
||||
</group>
|
||||
</vector>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/white" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/white" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission
|
||||
android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
|
||||
<application>
|
||||
<service
|
||||
android:name=".connect.KeepAliveService"
|
||||
android:foregroundServiceType="specialUse"
|
||||
android:enabled="true" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.thoughtcrime.securesms.geolocation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
/** Non-GMS, always uses the platform LocationManager. */
|
||||
public final class LocationSourceFactory {
|
||||
|
||||
private static final String TAG = "LocationSourceFactory";
|
||||
|
||||
private LocationSourceFactory() {}
|
||||
|
||||
public static LocationSource create(Context context) {
|
||||
Log.i(TAG, "Non-GMS build, Using platform LocationManager");
|
||||
return new PlatformLocationSource();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.thoughtcrime.securesms.notifications;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/*
|
||||
@@ -10,6 +9,11 @@ import androidx.annotation.Nullable;
|
||||
*/
|
||||
public class FcmReceiveService {
|
||||
public static void register(Context context) {}
|
||||
|
||||
public static void waitForRegisterFinished() {}
|
||||
@Nullable public static String getToken() { return null; }
|
||||
|
||||
@Nullable
|
||||
public static String getToken() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<!-- force compiling emojipicker on sdk<21 and firebase on sdk<19; runtime checks are required then -->
|
||||
<uses-sdk tools:overrideLibrary="androidx.emoji2.emojipicker, com.google.firebase.messaging, com.google.android.gms.cloudmessaging"/>
|
||||
|
||||
<meta-data android:name="firebase_analytics_collection_deactivated" android:value="true" />
|
||||
<meta-data android:name="google_analytics_adid_collection_enabled" android:value="false" />
|
||||
<meta-data android:name="firebase_messaging_auto_init_enabled" android:value="false" />
|
||||
<meta-data
|
||||
android:name="firebase_analytics_collection_deactivated"
|
||||
android:value="true" />
|
||||
<meta-data
|
||||
android:name="google_analytics_adid_collection_enabled"
|
||||
android:value="false" />
|
||||
<meta-data
|
||||
android:name="firebase_messaging_auto_init_enabled"
|
||||
android:value="false" />
|
||||
|
||||
<application>
|
||||
<service
|
||||
android:name=".connect.KeepAliveService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
android:enabled="true" />
|
||||
|
||||
<service
|
||||
android:name=".notifications.FcmReceiveService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.thoughtcrime.securesms.geolocation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import androidx.annotation.NonNull;
|
||||
import com.google.android.gms.location.FusedLocationProviderClient;
|
||||
import com.google.android.gms.location.LocationCallback;
|
||||
import com.google.android.gms.location.LocationRequest;
|
||||
import com.google.android.gms.location.LocationResult;
|
||||
import com.google.android.gms.location.LocationServices;
|
||||
import com.google.android.gms.location.Priority;
|
||||
|
||||
public class GmsLocationSource implements LocationSource {
|
||||
|
||||
private static final String TAG = "GmsLocationSource";
|
||||
private static final long UPDATE_INTERVAL_MS = 3_000;
|
||||
private static final long FASTEST_INTERVAL_MS = 1_000;
|
||||
|
||||
private FusedLocationProviderClient client;
|
||||
private LocationCallback locationCallback;
|
||||
|
||||
@Override
|
||||
public void startUpdates(@NonNull Context context, @NonNull Callback callback) {
|
||||
client = LocationServices.getFusedLocationProviderClient(context);
|
||||
|
||||
LocationRequest request =
|
||||
new LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, UPDATE_INTERVAL_MS)
|
||||
.setMinUpdateIntervalMillis(FASTEST_INTERVAL_MS)
|
||||
.setMinUpdateDistanceMeters(0)
|
||||
.setWaitForAccurateLocation(false)
|
||||
.build();
|
||||
|
||||
locationCallback =
|
||||
new LocationCallback() {
|
||||
@Override
|
||||
public void onLocationResult(@NonNull LocationResult result) {
|
||||
Location loc = result.getLastLocation();
|
||||
if (loc != null) {
|
||||
callback.onLocationUpdate(loc);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
client.requestLocationUpdates(request, locationCallback, Looper.getMainLooper());
|
||||
} catch (SecurityException e) {
|
||||
Log.e(TAG, "Missing location permission", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopUpdates() {
|
||||
if (client != null && locationCallback != null) {
|
||||
client.removeLocationUpdates(locationCallback);
|
||||
client = null;
|
||||
locationCallback = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package org.thoughtcrime.securesms.geolocation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
import com.google.android.gms.common.ConnectionResult;
|
||||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
|
||||
/**
|
||||
* Prefers FusedLocationProviderClient, falls back to platform LocationManager if Play Services are
|
||||
* somehow unavailable.
|
||||
*/
|
||||
public final class LocationSourceFactory {
|
||||
|
||||
private static final String TAG = "LocationSourceFactory";
|
||||
|
||||
private LocationSourceFactory() {}
|
||||
|
||||
public static LocationSource create(Context context) {
|
||||
if (isGmsAvailable(context)) {
|
||||
Log.i(TAG, "Using FusedLocationProviderClient");
|
||||
return new GmsLocationSource();
|
||||
}
|
||||
Log.i(TAG, "GMS unavailable, falling back to LocationManager");
|
||||
return new PlatformLocationSource();
|
||||
}
|
||||
|
||||
private static boolean isGmsAvailable(Context context) {
|
||||
try {
|
||||
return GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
|
||||
== ConnectionResult.SUCCESS;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,23 @@
|
||||
package org.thoughtcrime.securesms.notifications;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.google.android.gms.tasks.Tasks;
|
||||
import com.google.firebase.FirebaseApp;
|
||||
import com.google.firebase.messaging.FirebaseMessaging;
|
||||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.service.FetchForegroundService;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class FcmReceiveService extends FirebaseMessagingService {
|
||||
private static final String TAG = FcmReceiveService.class.getSimpleName();
|
||||
private static final String TAG = "FcmReceiveService";
|
||||
private static final Object INIT_LOCK = new Object();
|
||||
private static boolean initialized;
|
||||
private static volatile boolean triedRegistering;
|
||||
@@ -35,7 +31,8 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
||||
return;
|
||||
}
|
||||
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
Util.runOnAnyBackgroundThread(
|
||||
() -> {
|
||||
final String rawToken;
|
||||
|
||||
try {
|
||||
@@ -49,7 +46,8 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
||||
}
|
||||
rawToken = Tasks.await(FirebaseMessaging.getInstance().getToken());
|
||||
} catch (Exception e) {
|
||||
// we're here usually when FCM is not available and initializeApp() or getToken() failed.
|
||||
// we're here usually when FCM is not available and initializeApp() or getToken()
|
||||
// failed.
|
||||
Log.w(TAG, "cannot get FCM token for " + BuildConfig.APPLICATION_ID + ": " + e);
|
||||
triedRegistering = true;
|
||||
return;
|
||||
@@ -62,7 +60,7 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
||||
|
||||
prefixedToken = addPrefix(rawToken);
|
||||
Log.i(TAG, "FCM token: " + prefixedToken);
|
||||
ApplicationContext.dcAccounts.setPushDeviceToken(prefixedToken);
|
||||
ApplicationContext.getDcAccounts().setPushDeviceToken(prefixedToken);
|
||||
triedRegistering = true;
|
||||
});
|
||||
}
|
||||
@@ -91,7 +89,20 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
||||
@Override
|
||||
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
|
||||
Log.i(TAG, "FCM push notification received");
|
||||
// Note: The system can downgrade the high priority messages to normal priority
|
||||
// if the app is not using the high priority messages for surfacing time sensitive
|
||||
// content to the user. If the message's priority is downgraded, your app cannot
|
||||
// start a foreground service and attempting to start one results in a
|
||||
// ForegroundServiceStartNotAllowedException.
|
||||
// So, it's recommended to check the result of RemoteMessage.getPriority() and
|
||||
// confirm it's PRIORITY_HIGH() before attempting to start a foreground service.
|
||||
// source:
|
||||
// https://developer.android.com/develop/background-work/services/fgs/restrictions-bg-start
|
||||
if (remoteMessage.getPriority() == RemoteMessage.PRIORITY_HIGH) {
|
||||
FetchForegroundService.start(this);
|
||||
} else {
|
||||
FetchForegroundService.fetchSynchronously();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -104,6 +115,6 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
||||
public void onNewToken(@NonNull String rawToken) {
|
||||
prefixedToken = addPrefix(rawToken);
|
||||
Log.i(TAG, "new FCM token: " + prefixedToken);
|
||||
ApplicationContext.dcAccounts.setPushDeviceToken(prefixedToken);
|
||||
ApplicationContext.getDcAccounts().setPushDeviceToken(prefixedToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,28 +1,55 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.bluetooth" android:required="false" />
|
||||
<uses-feature android:name="android.hardware.location" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.location.network" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.location.gps" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.microphone" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.wifi" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.portrait" android:required="false"/>
|
||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
|
||||
<uses-feature
|
||||
android:name="android.hardware.camera"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.location"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.location.network"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.location.gps"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.microphone"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.wifi"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.portrait"
|
||||
android:required="false" />
|
||||
<uses-feature
|
||||
android:name="android.hardware.touchscreen"
|
||||
android:required="false" />
|
||||
|
||||
<!-- dangerous permissions - we need to as the user with a PermissionsRequest -->
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="29" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission
|
||||
android:name="android.permission.BLUETOOTH"
|
||||
android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
|
||||
|
||||
<!-- normal/instant permissions - adding them here is enough -->
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
@@ -35,41 +62,47 @@
|
||||
<uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
<uses-permission android:name="android.permission.RAISED_THREAD_PRIORITY" />
|
||||
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
<uses-permission
|
||||
android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
|
||||
<uses-permission
|
||||
android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
|
||||
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
|
||||
|
||||
<!-- force compiling emojipicker on sdk<21; runtime checks are required then -->
|
||||
<uses-sdk tools:overrideLibrary="androidx.emoji2.emojipicker"/>
|
||||
<!-- force compiling libs on older sdk than supported; runtime checks are required -->
|
||||
<uses-sdk tools:overrideLibrary="androidx.core.telecom,im.conversations.webrtc" />
|
||||
|
||||
<application android:name=".ApplicationContext"
|
||||
<application
|
||||
android:name=".ApplicationContext"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
tools:replace="android:allowBackup"
|
||||
android:allowBackup="false"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:largeHeap="true"
|
||||
tools:ignore="GoogleAppIndexingWarning"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
tools:targetApi="TIRAMISU"
|
||||
android:hasFragileUserData="true"
|
||||
>
|
||||
android:hasFragileUserData="true">
|
||||
|
||||
<!-- android car support, see https://developer.android.com/training/auto/start/,
|
||||
as this potentially blocks releases on gplay due to extra-checks,
|
||||
we disable this during the first gplay releases -->
|
||||
<!--
|
||||
<meta-data android:name="com.google.android.gms.car.application"
|
||||
android:resource="@xml/automotive_app_desc" />
|
||||
-->
|
||||
<!-- android car support, see https://developer.android.com/training/auto/start/, as this potentially
|
||||
blocks releases on gplay due to extra-checks, we disable this during the first gplay releases -->
|
||||
<!-- <meta-data android:name="com.google.android.gms.car.application" android:resource="@xml/automotive_app_desc"
|
||||
/> -->
|
||||
|
||||
<!-- Opt out of metrics collection: https://developer.android.com/develop/ui/views/layout/webapps/managing-webview#metrics -->
|
||||
<meta-data android:name="android.webkit.WebView.MetricsOptOut"
|
||||
<meta-data
|
||||
android:name="android.webkit.WebView.MetricsOptOut"
|
||||
android:value="true" />
|
||||
|
||||
<activity android:name=".ShareActivity"
|
||||
<activity
|
||||
android:name=".ShareActivity"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
android:excludeFromRecents="true"
|
||||
android:launchMode="singleTask"
|
||||
@@ -80,21 +113,22 @@
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="audio/*" />
|
||||
<data android:mimeType="image/*" />
|
||||
<data android:mimeType="text/plain" />
|
||||
<data android:mimeType="video/*" />
|
||||
<data android:mimeType="application/*"/>
|
||||
<data android:mimeType="text/*"/>
|
||||
<data android:mimeType="*/*"/>
|
||||
<data android:mimeType="application/*" />
|
||||
<data android:mimeType="text/*" />
|
||||
<data android:mimeType="*/*" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<data android:scheme="mailto"/>
|
||||
<action android:name="android.intent.action.SENDTO"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data android:scheme="mailto" />
|
||||
<action android:name="android.intent.action.SENDTO" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
@@ -104,9 +138,9 @@
|
||||
<data android:mimeType="image/*" />
|
||||
<data android:mimeType="text/plain" />
|
||||
<data android:mimeType="video/*" />
|
||||
<data android:mimeType="application/*"/>
|
||||
<data android:mimeType="text/*"/>
|
||||
<data android:mimeType="*/*"/>
|
||||
<data android:mimeType="application/*" />
|
||||
<data android:mimeType="text/*" />
|
||||
<data android:mimeType="*/*" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="android.service.chooser.chooser_target_service"
|
||||
@@ -114,14 +148,16 @@
|
||||
|
||||
</activity>
|
||||
|
||||
<activity android:name=".ConversationListActivity"
|
||||
<activity
|
||||
android:name=".ConversationListActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/TextSecure.Splash"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
android:exported="true" />
|
||||
|
||||
<activity-alias android:name=".RoutingActivity"
|
||||
<activity-alias
|
||||
android:name=".RoutingActivity"
|
||||
android:targetActivity=".ConversationListActivity"
|
||||
android:exported="true">
|
||||
|
||||
@@ -132,18 +168,22 @@
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<!-- Android's scheme matcher is case-sensitive, so include most likely variations -->
|
||||
<data android:scheme="openpgp4fpr" />
|
||||
<data android:scheme="OPENPGP4FPR"
|
||||
<data
|
||||
android:scheme="OPENPGP4FPR"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
<data android:scheme="OpenPGP4FPR"
|
||||
<data
|
||||
android:scheme="OpenPGP4FPR"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
<data android:scheme="OpenPGP4Fpr"
|
||||
<data
|
||||
android:scheme="OpenPGP4Fpr"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
<data android:scheme="OpenPGP4fpr"
|
||||
<data
|
||||
android:scheme="OpenPGP4fpr"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
</intent-filter>
|
||||
|
||||
@@ -151,13 +191,16 @@
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="https"
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="i.delta.chat" />
|
||||
</intent-filter>
|
||||
|
||||
<meta-data android:name="com.sec.minimode.icon.portrait.normal"
|
||||
<meta-data
|
||||
android:name="com.sec.minimode.icon.portrait.normal"
|
||||
android:resource="@mipmap/ic_launcher" />
|
||||
<meta-data android:name="com.sec.minimode.icon.landscape.normal"
|
||||
<meta-data
|
||||
android:name="com.sec.minimode.icon.landscape.normal"
|
||||
android:resource="@mipmap/ic_launcher" />
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
@@ -165,7 +208,8 @@
|
||||
|
||||
</activity-alias>
|
||||
|
||||
<activity android:name=".ConversationListArchiveActivity"
|
||||
<activity
|
||||
android:name=".ConversationListArchiveActivity"
|
||||
android:label="@string/chat_archived_label"
|
||||
android:launchMode="singleTask"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
@@ -175,111 +219,122 @@
|
||||
android:value="org.thoughtcrime.securesms.ConversationListActivity" />
|
||||
</activity>
|
||||
|
||||
<activity android:name=".ConversationListRelayingActivity"
|
||||
<activity
|
||||
android:name=".ConversationListRelayingActivity"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTask"
|
||||
android:theme="@style/TextSecure.LightNoActionBar"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".ConversationActivity"
|
||||
<activity
|
||||
android:name=".ConversationActivity"
|
||||
android:windowSoftInputMode="stateUnchanged"
|
||||
android:launchMode="singleTask"
|
||||
android:relinquishTaskIdentity="true"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
android:parentActivityName=".ConversationListActivity">
|
||||
<!--
|
||||
Without relinquishTaskIdentity="true", we would have the following bug:
|
||||
- Directly open a chat via shortcut (by long-pressing on the DeltaChat icon in the launcher)
|
||||
- Press back twice
|
||||
- Reopen DeltaChat from recent apps
|
||||
- Expected: ConversationList shown. Actual: The chat from the beginning is shown again.
|
||||
-->
|
||||
<!-- Without relinquishTaskIdentity="true", we would have the following bug: - Directly open
|
||||
a chat via shortcut (by long-pressing on the DeltaChat icon in the launcher) - Press back twice - Reopen
|
||||
DeltaChat from recent apps - Expected: ConversationList shown. Actual: The chat from the beginning is
|
||||
shown again. -->
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.thoughtcrime.securesms.ConversationListActivity" />
|
||||
</activity>
|
||||
|
||||
<activity android:name=".GroupCreateActivity"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
<activity
|
||||
android:name=".GroupCreateActivity"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".contacts.NewContactActivity"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
<activity
|
||||
android:name=".contacts.NewContactActivity"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".NewConversationActivity"
|
||||
<activity
|
||||
android:name=".NewConversationActivity"
|
||||
android:theme="@style/TextSecure.LightNoActionBar"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<data android:scheme="mailto"/>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
</intent-filter>
|
||||
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".ContactMultiSelectionActivity"
|
||||
<activity
|
||||
android:name=".ContactMultiSelectionActivity"
|
||||
android:label="@string/contacts_title"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".ApplicationPreferencesActivity"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
<activity
|
||||
android:name=".ApplicationPreferencesActivity"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".WelcomeActivity"
|
||||
android:launchMode="singleTask"
|
||||
<activity
|
||||
android:name=".WelcomeActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/TextSecure.LightNoActionBar"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".RegistrationActivity"
|
||||
<activity
|
||||
android:name=".relay.EditRelayActivity"
|
||||
android:launchMode="singleTask"
|
||||
android:windowSoftInputMode="stateUnchanged"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
android:exported="true">
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".proxy.ProxySettingsActivity"
|
||||
<activity
|
||||
android:name=".relay.RelayListActivity"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity
|
||||
android:name=".proxy.ProxySettingsActivity"
|
||||
android:label="@string/proxy_settings"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:exported="true"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<!-- Android's scheme matcher is case-sensitive, so include most likely variations -->
|
||||
<data android:scheme="ss" />
|
||||
<data android:scheme="socks5" />
|
||||
<data android:scheme="SOCKS5" tools:ignore="AppLinkUrlError" />
|
||||
<data android:scheme="SS" tools:ignore="AppLinkUrlError" />
|
||||
<data
|
||||
android:scheme="SOCKS5"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
<data
|
||||
android:scheme="SS"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
|
||||
<activity android:name=".LogViewActivity"
|
||||
<activity
|
||||
android:name=".LogViewActivity"
|
||||
android:label="@string/pref_log_header"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".MediaPreviewActivity"
|
||||
<activity
|
||||
android:name=".MediaPreviewActivity"
|
||||
android:label="@string/media_preview"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:launchMode="singleTask"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".ProfileActivity"
|
||||
<activity
|
||||
android:name=".ProfileActivity"
|
||||
android:theme="@style/TextSecure.LightNoActionBar"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".AllMediaActivity"
|
||||
<activity
|
||||
android:name=".AllMediaActivity"
|
||||
android:theme="@style/TextSecure.LightNoActionBar"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".DummyActivity"
|
||||
<activity
|
||||
android:name=".DummyActivity"
|
||||
android:theme="@android:style/Theme.NoDisplay"
|
||||
android:enabled="true"
|
||||
android:allowTaskReparenting="true"
|
||||
@@ -290,112 +345,126 @@
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:finishOnTaskLaunch="true" />
|
||||
|
||||
<activity android:name=".AttachContactActivity"
|
||||
<activity
|
||||
android:name=".AttachContactActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".BlockedContactsActivity"
|
||||
<activity
|
||||
android:name=".BlockedContactsActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".scribbles.ScribbleActivity"
|
||||
<activity
|
||||
android:name=".scribbles.ScribbleActivity"
|
||||
android:theme="@style/TextSecure.ScribbleTheme"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".scribbles.StickerSelectActivity"
|
||||
<activity
|
||||
android:name=".scribbles.StickerSelectActivity"
|
||||
android:theme="@style/TextSecure.ScribbleTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".InstantOnboardingActivity"
|
||||
<activity
|
||||
android:name=".InstantOnboardingActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:windowSoftInputMode="stateHidden|adjustResize"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<!-- Android's scheme matcher is case-sensitive, so include most likely variations -->
|
||||
<data android:scheme="DCACCOUNT"
|
||||
<data
|
||||
android:scheme="DCACCOUNT"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
<data android:scheme="dcaccount"
|
||||
<data
|
||||
android:scheme="dcaccount"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
<data android:scheme="DCLOGIN"
|
||||
<data
|
||||
android:scheme="DCLOGIN"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
<data android:scheme="dclogin"
|
||||
<data
|
||||
android:scheme="dclogin"
|
||||
tools:ignore="AppLinkUrlError" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".CreateProfileActivity"
|
||||
<activity
|
||||
android:name=".CreateProfileActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:windowSoftInputMode="stateHidden|adjustResize"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".qr.QrActivity"
|
||||
<activity
|
||||
android:name=".qr.QrActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".qr.QrShowActivity"
|
||||
<activity
|
||||
android:name=".qr.QrShowActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".qr.RegistrationQrActivity"
|
||||
<activity
|
||||
android:name=".qr.RegistrationQrActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".qr.BackupTransferActivity"
|
||||
<activity
|
||||
android:name=".qr.BackupTransferActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".preferences.ChatBackgroundActivity"
|
||||
<activity
|
||||
android:name=".preferences.ChatBackgroundActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize" />
|
||||
|
||||
<activity android:name=".LocalHelpActivity"
|
||||
<activity
|
||||
android:name=".LocalHelpActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".calls.CallActivity"
|
||||
android:label=""
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize|uiMode"
|
||||
android:exported="true">
|
||||
<activity
|
||||
android:name=".calls.CallActivity"
|
||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|keyboard|keyboardHidden"
|
||||
android:launchMode="singleTask"
|
||||
android:taskAffinity=".calls.PipCallTask"
|
||||
android:theme="@style/Theme.App.NoActionBar.Fullscreen"
|
||||
android:exported="false"
|
||||
android:supportsPictureInPicture="true"
|
||||
android:excludeFromRecents="true">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".WebxdcActivity"
|
||||
<activity
|
||||
android:name=".WebxdcActivity"
|
||||
android:label=""
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize|uiMode"
|
||||
android:exported="true">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".WebxdcStoreActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize|uiMode">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".FullMsgActivity"
|
||||
<activity
|
||||
android:name=".WebxdcStoreActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize|uiMode">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".FullMsgActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
|
||||
</activity>
|
||||
|
||||
<activity android:name=".ConnectivityActivity"
|
||||
<activity
|
||||
android:name=".ConnectivityActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name=".connect.KeepAliveService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
android:enabled="true" />
|
||||
|
||||
<service
|
||||
android:name=".geolocation.LocationBackgroundService"
|
||||
android:foregroundServiceType="location" />
|
||||
|
||||
<service
|
||||
android:name=".service.GenericForegroundService"
|
||||
android:foregroundServiceType="dataSync" />
|
||||
@@ -404,45 +473,58 @@
|
||||
android:name=".service.FetchForegroundService"
|
||||
android:foregroundServiceType="dataSync" />
|
||||
|
||||
<receiver android:name=".notifications.MarkReadReceiver"
|
||||
<service
|
||||
android:name=".geolocation.LocationStreamingService"
|
||||
android:foregroundServiceType="location"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name=".service.AudioPlaybackService"
|
||||
android:foregroundServiceType="mediaPlayback"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="androidx.media3.session.MediaSessionService" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<service
|
||||
android:name=".calls.CallService"
|
||||
android:enabled="true"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="camera|microphone|phoneCall" />
|
||||
|
||||
<receiver
|
||||
android:name=".notifications.MarkReadReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="org.thoughtcrime.securesms.notifications.MARK_NOTICED"/>
|
||||
<action android:name="org.thoughtcrime.securesms.notifications.CANCEL"/>
|
||||
<action android:name="org.thoughtcrime.securesms.notifications.MARK_NOTICED" />
|
||||
<action android:name="org.thoughtcrime.securesms.notifications.CANCEL" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".notifications.DeclineCallReceiver"
|
||||
<receiver
|
||||
android:name=".notifications.RemoteReplyReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="org.thoughtcrime.securesms.notifications.DECLINE_CALL_NOTICED"/>
|
||||
<action android:name="org.thoughtcrime.securesms.notifications.WEAR_REPLY" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".notifications.RemoteReplyReceiver"
|
||||
android:enabled="true"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="org.thoughtcrime.securesms.notifications.WEAR_REPLY"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<provider android:name="androidx.core.content.FileProvider"
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
|
||||
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_provider_paths" />
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_provider_paths" />
|
||||
|
||||
<!--
|
||||
tell SafeContentResolver to allow incoming share-file Intent pointing to files from
|
||||
this content resolver, it could be the user sharing the app's log file to a chat.
|
||||
See:
|
||||
https://github.com/deltachat/deltachat-android/pull/3052
|
||||
https://github.com/deltachat/deltachat-android/pull/3031
|
||||
-->
|
||||
<!-- tell SafeContentResolver to allow incoming share-file Intent pointing to files from
|
||||
this content resolver, it could be the user sharing the app's log file to a chat. See: https://github.com/deltachat/deltachat-android/pull/3052
|
||||
https://github.com/deltachat/deltachat-android/pull/3031 -->
|
||||
<meta-data
|
||||
android:name="de.cketti.safecontentresolver.ALLOW_INTERNAL_ACCESS"
|
||||
android:value="true" />
|
||||
@@ -455,22 +537,20 @@
|
||||
android:grantUriPermissions="true"
|
||||
android:exported="false">
|
||||
|
||||
<!--
|
||||
tell SafeContentResolver to allow incoming share-file Intent pointing to files from
|
||||
this content resolver, it could be the user sharing a file from one chat to another.
|
||||
See: https://github.com/deltachat/deltachat-android/pull/3031
|
||||
-->
|
||||
<!-- tell SafeContentResolver to allow incoming share-file Intent pointing to files from
|
||||
this content resolver, it could be the user sharing a file from one chat to another. See: https://github.com/deltachat/deltachat-android/pull/3031 -->
|
||||
<meta-data
|
||||
android:name="de.cketti.safecontentresolver.ALLOW_INTERNAL_ACCESS"
|
||||
android:value="true" />
|
||||
|
||||
</provider>
|
||||
|
||||
<receiver android:name=".service.BootReceiver"
|
||||
<receiver
|
||||
android:name=".service.BootReceiver"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||
<action android:name="org.thoughtcrime.securesms.RESTART"/>
|
||||
<action android:name="android.intent.action.BOOT_COMPLETED" />
|
||||
<action android:name="org.thoughtcrime.securesms.RESTART" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
@@ -482,20 +562,32 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<uses-library android:name="com.sec.android.app.multiwindow" android:required="false"/>
|
||||
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632.0dip" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H" android:value="598.0dip" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_W" android:value="632.0dip" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_H" android:value="598.0dip" />
|
||||
</application>
|
||||
<uses-library
|
||||
android:name="com.sec.android.app.multiwindow"
|
||||
android:required="false" />
|
||||
<meta-data
|
||||
android:name="com.sec.android.support.multiwindow"
|
||||
android:value="true" />
|
||||
<meta-data
|
||||
android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W"
|
||||
android:value="632.0dip" />
|
||||
<meta-data
|
||||
android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H"
|
||||
android:value="598.0dip" />
|
||||
<meta-data
|
||||
android:name="com.sec.android.multiwindow.MINIMUM_SIZE_W"
|
||||
android:value="632.0dip" />
|
||||
<meta-data
|
||||
android:name="com.sec.android.multiwindow.MINIMUM_SIZE_H"
|
||||
android:value="598.0dip" />
|
||||
</application>
|
||||
|
||||
<queries>
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.media.action.IMAGE_CAPTURE" />
|
||||
</intent>
|
||||
<intent>
|
||||
<action android:name="android.intent.action.TTS_SERVICE" />
|
||||
</intent>
|
||||
</queries>
|
||||
</queries>
|
||||
</manifest>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB |
@@ -6,6 +6,10 @@ a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a[href^='http']::after {
|
||||
content: " ↗";
|
||||
}
|
||||
|
||||
h2, h3, h4 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 778 B |
|
After Width: | Height: | Size: 577 B |
|
After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 137 B After Width: | Height: | Size: 138 B |
|
Before Width: | Height: | Size: 145 B After Width: | Height: | Size: 148 B |
|
After Width: | Height: | Size: 232 B |
|
After Width: | Height: | Size: 286 B |
@@ -14,7 +14,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
/* Basic RPC Transport implementation */
|
||||
public abstract class BaseTransport implements Rpc.Transport {
|
||||
public abstract class BaseRpcTransport implements Rpc.RpcTransport {
|
||||
private final Map<Integer, SettableFuture<JsonNode>> requestFutures = new ConcurrentHashMap<>();
|
||||
private int requestId = 0;
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
@@ -94,7 +94,7 @@ public abstract class BaseTransport implements Rpc.Transport {
|
||||
}
|
||||
|
||||
if (response.error != null) {
|
||||
future.setException(new RpcException(response.error.toString()));
|
||||
future.setException(new RpcException(response.error.message));
|
||||
} else if (response.result != null) {
|
||||
future.set(response.result);
|
||||
} else {
|
||||
@@ -115,10 +115,15 @@ public abstract class BaseTransport implements Rpc.Transport {
|
||||
}
|
||||
}
|
||||
|
||||
private static class RpcError {
|
||||
public int code;
|
||||
public String message;
|
||||
}
|
||||
|
||||
private static class Response {
|
||||
public String jsonrpc;
|
||||
public int id;
|
||||
public JsonNode result;
|
||||
public JsonNode error;
|
||||
public RpcError error;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
|
||||
|
||||
@JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="kind")
|
||||
@JsonSubTypes({@Type(value = Account.Configured.class, name="Configured"), @Type(value = Account.Unconfigured.class, name="Unconfigured")})
|
||||
public abstract class Account {
|
||||
|
||||
public static class Configured extends Account {
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String addr;
|
||||
public String color;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String displayName;
|
||||
public Integer id;
|
||||
/** Optional tag as "Work", "Family". Meant to help profile owner to differ between profiles with similar names. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String privateTag;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String profileImage;
|
||||
}
|
||||
|
||||
public static class Unconfigured extends Account {
|
||||
public Integer id;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
/**
|
||||
* cheaper version of fullchat, omits: - contact_ids - fresh_message_counter - ephemeral_timer - self_in_group - was_seen_recently - can_send
|
||||
* <p>
|
||||
* used when you only need the basic metadata of a chat like type, name, profile picture
|
||||
*/
|
||||
public class BasicChat {
|
||||
public Boolean archived;
|
||||
public ChatType chatType;
|
||||
public String color;
|
||||
public Integer id;
|
||||
public Boolean isContactRequest;
|
||||
public Boolean isDeviceChat;
|
||||
/**
|
||||
* True if the chat is encrypted. This means that all messages in the chat are encrypted, and all contacts in the chat are "key-contacts", i.e. identified by the PGP key fingerprint.
|
||||
* <p>
|
||||
* False if the chat is unencrypted. This means that all messages in the chat are unencrypted, and all contacts in the chat are "address-contacts", i.e. identified by the email address. The UI should mark this chat e.g. with a mail-letter icon.
|
||||
* <p>
|
||||
* Unencrypted groups are called "ad-hoc groups" and the user can't add/remove members, create a QR invite code, or set an avatar. These options should therefore be disabled in the UI.
|
||||
* <p>
|
||||
* Note that it can happen that an encrypted chat contains unencrypted messages that were received in core <= v1.159.* and vice versa.
|
||||
* <p>
|
||||
* See also `is_key_contact` on `Contact`.
|
||||
*/
|
||||
public Boolean isEncrypted;
|
||||
public Boolean isMuted;
|
||||
public Boolean isSelfTalk;
|
||||
public Boolean isUnpromoted;
|
||||
public String name;
|
||||
public Boolean pinned;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String profileImage;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class CallInfo {
|
||||
/* True if SDP offer has a video. */
|
||||
/** True if the call is started as a video call. */
|
||||
public Boolean hasVideo;
|
||||
/**
|
||||
* SDP offer.
|
||||
|
||||
@@ -19,21 +19,21 @@ public abstract class CallState {
|
||||
public static class Alerting extends CallState {
|
||||
}
|
||||
|
||||
/* Active call. */
|
||||
/** Active call. */
|
||||
public static class Active extends CallState {
|
||||
}
|
||||
|
||||
/* Completed call that was once active and then was terminated for any reason. */
|
||||
/** Completed call that was once active and then was terminated for any reason. */
|
||||
public static class Completed extends CallState {
|
||||
/* Call duration in seconds. */
|
||||
/** Call duration in seconds. */
|
||||
public Integer duration;
|
||||
}
|
||||
|
||||
/* Incoming call that was not picked up within a timeout or was explicitly ended by the caller before we picked up. */
|
||||
/** Incoming call that was not picked up within a timeout or was explicitly ended by the caller before we picked up. */
|
||||
public static class Missed extends CallState {
|
||||
}
|
||||
|
||||
/* Incoming call that was explicitly ended on our side before picking up or outgoing call that was declined before the timeout. */
|
||||
/** Incoming call that was explicitly ended on our side before picking up or outgoing call that was declined before the timeout. */
|
||||
public static class Declined extends CallState {
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
|
||||
|
||||
@JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="kind")
|
||||
@JsonSubTypes({@Type(value = ChatListItemFetchResult.ChatListItem.class, name="ChatListItem"), @Type(value = ChatListItemFetchResult.ArchiveLink.class, name="ArchiveLink"), @Type(value = ChatListItemFetchResult.Error.class, name="Error")})
|
||||
public abstract class ChatListItemFetchResult {
|
||||
|
||||
public static class ChatListItem extends ChatListItemFetchResult {
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String avatarPath;
|
||||
public ChatType chatType;
|
||||
public String color;
|
||||
/** contact id if this is a dm chat (for view profile entry in context menu) */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer dmChatContact;
|
||||
public Integer freshMessageCounter;
|
||||
public Integer id;
|
||||
public Boolean isArchived;
|
||||
public Boolean isContactRequest;
|
||||
public Boolean isDeviceTalk;
|
||||
/**
|
||||
* True if the chat is encrypted. This means that all messages in the chat are encrypted, and all contacts in the chat are "key-contacts", i.e. identified by the PGP key fingerprint.
|
||||
* <p>
|
||||
* False if the chat is unencrypted. This means that all messages in the chat are unencrypted, and all contacts in the chat are "address-contacts", i.e. identified by the email address. The UI should mark this chat e.g. with a mail-letter icon.
|
||||
* <p>
|
||||
* Unencrypted groups are called "ad-hoc groups" and the user can't add/remove members, create a QR invite code, or set an avatar. These options should therefore be disabled in the UI.
|
||||
* <p>
|
||||
* Note that it can happen that an encrypted chat contains unencrypted messages that were received in core <= v1.159.* and vice versa.
|
||||
* <p>
|
||||
* See also `is_key_contact` on `Contact`.
|
||||
*/
|
||||
public Boolean isEncrypted;
|
||||
/** deprecated 2025-07, use chat_type instead */
|
||||
public Boolean isGroup;
|
||||
public Boolean isMuted;
|
||||
public Boolean isPinned;
|
||||
public Boolean isSelfInGroup;
|
||||
public Boolean isSelfTalk;
|
||||
public Boolean isSendingLocation;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer lastMessageId;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Viewtype lastMessageType;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer lastUpdated;
|
||||
public String name;
|
||||
/** showing preview if last chat message is image */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String summaryPreviewImage;
|
||||
public Integer summaryStatus;
|
||||
public String summaryText1;
|
||||
public String summaryText2;
|
||||
public Boolean wasSeenRecently;
|
||||
}
|
||||
|
||||
public static class ArchiveLink extends ChatListItemFetchResult {
|
||||
public Integer freshMessageCounter;
|
||||
}
|
||||
|
||||
public static class Error extends ChatListItemFetchResult {
|
||||
public String error;
|
||||
public Integer id;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public enum ChatType {
|
||||
Single,
|
||||
Group,
|
||||
Mailinglist,
|
||||
OutBroadcast,
|
||||
InBroadcast,
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public enum ChatVisibility {
|
||||
Normal,
|
||||
Archived,
|
||||
Pinned,
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class Contact {
|
||||
public String address;
|
||||
public String authName;
|
||||
public String color;
|
||||
public String displayName;
|
||||
/**
|
||||
* Is encryption available for this contact.
|
||||
* <p>
|
||||
* This can only be true for key-contacts. However, it is possible to have a key-contact for which encryption is not available because we don't have a key yet, e.g. if we just scanned the fingerprint from a QR code.
|
||||
*/
|
||||
public Boolean e2eeAvail;
|
||||
public Integer id;
|
||||
public Boolean isBlocked;
|
||||
/** If the contact is a bot. */
|
||||
public Boolean isBot;
|
||||
/** Is the contact a key contact. */
|
||||
public Boolean isKeyContact;
|
||||
/**
|
||||
* True if the contact can be added to protected chats because SELF and contact have verified their fingerprints in both directions.
|
||||
* <p>
|
||||
* See [`Self::verifier_id`]/`Contact.verifierId` for a guidance how to display these information.
|
||||
*/
|
||||
public Boolean isVerified;
|
||||
/** the contact's last seen timestamp */
|
||||
public Integer lastSeen;
|
||||
public String name;
|
||||
public String nameAndAddr;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String profileImage;
|
||||
public String status;
|
||||
/**
|
||||
* The contact ID that verified a contact.
|
||||
* <p>
|
||||
* As verifier may be unknown, use [`Self::is_verified`]/`Contact.isVerified` to check if a contact can be added to a protected chat.
|
||||
* <p>
|
||||
* UI should display the information in the contact's profile as follows:
|
||||
* <p>
|
||||
* - If `verifierId` != 0, display text "Introduced by ..." with the name of the contact. Prefix the text by a green checkmark.
|
||||
* <p>
|
||||
* - If `verifierId` == 0 and `isVerified` != 0, display "Introduced" prefixed by a green checkmark.
|
||||
* <p>
|
||||
* - if `verifierId` == 0 and `isVerified` == 0, display nothing
|
||||
* <p>
|
||||
* This contains the contact ID of the verifier. If it is `DC_CONTACT_ID_SELF`, we verified the contact ourself. If it is None/Null, we don't have verifier information or the contact is not verified.
|
||||
*/
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer verifierId;
|
||||
public Boolean wasSeenRecently;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public enum DownloadState {
|
||||
Done,
|
||||
Available,
|
||||
Failure,
|
||||
Undecipherable,
|
||||
InProgress,
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public enum EnteredCertificateChecks {
|
||||
/* `Automatic` means that provider database setting should be taken. If there is no provider database setting for certificate checks, check certificates strictly. */
|
||||
/** `Automatic` means that provider database setting should be taken. If there is no provider database setting for certificate checks, check certificates strictly. */
|
||||
automatic,
|
||||
|
||||
/* Ensure that TLS certificate is valid for the server hostname. */
|
||||
/** Ensure that TLS certificate is valid for the server hostname. */
|
||||
strict,
|
||||
|
||||
/* Accept certificates that are expired, self-signed or otherwise not valid for the server hostname. */
|
||||
/** Accept certificates that are expired, self-signed or otherwise not valid for the server hostname. */
|
||||
acceptInvalidCertificates,
|
||||
}
|
||||
@@ -7,27 +7,34 @@ package chat.delta.rpc.types;
|
||||
* Usually it will be enough to only set `addr` and `password`, and all the other settings will be autoconfigured.
|
||||
*/
|
||||
public class EnteredLoginParam {
|
||||
/* Email address. */
|
||||
/** Email address. */
|
||||
public String addr;
|
||||
/* TLS options: whether to allow invalid certificates and/or invalid hostnames. Default: Automatic */
|
||||
/** TLS options: whether to allow invalid certificates and/or invalid hostnames. Default: Automatic */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public EnteredCertificateChecks certificateChecks;
|
||||
/* Imap server port. */
|
||||
/**
|
||||
* IMAP server folder.
|
||||
* <p>
|
||||
* Defaults to "INBOX" if not set. Should not be an empty string.
|
||||
*/
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String imapFolder;
|
||||
/** Imap server port. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer imapPort;
|
||||
/* Imap socket security. */
|
||||
/** Imap socket security. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Socket imapSecurity;
|
||||
/* Imap server hostname or IP address. */
|
||||
/** Imap server hostname or IP address. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String imapServer;
|
||||
/* Imap username. */
|
||||
/** Imap username. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String imapUser;
|
||||
/* If true, login via OAUTH2 (not recommended anymore). Default: false */
|
||||
/** If true, login via OAUTH2 (not recommended anymore). Default: false */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Boolean oauth2;
|
||||
/* Password. */
|
||||
/** Password. */
|
||||
public String password;
|
||||
/**
|
||||
* SMTP Password.
|
||||
@@ -36,16 +43,16 @@ public class EnteredLoginParam {
|
||||
*/
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String smtpPassword;
|
||||
/* SMTP server port. */
|
||||
/** SMTP server port. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer smtpPort;
|
||||
/* SMTP socket security. */
|
||||
/** SMTP socket security. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Socket smtpSecurity;
|
||||
/* SMTP server hostname or IP address. */
|
||||
/** SMTP server hostname or IP address. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String smtpServer;
|
||||
/* SMTP username. */
|
||||
/** SMTP username. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String smtpUser;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
|
||||
|
||||
@JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="kind")
|
||||
@JsonSubTypes({@Type(value = EphemeralTimer.Disabled.class, name="Disabled"), @Type(value = EphemeralTimer.Enabled.class, name="Enabled")})
|
||||
public abstract class EphemeralTimer {
|
||||
|
||||
/** Timer is disabled. */
|
||||
public static class Disabled extends EphemeralTimer {
|
||||
}
|
||||
|
||||
/** Timer is enabled. */
|
||||
public static class Enabled extends EphemeralTimer {
|
||||
/**
|
||||
* Timer duration in seconds.
|
||||
* <p>
|
||||
* The value cannot be 0.
|
||||
*/
|
||||
public Integer duration;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class Event {
|
||||
/** Account ID. */
|
||||
public Integer contextId;
|
||||
/** Event payload. */
|
||||
public EventType event;
|
||||
}
|
||||
@@ -0,0 +1,424 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
|
||||
|
||||
@JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="kind")
|
||||
@JsonSubTypes({@Type(value = EventType.Info.class, name="Info"), @Type(value = EventType.SmtpConnected.class, name="SmtpConnected"), @Type(value = EventType.ImapConnected.class, name="ImapConnected"), @Type(value = EventType.SmtpMessageSent.class, name="SmtpMessageSent"), @Type(value = EventType.ImapMessageDeleted.class, name="ImapMessageDeleted"), @Type(value = EventType.ImapMessageMoved.class, name="ImapMessageMoved"), @Type(value = EventType.ImapInboxIdle.class, name="ImapInboxIdle"), @Type(value = EventType.NewBlobFile.class, name="NewBlobFile"), @Type(value = EventType.DeletedBlobFile.class, name="DeletedBlobFile"), @Type(value = EventType.Warning.class, name="Warning"), @Type(value = EventType.Error.class, name="Error"), @Type(value = EventType.ErrorSelfNotInGroup.class, name="ErrorSelfNotInGroup"), @Type(value = EventType.MsgsChanged.class, name="MsgsChanged"), @Type(value = EventType.ReactionsChanged.class, name="ReactionsChanged"), @Type(value = EventType.IncomingReaction.class, name="IncomingReaction"), @Type(value = EventType.IncomingWebxdcNotify.class, name="IncomingWebxdcNotify"), @Type(value = EventType.IncomingMsg.class, name="IncomingMsg"), @Type(value = EventType.IncomingMsgBunch.class, name="IncomingMsgBunch"), @Type(value = EventType.MsgsNoticed.class, name="MsgsNoticed"), @Type(value = EventType.MsgDelivered.class, name="MsgDelivered"), @Type(value = EventType.MsgFailed.class, name="MsgFailed"), @Type(value = EventType.MsgRead.class, name="MsgRead"), @Type(value = EventType.MsgDeleted.class, name="MsgDeleted"), @Type(value = EventType.ChatModified.class, name="ChatModified"), @Type(value = EventType.ChatEphemeralTimerModified.class, name="ChatEphemeralTimerModified"), @Type(value = EventType.ChatDeleted.class, name="ChatDeleted"), @Type(value = EventType.ContactsChanged.class, name="ContactsChanged"), @Type(value = EventType.LocationChanged.class, name="LocationChanged"), @Type(value = EventType.ConfigureProgress.class, name="ConfigureProgress"), @Type(value = EventType.ImexProgress.class, name="ImexProgress"), @Type(value = EventType.ImexFileWritten.class, name="ImexFileWritten"), @Type(value = EventType.SecurejoinInviterProgress.class, name="SecurejoinInviterProgress"), @Type(value = EventType.SecurejoinJoinerProgress.class, name="SecurejoinJoinerProgress"), @Type(value = EventType.ConnectivityChanged.class, name="ConnectivityChanged"), @Type(value = EventType.SelfavatarChanged.class, name="SelfavatarChanged"), @Type(value = EventType.ConfigSynced.class, name="ConfigSynced"), @Type(value = EventType.WebxdcStatusUpdate.class, name="WebxdcStatusUpdate"), @Type(value = EventType.WebxdcRealtimeData.class, name="WebxdcRealtimeData"), @Type(value = EventType.WebxdcRealtimeAdvertisementReceived.class, name="WebxdcRealtimeAdvertisementReceived"), @Type(value = EventType.WebxdcInstanceDeleted.class, name="WebxdcInstanceDeleted"), @Type(value = EventType.AccountsBackgroundFetchDone.class, name="AccountsBackgroundFetchDone"), @Type(value = EventType.ChatlistChanged.class, name="ChatlistChanged"), @Type(value = EventType.ChatlistItemChanged.class, name="ChatlistItemChanged"), @Type(value = EventType.AccountsChanged.class, name="AccountsChanged"), @Type(value = EventType.AccountsItemChanged.class, name="AccountsItemChanged"), @Type(value = EventType.EventChannelOverflow.class, name="EventChannelOverflow"), @Type(value = EventType.IncomingCall.class, name="IncomingCall"), @Type(value = EventType.IncomingCallAccepted.class, name="IncomingCallAccepted"), @Type(value = EventType.OutgoingCallAccepted.class, name="OutgoingCallAccepted"), @Type(value = EventType.CallEnded.class, name="CallEnded"), @Type(value = EventType.TransportsModified.class, name="TransportsModified")})
|
||||
public abstract class EventType {
|
||||
|
||||
/**
|
||||
* The library-user may write an informational string to the log.
|
||||
* <p>
|
||||
* This event should *not* be reported to the end-user using a popup or something like that.
|
||||
*/
|
||||
public static class Info extends EventType {
|
||||
public String msg;
|
||||
}
|
||||
|
||||
/** Emitted when SMTP connection is established and login was successful. */
|
||||
public static class SmtpConnected extends EventType {
|
||||
public String msg;
|
||||
}
|
||||
|
||||
/** Emitted when IMAP connection is established and login was successful. */
|
||||
public static class ImapConnected extends EventType {
|
||||
public String msg;
|
||||
}
|
||||
|
||||
/** Emitted when a message was successfully sent to the SMTP server. */
|
||||
public static class SmtpMessageSent extends EventType {
|
||||
public String msg;
|
||||
}
|
||||
|
||||
/** Emitted when an IMAP message has been marked as deleted */
|
||||
public static class ImapMessageDeleted extends EventType {
|
||||
public String msg;
|
||||
}
|
||||
|
||||
/** Emitted when an IMAP message has been moved */
|
||||
public static class ImapMessageMoved extends EventType {
|
||||
public String msg;
|
||||
}
|
||||
|
||||
/** Emitted before going into IDLE on the Inbox folder. */
|
||||
public static class ImapInboxIdle extends EventType {
|
||||
}
|
||||
|
||||
/** Emitted when an new file in the $BLOBDIR was created */
|
||||
public static class NewBlobFile extends EventType {
|
||||
public String file;
|
||||
}
|
||||
|
||||
/** Emitted when an file in the $BLOBDIR was deleted */
|
||||
public static class DeletedBlobFile extends EventType {
|
||||
public String file;
|
||||
}
|
||||
|
||||
/**
|
||||
* The library-user should write a warning string to the log.
|
||||
* <p>
|
||||
* This event should *not* be reported to the end-user using a popup or something like that.
|
||||
*/
|
||||
public static class Warning extends EventType {
|
||||
public String msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* The library-user should report an error to the end-user.
|
||||
* <p>
|
||||
* As most things are asynchronous, things may go wrong at any time and the user should not be disturbed by a dialog or so. Instead, use a bubble or so.
|
||||
* <p>
|
||||
* However, for ongoing processes (eg. configure()) or for functions that are expected to fail (eg. autocryptContinueKeyTransfer()) it might be better to delay showing these events until the function has really failed (returned false). It should be sufficient to report only the *last* error in a message box then.
|
||||
*/
|
||||
public static class Error extends EventType {
|
||||
public String msg;
|
||||
}
|
||||
|
||||
/** An action cannot be performed because the user is not in the group. Reported eg. after a call to setChatName(), setChatProfileImage(), addContactToChat(), removeContactFromChat(), and messages sending functions. */
|
||||
public static class ErrorSelfNotInGroup extends EventType {
|
||||
public String msg;
|
||||
}
|
||||
|
||||
/** Messages or chats changed. One or more messages or chats changed for various reasons in the database: - Messages sent, received or removed - Chats created, deleted or archived - A draft has been set */
|
||||
public static class MsgsChanged extends EventType {
|
||||
/** Set if only a single chat is affected by the changes, otherwise 0. */
|
||||
public Integer chatId;
|
||||
/** Set if only a single message is affected by the changes, otherwise 0. */
|
||||
public Integer msgId;
|
||||
}
|
||||
|
||||
/** Reactions for the message changed. */
|
||||
public static class ReactionsChanged extends EventType {
|
||||
/** ID of the chat which the message belongs to. */
|
||||
public Integer chatId;
|
||||
/** ID of the contact whose reaction set is changed. */
|
||||
public Integer contactId;
|
||||
/** ID of the message for which reactions were changed. */
|
||||
public Integer msgId;
|
||||
}
|
||||
|
||||
/**
|
||||
* A reaction to one's own sent message received. Typically, the UI will show a notification for that.
|
||||
* <p>
|
||||
* In addition to this event, ReactionsChanged is emitted.
|
||||
*/
|
||||
public static class IncomingReaction extends EventType {
|
||||
/** ID of the chat which the message belongs to. */
|
||||
public Integer chatId;
|
||||
/** ID of the contact whose reaction set is changed. */
|
||||
public Integer contactId;
|
||||
/** ID of the message for which reactions were changed. */
|
||||
public Integer msgId;
|
||||
/** The reaction. */
|
||||
public String reaction;
|
||||
}
|
||||
|
||||
/** Incoming webxdc info or summary update, should be notified. */
|
||||
public static class IncomingWebxdcNotify extends EventType {
|
||||
/** ID of the chat. */
|
||||
public Integer chatId;
|
||||
/** ID of the contact sending. */
|
||||
public Integer contactId;
|
||||
/** Link assigned to this notification, if any. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String href;
|
||||
/** ID of the added info message or webxdc instance in case of summary change. */
|
||||
public Integer msgId;
|
||||
/** Text to notify. */
|
||||
public String text;
|
||||
}
|
||||
|
||||
/**
|
||||
* There is a fresh message. Typically, the user will show a notification when receiving this message.
|
||||
* <p>
|
||||
* There is no extra #DC_EVENT_MSGS_CHANGED event sent together with this event.
|
||||
*/
|
||||
public static class IncomingMsg extends EventType {
|
||||
/** ID of the chat where the message is assigned. */
|
||||
public Integer chatId;
|
||||
/** ID of the message. */
|
||||
public Integer msgId;
|
||||
}
|
||||
|
||||
/** Downloading a bunch of messages just finished. This is an event to allow the UI to only show one notification per message bunch, instead of cluttering the user with many notifications. */
|
||||
public static class IncomingMsgBunch extends EventType {
|
||||
}
|
||||
|
||||
/** Messages were seen or noticed. chat id is always set. */
|
||||
public static class MsgsNoticed extends EventType {
|
||||
public Integer chatId;
|
||||
}
|
||||
|
||||
/** A single message is sent successfully. State changed from DC_STATE_OUT_PENDING to DC_STATE_OUT_DELIVERED, see `Message.state`. */
|
||||
public static class MsgDelivered extends EventType {
|
||||
/** ID of the chat which the message belongs to. */
|
||||
public Integer chatId;
|
||||
/** ID of the message that was successfully sent. */
|
||||
public Integer msgId;
|
||||
}
|
||||
|
||||
/** A single message could not be sent. State changed from DC_STATE_OUT_PENDING or DC_STATE_OUT_DELIVERED to DC_STATE_OUT_FAILED, see `Message.state`. */
|
||||
public static class MsgFailed extends EventType {
|
||||
/** ID of the chat which the message belongs to. */
|
||||
public Integer chatId;
|
||||
/** ID of the message that could not be sent. */
|
||||
public Integer msgId;
|
||||
}
|
||||
|
||||
/** A single message is read by the receiver. State changed from DC_STATE_OUT_DELIVERED to DC_STATE_OUT_MDN_RCVD, see `Message.state`. */
|
||||
public static class MsgRead extends EventType {
|
||||
/** ID of the chat which the message belongs to. */
|
||||
public Integer chatId;
|
||||
/** ID of the message that was read. */
|
||||
public Integer msgId;
|
||||
}
|
||||
|
||||
/**
|
||||
* A single message was deleted.
|
||||
* <p>
|
||||
* This event means that the message will no longer appear in the messagelist. UI should remove the message from the messagelist in response to this event if the message is currently displayed.
|
||||
* <p>
|
||||
* The message may have been explicitly deleted by the user or expired. Internally the message may have been removed from the database, moved to the trash chat or hidden.
|
||||
* <p>
|
||||
* This event does not indicate the message deletion from the server.
|
||||
*/
|
||||
public static class MsgDeleted extends EventType {
|
||||
/** ID of the chat where the message was prior to deletion. Never 0. */
|
||||
public Integer chatId;
|
||||
/** ID of the deleted message. Never 0. */
|
||||
public Integer msgId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chat changed. The name or the image of a chat group was changed or members were added or removed. See setChatName(), setChatProfileImage(), addContactToChat() and removeContactFromChat().
|
||||
* <p>
|
||||
* This event does not include ephemeral timer modification, which is a separate event.
|
||||
*/
|
||||
public static class ChatModified extends EventType {
|
||||
public Integer chatId;
|
||||
}
|
||||
|
||||
/** Chat ephemeral timer changed. */
|
||||
public static class ChatEphemeralTimerModified extends EventType {
|
||||
/** Chat ID. */
|
||||
public Integer chatId;
|
||||
/** New ephemeral timer value. */
|
||||
public Integer timer;
|
||||
}
|
||||
|
||||
/** Chat deleted. */
|
||||
public static class ChatDeleted extends EventType {
|
||||
/** Chat ID. */
|
||||
public Integer chat_id;
|
||||
}
|
||||
|
||||
/** Contact(s) created, renamed, blocked or deleted. */
|
||||
public static class ContactsChanged extends EventType {
|
||||
/** If set, this is the contact_id of an added contact that should be selected. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer contactId;
|
||||
}
|
||||
|
||||
/** Location of one or more contact has changed. */
|
||||
public static class LocationChanged extends EventType {
|
||||
/** contact_id of the contact for which the location has changed. If the locations of several contacts have been changed, this parameter is set to `None`. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer contactId;
|
||||
}
|
||||
|
||||
/** Inform about the configuration progress started by configure(). */
|
||||
public static class ConfigureProgress extends EventType {
|
||||
/** Progress comment or error, something to display to the user. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String comment;
|
||||
/**
|
||||
* Progress.
|
||||
* <p>
|
||||
* 0=error, 1-999=progress in permille, 1000=success and done
|
||||
*/
|
||||
public Integer progress;
|
||||
}
|
||||
|
||||
/** Inform about the import/export progress started by imex(). */
|
||||
public static class ImexProgress extends EventType {
|
||||
/** 0=error, 1-999=progress in permille, 1000=success and done */
|
||||
public Integer progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* A file has been exported. A file has been written by imex(). This event may be sent multiple times by a single call to imex().
|
||||
* <p>
|
||||
* A typical purpose for a handler of this event may be to make the file public to some system services.
|
||||
* <p>
|
||||
* @param data2 0
|
||||
*/
|
||||
public static class ImexFileWritten extends EventType {
|
||||
public String path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Progress event sent when SecureJoin protocol has finished from the view of the inviter (Alice, the person who shows the QR code).
|
||||
* <p>
|
||||
* These events are typically sent after a joiner has scanned the QR code generated by getChatSecurejoinQrCodeSvg().
|
||||
*/
|
||||
public static class SecurejoinInviterProgress extends EventType {
|
||||
/** ID of the chat in case of success. */
|
||||
public Integer chatId;
|
||||
/** The type of the joined chat. This can take the same values as `BasicChat.chatType` ([`crate::api::types::chat::BasicChat::chat_type`]). */
|
||||
public ChatType chatType;
|
||||
/** ID of the contact that wants to join. */
|
||||
public Integer contactId;
|
||||
/** Progress, always 1000. */
|
||||
public Integer progress;
|
||||
}
|
||||
|
||||
/** Progress information of a secure-join handshake from the view of the joiner (Bob, the person who scans the QR code). The events are typically sent while secureJoin(), which may take some time, is executed. */
|
||||
public static class SecurejoinJoinerProgress extends EventType {
|
||||
/** ID of the inviting contact. */
|
||||
public Integer contactId;
|
||||
/** Progress as: 400=vg-/vc-request-with-auth sent, typically shown as "alice@addr verified, introducing myself." (Bob has verified alice and waits until Alice does the same for him) 1000=vg-member-added/vc-contact-confirm received */
|
||||
public Integer progress;
|
||||
}
|
||||
|
||||
/** The connectivity to the server changed. This means that you should refresh the connectivity view and possibly the connectivtiy HTML; see getConnectivity() and getConnectivityHtml() for details. */
|
||||
public static class ConnectivityChanged extends EventType {
|
||||
}
|
||||
|
||||
/** Deprecated by `ConfigSynced`. */
|
||||
public static class SelfavatarChanged extends EventType {
|
||||
}
|
||||
|
||||
/** A multi-device synced config value changed. Maybe the app needs to refresh smth. For uniformity this is emitted on the source device too. The value isn't here, otherwise it would be logged which might not be good for privacy. */
|
||||
public static class ConfigSynced extends EventType {
|
||||
/** Configuration key. */
|
||||
public String key;
|
||||
}
|
||||
|
||||
public static class WebxdcStatusUpdate extends EventType {
|
||||
/** Message ID. */
|
||||
public Integer msgId;
|
||||
/** Status update ID. */
|
||||
public Integer statusUpdateSerial;
|
||||
}
|
||||
|
||||
/** Data received over an ephemeral peer channel. */
|
||||
public static class WebxdcRealtimeData extends EventType {
|
||||
/** Realtime data. */
|
||||
public java.util.List<Integer> data;
|
||||
/** Message ID. */
|
||||
public Integer msgId;
|
||||
}
|
||||
|
||||
/** Advertisement received over an ephemeral peer channel. This can be used by bots to initiate peer-to-peer communication from their side. */
|
||||
public static class WebxdcRealtimeAdvertisementReceived extends EventType {
|
||||
/** Message ID of the webxdc instance. */
|
||||
public Integer msgId;
|
||||
}
|
||||
|
||||
/** Inform that a message containing a webxdc instance has been deleted */
|
||||
public static class WebxdcInstanceDeleted extends EventType {
|
||||
/** ID of the deleted message. */
|
||||
public Integer msgId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells that the Background fetch was completed (or timed out). This event acts as a marker, when you reach this event you can be sure that all events emitted during the background fetch were processed.
|
||||
* <p>
|
||||
* This event is only emitted by the account manager
|
||||
*/
|
||||
public static class AccountsBackgroundFetchDone extends EventType {
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform that set of chats or the order of the chats in the chatlist has changed.
|
||||
* <p>
|
||||
* Sometimes this is emitted together with `UIChatlistItemChanged`.
|
||||
*/
|
||||
public static class ChatlistChanged extends EventType {
|
||||
}
|
||||
|
||||
/** Inform that a single chat list item changed and needs to be rerendered. If `chat_id` is set to None, then all currently visible chats need to be rerendered, and all not-visible items need to be cleared from cache if the UI has a cache. */
|
||||
public static class ChatlistItemChanged extends EventType {
|
||||
/** ID of the changed chat */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer chatId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform that the list of accounts has changed (an account removed or added or (not yet implemented) the account order changes)
|
||||
* <p>
|
||||
* This event is only emitted by the account manager
|
||||
*/
|
||||
public static class AccountsChanged extends EventType {
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform that an account property that might be shown in the account list changed, namely: - is_configured (see is_configured()) - displayname - selfavatar - private_tag
|
||||
* <p>
|
||||
* This event is emitted from the account whose property changed.
|
||||
*/
|
||||
public static class AccountsItemChanged extends EventType {
|
||||
}
|
||||
|
||||
/** Inform than some events have been skipped due to event channel overflow. */
|
||||
public static class EventChannelOverflow extends EventType {
|
||||
/** Number of events skipped. */
|
||||
public Integer n;
|
||||
}
|
||||
|
||||
/** Incoming call. */
|
||||
public static class IncomingCall extends EventType {
|
||||
/** ID of the chat which the message belongs to. */
|
||||
public Integer chat_id;
|
||||
/** True if incoming call is a video call. */
|
||||
public Boolean has_video;
|
||||
/** ID of the info message referring to the call. */
|
||||
public Integer msg_id;
|
||||
/** User-defined info as passed to place_outgoing_call() */
|
||||
public String place_call_info;
|
||||
}
|
||||
|
||||
/** Incoming call accepted. This is esp. interesting to stop ringing on other devices. */
|
||||
public static class IncomingCallAccepted extends EventType {
|
||||
/** ID of the chat which the message belongs to. */
|
||||
public Integer chat_id;
|
||||
/** The call was accepted from this device (process). */
|
||||
public Boolean from_this_device;
|
||||
/** ID of the info message referring to the call. */
|
||||
public Integer msg_id;
|
||||
}
|
||||
|
||||
/** Outgoing call accepted. */
|
||||
public static class OutgoingCallAccepted extends EventType {
|
||||
/** User-defined info passed to dc_accept_incoming_call( */
|
||||
public String accept_call_info;
|
||||
/** ID of the chat which the message belongs to. */
|
||||
public Integer chat_id;
|
||||
/** ID of the info message referring to the call. */
|
||||
public Integer msg_id;
|
||||
}
|
||||
|
||||
/** Call ended. */
|
||||
public static class CallEnded extends EventType {
|
||||
/** ID of the chat which the message belongs to. */
|
||||
public Integer chat_id;
|
||||
/** ID of the info message referring to the call. */
|
||||
public Integer msg_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* One or more transports has changed.
|
||||
* <p>
|
||||
* UI should update the list.
|
||||
* <p>
|
||||
* This event is emitted when transport synchronization messages arrives, but not when the UI modifies the transport list by itself.
|
||||
*/
|
||||
public static class TransportsModified extends EventType {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class FullChat {
|
||||
public Boolean archived;
|
||||
public Boolean canSend;
|
||||
public ChatType chatType;
|
||||
public String color;
|
||||
public java.util.List<Integer> contactIds;
|
||||
public Integer ephemeralTimer;
|
||||
public Integer freshMessageCounter;
|
||||
public Integer id;
|
||||
public Boolean isContactRequest;
|
||||
public Boolean isDeviceChat;
|
||||
/**
|
||||
* True if the chat is encrypted. This means that all messages in the chat are encrypted, and all contacts in the chat are "key-contacts", i.e. identified by the PGP key fingerprint.
|
||||
* <p>
|
||||
* False if the chat is unencrypted. This means that all messages in the chat are unencrypted, and all contacts in the chat are "address-contacts", i.e. identified by the email address. The UI should mark this chat e.g. with a mail-letter icon.
|
||||
* <p>
|
||||
* Unencrypted groups are called "ad-hoc groups" and the user can't add/remove members, create a QR invite code, or set an avatar. These options should therefore be disabled in the UI.
|
||||
* <p>
|
||||
* Note that it can happen that an encrypted chat contains unencrypted messages that were received in core <= v1.159.* and vice versa.
|
||||
* <p>
|
||||
* See also `is_key_contact` on `Contact`.
|
||||
*/
|
||||
public Boolean isEncrypted;
|
||||
public Boolean isMuted;
|
||||
public Boolean isSelfTalk;
|
||||
public Boolean isUnpromoted;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String mailingListAddress;
|
||||
public String name;
|
||||
/** Contact IDs of the past chat members. */
|
||||
public java.util.List<Integer> pastContactIds;
|
||||
public Boolean pinned;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String profileImage;
|
||||
/** Note that this is different from [`ChatListItem::is_self_in_group`](`crate::api::types::chat_list::ChatListItemFetchResult::ChatListItem::is_self_in_group`). This property should only be accessed when [`FullChat::chat_type`] is [`Chattype::Group`]. */
|
||||
public Boolean selfInGroup;
|
||||
public Boolean wasSeenRecently;
|
||||
}
|
||||
@@ -2,12 +2,12 @@
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class HttpResponse {
|
||||
/* base64-encoded response body. */
|
||||
/** base64-encoded response body. */
|
||||
public String blob;
|
||||
/* Encoding, e.g. "utf-8". */
|
||||
/** Encoding, e.g. "utf-8". */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String encoding;
|
||||
/* MIME type, e.g. "text/plain" or "text/html". */
|
||||
/** MIME type, e.g. "text/plain" or "text/html". */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String mimetype;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class Location {
|
||||
public Float accuracy;
|
||||
public Integer chatId;
|
||||
public Integer contactId;
|
||||
public Boolean isIndependent;
|
||||
public Float latitude;
|
||||
public Integer locationId;
|
||||
public Float longitude;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String marker;
|
||||
public Integer msgId;
|
||||
public Integer timestamp;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class Message {
|
||||
public Integer chatId;
|
||||
public Integer dimensionsHeight;
|
||||
public Integer dimensionsWidth;
|
||||
public DownloadState downloadState;
|
||||
public Integer duration;
|
||||
/** An error text, if there is one. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String error;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String file;
|
||||
/** The size of the file in bytes, if applicable. If message is a pre-message, then this is the size of the file to be downloaded. */
|
||||
public Integer fileBytes;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String fileMime;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String fileName;
|
||||
public Integer fromId;
|
||||
public Boolean hasDeviatingTimestamp;
|
||||
public Boolean hasHtml;
|
||||
/** Check if a message has a POI location bound to it. These locations are also returned by `get_locations` method. The UI may decide to display a special icon beside such messages. */
|
||||
public Boolean hasLocation;
|
||||
public Integer id;
|
||||
/** if is_info is set, this refers to the contact profile that should be opened when the info message is tapped. */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer infoContactId;
|
||||
/** True if the message was sent by a bot. */
|
||||
public Boolean isBot;
|
||||
public Boolean isEdited;
|
||||
public Boolean isForwarded;
|
||||
public Boolean isInfo;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer originalMsgId;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String overrideSenderName;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer parentId;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public MessageQuote quote;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Reactions reactions;
|
||||
public Integer receivedTimestamp;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer savedMessageId;
|
||||
public Contact sender;
|
||||
/**
|
||||
* True if the message was correctly encrypted&signed, false otherwise. Historically, UIs showed a small padlock on the message then.
|
||||
* <p>
|
||||
* Today, the UIs should instead show a small email-icon on the message if `show_padlock` is `false`, and nothing if it is `true`.
|
||||
*/
|
||||
public Boolean showPadlock;
|
||||
public Integer sortTimestamp;
|
||||
public Integer state;
|
||||
public String subject;
|
||||
/** when is_info is true this describes what type of system message it is */
|
||||
public SystemMessageType systemMessageType;
|
||||
public String text;
|
||||
public Integer timestamp;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public VcardContact vcardContact;
|
||||
public Viewtype viewType;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String webxdcHref;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class MessageData {
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String file;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String filename;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String html;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Pair<Float, Float> location;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String overrideSenderName;
|
||||
/** Quoted message id. Takes preference over `quoted_text` (see below). */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer quotedMessageId;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String quotedText;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String text;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Viewtype viewtype;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
public class MessageInfo {
|
||||
public EphemeralTimer ephemeralTimer;
|
||||
/** When message is ephemeral this contains the timestamp of the message expiry */
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public Integer ephemeralTimestamp;
|
||||
@com.fasterxml.jackson.annotation.JsonSetter(nulls = com.fasterxml.jackson.annotation.Nulls.SET)
|
||||
public String error;
|
||||
public String hopInfo;
|
||||
public String rfc724Mid;
|
||||
public java.util.List<String> serverUrls;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/* Autogenerated file, do not edit manually */
|
||||
package chat.delta.rpc.types;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
|
||||
|
||||
@JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="kind")
|
||||
@JsonSubTypes({@Type(value = MessageListItem.Message.class, name="Message"), @Type(value = MessageListItem.DayMarker.class, name="DayMarker")})
|
||||
public abstract class MessageListItem {
|
||||
|
||||
public static class Message extends MessageListItem {
|
||||
public Integer msg_id;
|
||||
}
|
||||
|
||||
/** Day marker, separating messages that correspond to different days according to local time. */
|
||||
public static class DayMarker extends MessageListItem {
|
||||
/** Marker timestamp, for day markers, in unix milliseconds */
|
||||
public Integer timestamp;
|
||||
}
|
||||
|
||||
}
|
||||