mirror of
https://github.com/ArcaneChat/android.git
synced 2026-07-03 14:05:24 +02:00
Compare commits
657 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ebfd9ca122 | |||
| 91f8e88db3 | |||
| a93b12909d | |||
| 8403abc5b9 | |||
| c49599f9c8 | |||
| ec590613d0 | |||
| 0c914b3771 | |||
| 24e363e130 | |||
| 85b9444f86 | |||
| 19f6bd3b5c | |||
| 1999bab9a0 | |||
| 44eb9b32fd | |||
| c5cf11d36a | |||
| fc36c6793e | |||
| 257e200c9c | |||
| 2c2bd2bf48 | |||
| 95fbe25b0a | |||
| 97552bc751 | |||
| a81cdb79ad | |||
| 1b8de09c41 | |||
| db427a036e | |||
| ab2151b974 | |||
| 0fa59fa22d | |||
| ec7807e662 | |||
| d47196d899 | |||
| b692abc235 | |||
| e3809cf1f8 | |||
| 564c0fe27d | |||
| 705e283cf5 | |||
| 40b5e10999 | |||
| d1f77d9de5 | |||
| 0704f7f1e7 | |||
| 0eb02b59a3 | |||
| 770861d6db | |||
| 17986e9d86 | |||
| 5ce1f415ce | |||
| e1c92712a0 | |||
| 6ec0f1bfce | |||
| db410d8b44 | |||
| cd07f3de96 | |||
| 12072a0342 | |||
| c6f3761bb9 | |||
| 673f0e78b1 | |||
| 65c8960ec8 | |||
| 089ecc67d1 | |||
| 0f84af5b32 | |||
| 710ed6dd56 | |||
| 335aabd4ff | |||
| 98c97a8aed | |||
| 23d18d2ac5 | |||
| a136b8b1e5 | |||
| 7f8b71cf28 | |||
| 9e5f2b18b9 | |||
| bdfeddecd5 | |||
| 23cbe63cd4 | |||
| f0f53455a5 | |||
| d8b49f57a9 | |||
| 7eaaf3bbb4 | |||
| d4f83cd38b | |||
| 9eca5f518e | |||
| d17bed02e6 | |||
| b4b194a59b | |||
| c6f62a2b81 | |||
| e3a9f42a56 | |||
| 323bcef1fe | |||
| 095b92b498 | |||
| 18c2ccd66c | |||
| 28fdeac01c | |||
| a7e4267b9b | |||
| d6837aa121 | |||
| 5a2913b36f | |||
| 20180fa89c | |||
| c6b89055d8 | |||
| bfda7ab2c3 | |||
| 953ce32bea | |||
| 961fa5ffe6 | |||
| b1b2959bcb | |||
| 70ef715dc6 | |||
| ffa58aae34 | |||
| 24f5209c03 | |||
| 7fd96732d6 | |||
| 6e0759f719 | |||
| 63434e1e2f | |||
| 9c17bc412a | |||
| d40144d50c | |||
| 131c0f5a37 | |||
| 7086314d8b | |||
| d75b2c2bb7 | |||
| c46d174869 | |||
| 17e03f2903 | |||
| 2c12a34051 | |||
| 2d3dde2101 | |||
| d539f5ecf2 | |||
| b17d6be4fc | |||
| 3c737f2360 | |||
| 9ac5e714b8 | |||
| 94defa3091 | |||
| 052ada221e | |||
| 1d5e4cf2a9 | |||
| c46aef3ea0 | |||
| d30e141693 | |||
| 305940396e | |||
| 2ab567a9d3 | |||
| a9c488ff03 | |||
| 8817b50c95 | |||
| 84c3710a35 | |||
| be7be9bba4 | |||
| b50ae284fb | |||
| 97716d5c26 | |||
| e77253c843 | |||
| 6aed8d003f | |||
| 0083e60c49 | |||
| 0fc79fd845 | |||
| a7c3bc7ac5 | |||
| 83b16e5f4b | |||
| ee17c6d75e | |||
| c0525ac69c | |||
| e9d2a39098 | |||
| 4d6fd16767 | |||
| b398870823 | |||
| e68c50d614 | |||
| f6a27718a2 | |||
| f136fa3e3a | |||
| 8e55a3dbf3 | |||
| 923227a0e8 | |||
| 14ecafe0e2 | |||
| b93f8323ab | |||
| 77f43cde9a | |||
| e4d018393d | |||
| 9a816090de | |||
| 4b04aa65be | |||
| 489bb55788 | |||
| 9d244611bc | |||
| 3533916149 | |||
| 46bc3e7f72 | |||
| ed0f0107e3 | |||
| a855d7043a | |||
| 66fd795763 | |||
| 05da43484f | |||
| a58de2278b | |||
| 6743df23e9 | |||
| 35ec0d05e2 | |||
| 6ead7207ec | |||
| 0d5223036d | |||
| 640fc433b8 | |||
| 35d814c3f6 | |||
| f8b9d2b0d9 | |||
| 3390b865e0 | |||
| 883486da9c | |||
| d048203f45 | |||
| f9d70d1196 | |||
| 4413b7b4fb | |||
| 7a4f263a62 | |||
| 1a360d5282 | |||
| dc785fc116 | |||
| 009593f7cc | |||
| 884be3a93e | |||
| 9a25328787 | |||
| 2d8ec490b1 | |||
| 3b19ca99e1 | |||
| f751a48568 | |||
| 4549989a63 | |||
| 19e2c4e051 | |||
| 6f5e90be53 | |||
| 34fa0620ab | |||
| fe37af1a3f | |||
| 3459802d67 | |||
| b8bf847941 | |||
| 5b6024584a | |||
| 4833a44542 | |||
| eb93e2bb7e | |||
| 291700dfc7 | |||
| 7a4913b394 | |||
| 0dae71f4b7 | |||
| 08e4229533 | |||
| 101a31628d | |||
| 2a2ce883b4 | |||
| 5a0e26bdb5 | |||
| 0c9277dfd0 | |||
| 37886cf296 | |||
| df5ba2eced | |||
| 3c2ddb96b3 | |||
| e2a825dfb2 | |||
| 8d49c7e595 | |||
| 966d5dac24 | |||
| 7f684f4d2e | |||
| 1510f7f3a8 | |||
| 6916becf7f | |||
| ad5b496f5c | |||
| e647401db4 | |||
| 3113f9c3ab | |||
| a1e47865c5 | |||
| 3a5f9b3fed | |||
| 5ffbc19d03 | |||
| d9db4b818a | |||
| 693efdbd0f | |||
| 399b783437 | |||
| 4bc574dfbe | |||
| 294af0981d | |||
| e8c7014993 | |||
| 0edc8303c1 | |||
| 8c89c3e225 | |||
| a93c8ab055 | |||
| c5cb79d116 | |||
| b3c50b9571 | |||
| 41579de502 | |||
| e6f735b8bc | |||
| 70b6f2cdfa | |||
| c1e716d6a3 | |||
| dde59b4673 | |||
| 9d77920adf | |||
| 6f50ee0cfb | |||
| 4c86d6d49e | |||
| 963327dd64 | |||
| 5cba1ccd98 | |||
| de8e6b6852 | |||
| 811089f3b3 | |||
| e045a09d36 | |||
| a3a6919b08 | |||
| cbee839a43 | |||
| efdd92b6a1 | |||
| 75296e189a | |||
| 708a68119e | |||
| 1d5ab98892 | |||
| 07753e211d | |||
| 8135d96300 | |||
| d151e825da | |||
| d5289cc3df | |||
| af40a8b57e | |||
| 529139099e | |||
| b4aa18abae | |||
| a7cee63d1c | |||
| eda735925a | |||
| 46650c8cc3 | |||
| fbab156d22 | |||
| 539cb670f1 | |||
| 2a6aba110b | |||
| 0351a1e974 | |||
| d48ab128a0 | |||
| ef67585529 | |||
| 953e7c6da0 | |||
| ab5a9c9d60 | |||
| af91cf7413 | |||
| 6a618986d0 | |||
| 9eefcacbc1 | |||
| e245e29058 | |||
| 7d879f8d1f | |||
| f7963a56e9 | |||
| 0a73877c25 | |||
| 1b57880be3 | |||
| f54144e7e8 | |||
| b735759bd0 | |||
| a7199ecedf | |||
| 2cb529be32 | |||
| 235038027b | |||
| e8eb036594 | |||
| d531eb8b47 | |||
| a88a619099 | |||
| 00bc429f20 | |||
| 3f25d002e4 | |||
| 74c6f20c3e | |||
| 8728a0a39b | |||
| dcf5cf7f54 | |||
| 7f89ecea5c | |||
| 30a63dd13b | |||
| a5d2642c37 | |||
| 79e5eedab0 | |||
| 27da217eb7 | |||
| a0c71a5387 | |||
| 4d19a59cb6 | |||
| 819a9f415a | |||
| dff1ef3778 | |||
| 7131f5774e | |||
| aa572508dc | |||
| 1f880efb3f | |||
| 72ace5c156 | |||
| 2f34a6ffa4 | |||
| afdfe7bbaa | |||
| 14f43f2a79 | |||
| f3353cf6e9 | |||
| 722f2cad1e | |||
| b135093628 | |||
| be44789b01 | |||
| 233197095b | |||
| 494cb728c3 | |||
| 60e9a9101a | |||
| c23dac6f99 | |||
| 3965319ef4 | |||
| c4db7c515f | |||
| fbf88e102b | |||
| d5ea043893 | |||
| f70c79ba4a | |||
| 0b2a26e2f1 | |||
| b968ba67b3 | |||
| e234cc864b | |||
| b47e75eed6 | |||
| 6b684bf030 | |||
| ea89d37461 | |||
| 814af177d1 | |||
| 1ccbb7177f | |||
| 3118dbd32b | |||
| 1a5e062dac | |||
| 0bcaea6f01 | |||
| 8283a6c4ad | |||
| cd159bac6c | |||
| 21f917004f | |||
| 0abf2ff00c | |||
| 0ca92ec6b5 | |||
| e66fa53537 | |||
| a51013cc00 | |||
| 171500a97d | |||
| 9a4851961e | |||
| e5ddbacb2e | |||
| 03c7d78e2b | |||
| 00498b02b3 | |||
| ad6e2d1a9f | |||
| 5cfa71cd72 | |||
| 0551044ef9 | |||
| 5126b3eeb2 | |||
| 8d7078f96f | |||
| c446440537 | |||
| 333e4c9eca | |||
| fb1f5df234 | |||
| cc419a9f62 | |||
| 2469b6efef | |||
| b7446c9a93 | |||
| 0c9b5bbaf4 | |||
| 3126544f00 | |||
| ccdad0469d | |||
| 9f3eeb3d0d | |||
| 92bc53b672 | |||
| 1355303360 | |||
| 7227f513a5 | |||
| 4933d66000 | |||
| 977b21618c | |||
| 5cecd5bec3 | |||
| d8db39f9c7 | |||
| 736fc44870 | |||
| 537127ec4e | |||
| a5167f3739 | |||
| d481541ad8 | |||
| 7ab19fb8af | |||
| 715a2c0653 | |||
| 350cd0539c | |||
| 9f8fe08c75 | |||
| 5048239563 | |||
| 6e135e06a9 | |||
| d52647b288 | |||
| c0a729978c | |||
| 041c95c6d2 | |||
| 8de0fed18e | |||
| dd75a8e858 | |||
| 2e77db23d5 | |||
| 04a4a02235 | |||
| 2910730bc1 | |||
| 23458a6c64 | |||
| 9679b22072 | |||
| 3fae301ec2 | |||
| d08069f7b0 | |||
| 56a0607a5e | |||
| 9c08617f7d | |||
| 812dc8d738 | |||
| d8b278a1f5 | |||
| 4368a4f63e | |||
| 72ae90ae93 | |||
| c36ce7a8ab | |||
| 404097fe30 | |||
| 07d5c719d4 | |||
| 13a43473cc | |||
| 5a84198829 | |||
| 1f443cd87c | |||
| 4901b92ee2 | |||
| cd48e15071 | |||
| 2d4b570f48 | |||
| 3f0b36bd4b | |||
| b342fb9c30 | |||
| 0974655366 | |||
| 9675c419ac | |||
| de4e95d495 | |||
| 7a738abba8 | |||
| 512f8104e2 | |||
| 0cd445f4e7 | |||
| dbfbb9060b | |||
| f2f910fe23 | |||
| 7dde6ad61a | |||
| ca947aeef2 | |||
| 1680d14835 | |||
| b5a2280776 | |||
| ab61246240 | |||
| 957a5f75dc | |||
| dad490074b | |||
| 09640c88ac | |||
| 021a98c135 | |||
| deacf8efef | |||
| 6c482af28a | |||
| cfd9371739 | |||
| c58a77dc26 | |||
| e45d722ba1 | |||
| 83213d14ad | |||
| 931476a196 | |||
| 4ce3869744 | |||
| 5dee44605d | |||
| 249d57897e | |||
| 3c9cecbc39 | |||
| 5a2c28b91d | |||
| 7758f6d991 | |||
| 285f59e46a | |||
| 91f8ce7cda | |||
| 12ad3daa28 | |||
| eaa6981523 | |||
| cd8f799f14 | |||
| 69fb68a873 | |||
| 5954b13440 | |||
| a7647e18e2 | |||
| e025da4e91 | |||
| 8ba93f8b82 | |||
| 849c6798c0 | |||
| 7a85cf9db5 | |||
| aa45476028 | |||
| c12ed8060c | |||
| 90c8650aaf | |||
| 6f530215af | |||
| e8c4d0e606 | |||
| 7feb4bc93f | |||
| e4b1d52d1a | |||
| efc09f142a | |||
| e5b8e488a4 | |||
| d397ccaf7e | |||
| f7bd609f91 | |||
| a118c33f89 | |||
| 86a9da5062 | |||
| d3328df6f2 | |||
| 169a706e36 | |||
| bf2fd62154 | |||
| e74795851a | |||
| 139b7f84f4 | |||
| 3d55ea931c | |||
| 73ada05e99 | |||
| 7ecba725a0 | |||
| 6cad73a00b | |||
| c5e675a72e | |||
| 75f779e47b | |||
| 2b1bb6e434 | |||
| ca8dcfc599 | |||
| a26764355e | |||
| d92265cd63 | |||
| 1787dc4c8b | |||
| 1293d419f5 | |||
| 421db5b403 | |||
| 5f77f791d0 | |||
| aa78c607ce | |||
| 7bb855e32a | |||
| eaa24e89f8 | |||
| fc5a3e5c75 | |||
| 6fe5ed32cb | |||
| 304942e98b | |||
| 44df03ad52 | |||
| c485aa9f6a | |||
| cb416e6959 | |||
| ee6c464a5b | |||
| 8790b26123 | |||
| 04d2eb99aa | |||
| 5627f5f123 | |||
| 7a66085107 | |||
| aa45a9082e | |||
| 3955f4d505 | |||
| 74dd4c0d9a | |||
| 23eb418591 | |||
| edcfa80d92 | |||
| 5ff1f3d915 | |||
| b0ae2da439 | |||
| 8487c286e6 | |||
| ffa9177094 | |||
| 6f3d8a4414 | |||
| 9bbee2db10 | |||
| 30580366fd | |||
| ec4bffdabe | |||
| ca2d8f4b6e | |||
| a7f0f753fd | |||
| 4025fd5e0b | |||
| 577959a51a | |||
| 776dc05755 | |||
| 28141bf942 | |||
| 3431163c24 | |||
| 45cb3a953c | |||
| 3080313568 | |||
| f13251bc07 | |||
| 6a7c498481 | |||
| b72a1ec7d8 | |||
| 5fd06f2b9d | |||
| 899b075349 | |||
| 1c0dc91f03 | |||
| a76762f321 | |||
| 86ebb6e1a8 | |||
| ecf87c58e1 | |||
| 0bef0b3501 | |||
| bc6d676fcd | |||
| 8aa615157a | |||
| 9ffa76c0f4 | |||
| 9fc4bfb970 | |||
| 1bc40837fe | |||
| ba3ea172e5 | |||
| 3a4c02c8cd | |||
| 4b9d521c13 | |||
| df9e3007b2 | |||
| 117f144858 | |||
| e17d37ebb7 | |||
| 08200d8443 | |||
| 9809e3edd6 | |||
| 2255c267ef | |||
| 4a83f4005a | |||
| 8ea78b1930 | |||
| 9d4b5e8fed | |||
| ca74afb229 | |||
| 1757c417fa | |||
| 4e6119b85d | |||
| 91467e5c65 | |||
| 2870ad988f | |||
| a35da9ac7c | |||
| e4543be71c | |||
| b1e4d4dbe5 | |||
| e6f9eda787 | |||
| 12b5f0767c | |||
| 0bd2c2f825 | |||
| 5c9afb910d | |||
| e41e3374e8 | |||
| 0be6457cd1 | |||
| f3fa1d5e7c | |||
| 5f2b4590c0 | |||
| be4bc8259e | |||
| 529842ad60 | |||
| 78bd221fdf | |||
| 054902eb67 | |||
| ef578da78d | |||
| 884cce3e1a | |||
| fc6bdc2fea | |||
| e441a582dd | |||
| 3e3a01dd62 | |||
| 1cda594e02 | |||
| 357e6de031 | |||
| 30ac01a57e | |||
| de5d45d04d | |||
| c599fc8e79 | |||
| 295e1b50d2 | |||
| ef8838cbe3 | |||
| eed124a0f2 | |||
| 18974ff023 | |||
| e666bbf610 | |||
| 0330485123 | |||
| 56717d3f44 | |||
| 958bdddacf | |||
| 6375b85ef9 | |||
| e076691f2a | |||
| 4635cbbe4f | |||
| 71311d43e8 | |||
| 6efe540310 | |||
| 1843c29b7c | |||
| 653d940242 | |||
| 2f3a730be7 | |||
| 7a2401a3d5 | |||
| 6690add48f | |||
| ace1c99daa | |||
| 125ac5e7b3 | |||
| b3248c9f6d | |||
| 00d1803631 | |||
| 0482889dfa | |||
| 6113195977 | |||
| 4a02d6c73d | |||
| a252eec698 | |||
| b89e094f9f | |||
| 6fa725e8ff | |||
| efb38db3ef | |||
| 8ef136d6b2 | |||
| 3412dc8a0f | |||
| 6cb1c0fad4 | |||
| bfb1fc0281 | |||
| bc511d6100 | |||
| 1ae69feb80 | |||
| 19fac45062 | |||
| fd8311cfc9 | |||
| 973e278d71 | |||
| 95f09a67f5 | |||
| 78ad04bd7b | |||
| 59435e8975 | |||
| bc94eba1da | |||
| 6c9d1592f8 | |||
| 56b925f600 | |||
| 5a5ea83fa0 | |||
| 3033000e4e | |||
| 9f8da69b25 | |||
| aa52f8172d | |||
| 82ddcd0839 | |||
| 8d99b36347 | |||
| 589fa8e3dd | |||
| 434b40e51e | |||
| 755c346d82 | |||
| b13defdf9c | |||
| fbe533c701 | |||
| 13ebad4942 | |||
| f9539c160e | |||
| 0195f2f78f | |||
| 64553b5655 | |||
| ce38181502 | |||
| 4c58f31dc6 | |||
| e5a2bde5c4 | |||
| d984bf15a0 | |||
| ab2904e274 | |||
| c751d7015c | |||
| eef3be840b | |||
| fed96377f5 | |||
| 774bee1e28 | |||
| c0b3d87ff9 | |||
| e72eed807f | |||
| cd1821f6a7 | |||
| e79f4ef84e | |||
| 8071f64669 | |||
| fd2d3a5b5a | |||
| 2e500ce97b | |||
| 997d03829e | |||
| 67d6a2aed3 | |||
| 884481fa9e | |||
| 4c90890643 | |||
| 1209ec02f9 | |||
| 63e4b25cbf | |||
| acdde4c0a0 | |||
| a9fba59386 | |||
| 4ef7fc0401 | |||
| 148f07729c | |||
| 529f46f226 | |||
| 7ad8a48255 | |||
| 3d7d3157fc | |||
| 6b34438958 | |||
| 31bc04d190 | |||
| c1c2aa4930 | |||
| 78a9bd98b0 | |||
| c058eb2927 | |||
| 6180397f8f | |||
| b4bb2e2b5d | |||
| e717837e6c | |||
| b7ae41b249 | |||
| 270e31fc58 | |||
| 5900b340e4 | |||
| 066d794360 | |||
| c9d9d915a1 | |||
| d397f7f16e | |||
| d1d379b9b1 | |||
| a4abc0181b | |||
| 7c762bbb6c | |||
| 0d3e009500 | |||
| d16d58b77a | |||
| f4bbb61313 | |||
| a38a29167e | |||
| cf954d0970 | |||
| 7ded91d8af | |||
| 27d7e3b27d | |||
| 669e21b6f1 | |||
| b7e4dda6f5 |
@@ -0,0 +1,3 @@
|
||||
ko_fi: adbenitez
|
||||
liberapay: adbenitez
|
||||
custom: "https://arcanechat.me/#contribute"
|
||||
@@ -1 +1 @@
|
||||
blank_issues_enabled: true
|
||||
blank_issues_enabled: false
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- uses: nttld/setup-ndk@v1
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r23c
|
||||
ndk-version: r27
|
||||
|
||||
- name: Compile core
|
||||
env:
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
run: ./gradlew --no-daemon -PABI_FILTER=armeabi-v7a assembleFossDebug
|
||||
|
||||
- name: Upload APK
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: app-preview.apk
|
||||
path: 'build/outputs/apk/foss/debug/*.apk'
|
||||
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
- uses: nttld/setup-ndk@v1
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r23c
|
||||
ndk-version: r27
|
||||
|
||||
- name: Compile core
|
||||
env:
|
||||
@@ -49,18 +49,22 @@ jobs:
|
||||
- name: Build APK
|
||||
run: |
|
||||
mkdir -p ~/.gradle
|
||||
echo -n ${{ secrets.SIGNING_KEY }} | base64 -d >> ~/app.keystore
|
||||
echo "DC_RELEASE_STORE_FILE=$HOME/app.keystore" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_STORE_PASSWORD=${{ secrets.KEY_STORE_PASSWORD }}" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_KEY_ALIAS=${{ secrets.ALIAS }}" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> ~/.gradle/gradle.properties
|
||||
./gradlew --no-daemon assembleFossRelease
|
||||
echo -n ${{ secrets.KEYSTORE_FILE }} | base64 -d >> ~/keystore.jks
|
||||
echo "DC_RELEASE_STORE_FILE=$HOME/keystore.jks" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_STORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_KEY_ALIAS_FDROID=${{ secrets.ALIAS_FDROID }}" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_KEY_ALIAS_GPLAY=${{ secrets.ALIAS_GPLAY }}" >> ~/.gradle/gradle.properties
|
||||
echo "DC_RELEASE_KEY_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> ~/.gradle/gradle.properties
|
||||
./gradlew assembleFossRelease
|
||||
rm build/outputs/apk/foss/release/*universal*
|
||||
./gradlew assembleGplayRelease
|
||||
mv build/outputs/apk/gplay/release/*universal* build/outputs/apk/foss/release/ArcaneChat-gplay.apk
|
||||
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
body: "If you don't know what APK file to download for your phone, download the one that has 'universal' in its name, it should work for all phones"
|
||||
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-IzzyOnDroid.png" alt="Get it on IzzyOnDroid" height="48">](https://apt.izzysoft.de/fdroid/index/apk/chat.delta.lite) [<img src="store/get-it-on-apklis.png" alt="Disponible en Apklis" height="48">](https://www.apklis.cu/application/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
|
||||
|
||||
+195
-2
@@ -1,4 +1,197 @@
|
||||
# Delta Chat Android Changelog
|
||||
# ArcaneChat Android Changelog
|
||||
|
||||
## v1.54.0
|
||||
2025-02
|
||||
|
||||
* enhanced "Saved Messages" feature, now when forwarding a message to "Saved Messages" chat, it retains the sender information and a button to jump to the original message
|
||||
* Saved messages are marked by a bookmark sign
|
||||
* improve explanation when blocking a contact
|
||||
* improve wording in empty "apps" and "files" tabs in chat media screen
|
||||
* remove deprecated/legacy built-in "half-camera"
|
||||
* UI improvement: keep avatars aligned to message bubble when message has reactions
|
||||
* fix problems when opening attachments in external apps
|
||||
* fix a bug with some big images appearing as blank/transparent
|
||||
* some other small bug fixes
|
||||
* update translations
|
||||
* update to core 1.155.4
|
||||
|
||||
## v1.52.1
|
||||
2025-01
|
||||
|
||||
* the app now requires less storage on your SD card by deduplicating newly received/sent files
|
||||
* some small bug fixes
|
||||
* update translations
|
||||
* update to core 1.155.1
|
||||
|
||||
## v1.52.0
|
||||
2025-01
|
||||
|
||||
* new group consistency algorithm
|
||||
* fix: don't show animated .webp stickers as static stickers
|
||||
* fix the chat shortcuts (created via long-press in launcher) to properly support multi-profile
|
||||
* fix some small bugs in certain android versions and special situations
|
||||
* avoid the app freezing in slow phones in some situations
|
||||
* improve menu in the help screen
|
||||
* update translations
|
||||
* update to core 1.155.0
|
||||
|
||||
## v1.50.5
|
||||
2025-01
|
||||
|
||||
* fix push-notifications handling for certain devices where it was not working correctly
|
||||
* update translations
|
||||
* using core 1.153.0
|
||||
|
||||
## v1.50.4
|
||||
2025-01
|
||||
|
||||
* properly send as animated stickers GIF files selected from keyboard
|
||||
* improve emoji picker in landscape mode and when changing from landscape to portrait
|
||||
* avoid crash when receiving push notifications if the user restricted the app from working in background
|
||||
* improve UI when attaching a file or image to easily recognize it is attached but not sent yet
|
||||
* avoid slow loading of in-chat apps in some devices when quickly re-opening an app after closing it
|
||||
* allow to select multiple images at once in the media picker via "Gallery" button
|
||||
* mark holiday notice messages as bot-generated
|
||||
* don't mark contacts as bot when receiving location-only and sync messages
|
||||
* prefer to encrypt even if peers have their preference to "no preference"
|
||||
* start ephemeral messages timers when the chat is archived or noticed
|
||||
* several bug fixes and updated translations
|
||||
* update to core 1.153.0
|
||||
|
||||
## v1.50.3
|
||||
2024-12
|
||||
|
||||
* Add in-chat apps picker to attachments options
|
||||
* Notify replies and reactions to your messages in muted chats (can be disabled in settings)
|
||||
* Cache HTTP GET requests (ex. when loading images from HTML messages)
|
||||
* update to core 1.152.0
|
||||
|
||||
## v1.50.2
|
||||
2024-12
|
||||
|
||||
* Encrypt notification tokens
|
||||
* update to core 1.151.5
|
||||
|
||||
## v1.50.0
|
||||
2024-12
|
||||
|
||||
* New emoji picker with support for more emojis
|
||||
* Webxdc apps can now trigger notifications
|
||||
* Webxdc apps can now deep-link to internal sections when you click their info-messages in chat
|
||||
* Add "Show in Chat" to the menu of opened Webxdc apps
|
||||
* Reverse order of messages in the notification group
|
||||
* Notify reactions to own messages
|
||||
* Improve the button to start Webxdc apps
|
||||
* Make account deletion confirmation dialog faster
|
||||
* Rename "Back up Chats to External Storage" to "Export Backup"
|
||||
* Improve compatibility with classic email clients in the outgoing messages
|
||||
* Removed internal font scaling setting in favor of the better system settings
|
||||
* Use privacy-preserving webxdc addresses
|
||||
* Use Rustls for connections with strict TLS
|
||||
* QR codes for adding contacts and joining groups provide help when opened in a normal browser
|
||||
* Mark Saved Messages chat as protected
|
||||
* Allow the user to replace maps integration
|
||||
* fix: Trim whitespace from scanned QR codes
|
||||
* fix quotes: Line-before-quote may be up to 120 character long instead of 80
|
||||
* fix: Prevent accidental wrong-password-notifications
|
||||
* fix: Remove footers from "Show Full Message..."
|
||||
* fix: Only add "member added/removed" messages if they actually do that
|
||||
* fix: Update state of message when fully downloading it
|
||||
* fix: send message: Do not fail if the message does not exist anymore
|
||||
* fix: Do not percent-encode dot when passing to autoconfig server (so, fix handling of some servers)
|
||||
* fix displaynames not being updated when intially scanned by a QR code
|
||||
* several bug fixes
|
||||
* update to core 1.151.3
|
||||
|
||||
## v1.48.3
|
||||
2024-10
|
||||
|
||||
* new Proxy settings screen available at "Advanced / Proxy"
|
||||
* manage a list of HTTP(S), SOCKS5 or Shadowsocks Proxies
|
||||
* Proxies icon shown on the chatlist if proxies are used
|
||||
* share Proxies by showing a QR code
|
||||
* scan Proxies' QR code and use them
|
||||
* make Proxy URLs inside Delta Chat tappable
|
||||
* open Delta Chat when tapping Proxy URLs in other apps
|
||||
* support for realtime webxdc apps moved out of experimental and enabled by default
|
||||
* realtime webxdc apps can be disabled at "Settings / Advanced"
|
||||
* "New Contact / Link" button to view, share or copy the invite line
|
||||
* "New Contact / Scan" button to easier access the scanner functionality
|
||||
* open "New Contact" scan/show activities directly, do not try to be too smart and open the last active tab
|
||||
* allow to attach multiple images in one step
|
||||
* to easier differ between multiple profiles, set a "Private Tag" (long tap profile switcher)
|
||||
* "Private Tag" is shown in notifications
|
||||
* improve profile deletion dialog: show name, size and avatar of the profile being deleted
|
||||
* show profile name in title bar when the user has multiple profiles
|
||||
* improve profile switcher layout
|
||||
* improve notification: allow to "Mark Read" from the notification
|
||||
* search for unread chats in the search's three-dot-menu
|
||||
* allow pasting QR codes from "Add As Second Device" screen
|
||||
* save traffic by supporting "IMAP COMPRESS"
|
||||
* automatic reconfiguration, e.g. switching to implicit TLS if STARTTLS port stops working
|
||||
* parallelize IMAP and SMTP connection attempts
|
||||
* improve DNS caching
|
||||
* always use preloaded DNS results
|
||||
* prioritize cached results if DNS resolver returns many results
|
||||
* always move auto-generated messages to DeltaChat folder
|
||||
* ignore invalid securejoin messages silently
|
||||
* delete messages from a chatmail server immediately by default
|
||||
* make resending pending messages possible
|
||||
* don't SMTP-send messages to self-chat if BccSelf is disabled
|
||||
* HTTP(S) tunneling
|
||||
* don't put displayname into From/To/Sender if it equals to address
|
||||
* hide sync messages from INBOX (use IMAP APPEND command to upload sync messages)
|
||||
* more verbose SMTP connection establishment errors
|
||||
* add "Learn More" button to "Manage keys"
|
||||
* visual feedback when tapping the action button of a message
|
||||
* log unexpected message state when resending fails
|
||||
* smoother backup and "Add Second Device" progress bars
|
||||
* assign messages to ad-hoc group with matching name and members
|
||||
* use stricter TLS checks for HTTPS downloads (images in HTML mails, Autoconfig)
|
||||
* improve logging for failed QR code scans, AEAP, Autocrypt, notification permissions and sending errors
|
||||
* improve logging of multi account setup (log account ID)
|
||||
* show more context for the "Cannot establish guaranteed..." info message
|
||||
* show file name in "Message Info"
|
||||
* show root SMTP connection failure in connectivity view
|
||||
* fix: Sort received outgoing message down if it's fresher than all non fresh messages
|
||||
* fix: avoid app being killed when processing a PUSH notification
|
||||
* fix crash when refreshing avatar
|
||||
* fix crash in gallery
|
||||
* fix: shorten message text in locally sent messages too
|
||||
* fix: Set http I/O timeout to 1 minute rather than whole request timeout
|
||||
* fix: don't sync QR code token before populating the group
|
||||
* fix: do not get stuck if the message to download does not exist anymore
|
||||
* fix: do not attempt to reference info messages
|
||||
* fix: do not get stuck if there is an error transferring backup
|
||||
* fix: make it possible to cancel ongoing backup transfer
|
||||
* fix: reset quota when entering a new address
|
||||
* fix: better detection of file extensions
|
||||
* fix: "database locked" errors
|
||||
* fix: never initialize realtime channels if realtime is disabled
|
||||
* fix reception of realtime channels
|
||||
* fix: normalize proxy URLs
|
||||
* fix connections getting stuck in "Updating..." sometimes
|
||||
* fix scanning "add second device" QR code from scanner above chatlist
|
||||
* fix warning about wrong password
|
||||
* fix app getting stale when receiving a PUSH notifications takes longer
|
||||
* fix app getting stale on network changes
|
||||
* fix: skip IDLE if we got unsolicited FETCH
|
||||
* update translations and local help
|
||||
* update to core 1.148.6
|
||||
|
||||
|
||||
## v1.46.14
|
||||
2024-09
|
||||
|
||||
* add monochrome/themed launcher icon support
|
||||
* allow to remove the selected profile in "Switch Profile" dialog
|
||||
* improve display of selected profile in "Switch Profile" dialog
|
||||
* improve the hit/tap area to open "Switch Profile" dialog in the main screen's toolbar
|
||||
* add support for system per-app language and remove in-app language selector
|
||||
* remove the experimental "encrypt database" checkbox in classic registration screen
|
||||
* fix various bugs
|
||||
* update to core 1.142.12
|
||||
|
||||
|
||||
## v1.46.13
|
||||
2024-08
|
||||
@@ -689,7 +882,7 @@
|
||||
|
||||
* fix sending status updates of private apps
|
||||
* show full messages: do not load remote content for requests automatically
|
||||
* using to core107.1
|
||||
* using core107.1
|
||||
|
||||
|
||||
## v1.34.12
|
||||
|
||||
+3
-3
@@ -34,10 +34,10 @@ ENV PATH ${PATH}:${ANDROID_SDK_ROOT}/cmdline-tools/bin
|
||||
# Install NDK manually. Other SDK parts are installed automatically by gradle.
|
||||
#
|
||||
# If you change the NDK version here, also change it in `flake.nix`.
|
||||
# NDK version r23c LTS aka 23.2.8568313
|
||||
RUN sdkmanager --sdk_root=${ANDROID_SDK_ROOT} 'ndk;23.2.8568313'
|
||||
# NDK version r27 LTS aka 27.0.11902837
|
||||
RUN sdkmanager --sdk_root=${ANDROID_SDK_ROOT} 'ndk;27.0.11902837'
|
||||
|
||||
ENV ANDROID_NDK_ROOT ${ANDROID_SDK_ROOT}/ndk/23.2.8568313
|
||||
ENV ANDROID_NDK_ROOT ${ANDROID_SDK_ROOT}/ndk/27.0.11902837
|
||||
ENV PATH ${PATH}:${ANDROID_NDK_ROOT}/toolchains/llvm/prebuilt/linux-x86_64/bin/
|
||||
|
||||
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
## ArcaneChat Android Client
|
||||
|
||||
A [Delta Chat](https://delta.chat/) client for Android.
|
||||
A [Delta Chat](https://delta.chat/) client for Android. Learn more at: https://arcanechat.me
|
||||
|
||||
[<img src="store/get-it-on-IzzyOnDroid.png"
|
||||
alt="Get it on IzzyOnDroid"
|
||||
height="48">](https://apt.izzysoft.de/fdroid/index/apk/chat.delta.lite)
|
||||
[<img src="store/get-it-on-apklis.png"
|
||||
alt="Disponible en Apklis"
|
||||
height="48">](https://www.apklis.cu/application/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)
|
||||
[<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-IzzyOnDroid.png" alt="Get it on IzzyOnDroid" height="48">](https://apt.izzysoft.de/fdroid/index/apk/chat.delta.lite)
|
||||
[<img src="store/get-it-on-apklis.png" alt="Disponible en Apklis" height="48">](https://www.apklis.cu/application/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)
|
||||
|
||||
|
||||
<img alt="Screenshot" src="fastlane/metadata/android/en-US/images/phoneScreenshots/1.png" width="298" /> <img alt="Screenshot" src="fastlane/metadata/android/en-US/images/phoneScreenshots/2.png" width="298" />
|
||||
|
||||
+23
-14
@@ -24,14 +24,18 @@ the "update-core-and-stuff-DATE" PR can be merged without review
|
||||
|
||||
the following steps are done in a PR called `prep-VERSION` (no leading "v"):
|
||||
|
||||
3. update `CHANGELOG.md`
|
||||
from <https://github.com/deltachat/deltachat-core-rust/blob/main/CHANGELOG.md>
|
||||
and <https://github.com/deltachat/deltachat-android/pulls?q=is%3Apr+is%3Aclosed+sort%3Aupdated-desc>.
|
||||
avoid technical terms, library versions etc. the changelog is for the end user.
|
||||
do not forget to update/mention used core version and release month.
|
||||
3. a) update `CHANGELOG.md`
|
||||
from <https://github.com/deltachat/deltachat-core-rust/blob/main/CHANGELOG.md>
|
||||
and <https://github.com/deltachat/deltachat-android/pulls?q=is%3Apr+is%3Aclosed+sort%3Aupdated-desc>.
|
||||
do not just copy and avoid technical terms.
|
||||
the changelog is for the end user and shall show impacts form that angle.
|
||||
b) update changelog date as `YYYY-MM`
|
||||
c) add used core version to end of changelog entry
|
||||
as `update to core 1.2.3` or `using core 1.2.3`
|
||||
|
||||
in case previous entries of the changelog refer to betas or to not officially released versions,
|
||||
the entries can be summarized.
|
||||
this makes it easier for the end user to follow changes by showing major changes atop
|
||||
this makes it easier for the end user to follow changes by showing major changes atop.
|
||||
|
||||
4. add a device message to `ConversationListActivity::onCreate()` or remove the old one.
|
||||
do not repeat the CHANGELOG here: write what really is the ux outcome
|
||||
@@ -44,7 +48,8 @@ the following steps are done in a PR called `prep-VERSION` (no leading "v"):
|
||||
6. build APKs:
|
||||
a) generate debug APK at "Build / Build Bundle(s)/APK / Build APK(s)"
|
||||
b) generate release APK at "Build / Generate Signed Bundle or APK",
|
||||
select "APK", add keys, flavor `gplayRelease`
|
||||
select "APK", add keys, flavor `gplayRelease`.
|
||||
this APK will go to the stores and is located at `gplay/release`
|
||||
|
||||
|
||||
## Push Test Releases
|
||||
@@ -75,16 +80,21 @@ only afterwards, push the APK to stores. **consider a blog post.**
|
||||
|
||||
on <https://play.google.com/apps/publish/>:
|
||||
|
||||
9. a) open "Delta Chat/Release/Production"
|
||||
then "Create new release" and upload APK from above
|
||||
9. a) open "Delta Chat / Test and release / Production"
|
||||
then "Create new release" and upload APK from above
|
||||
b) fill out "Release details/Release notes" (500 chars), add the line
|
||||
"These features will roll out over the coming days. Thanks for using Delta Chat!";
|
||||
release name should be default ("123 (1.2.3)")
|
||||
c) click "Next", set "Rollout Percentage" to 1% (later 2%, 5%, 10%, 20%, 50%, 100%),
|
||||
click "Save"
|
||||
c) click "Next", set "Rollout Percentage" to 50%, click "Save"
|
||||
d) Go to "Publishing Overview", "Managed publishing" is usually off;
|
||||
click "Send change for review", confirm
|
||||
|
||||
2 days later, change "Rollout Percentage" to 99%. Two more days later to 100%.
|
||||
Rollout is anyways slower in practise, however,
|
||||
only as long as we do not enter 100%, we can retract the version
|
||||
(Once we reach 100%, we have to submit a new version for approval.
|
||||
During these up to 4 days, sometimes longer, we cannot do anything on existing rollout)
|
||||
|
||||
|
||||
## Tag for F-Droid and create Github release
|
||||
|
||||
@@ -107,9 +117,8 @@ on <https://developer.amazon.com/dashboard>:
|
||||
12. a) for "Delta Chat", select "Add upcoming version" on the left
|
||||
b) at "Step 1 / Existing file(s)" hit "Replace", upload the APK from above
|
||||
c) on the "Step 1" page, add "Release notes" from CHANGELOG.md, hit "Next"
|
||||
d) on "Step 2" page: "Does your app collect or transfer user data to third parties?" -> No, then "Next"
|
||||
e) on "Step 3" page: "Next"
|
||||
f) on "Step 4" page: "Submit app"
|
||||
d) on "Step 2" and "Step 3" pages, hit "Next"
|
||||
e) on "Step 4" page: "Submit app"
|
||||
|
||||
|
||||
## Release on Huawei AppGallery
|
||||
|
||||
+45
-27
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
id 'com.android.application' version '8.1.4'
|
||||
id 'com.android.application' version '8.5.2'
|
||||
id 'com.google.gms.google-services' version '4.4.1'
|
||||
}
|
||||
|
||||
@@ -29,12 +29,12 @@ android {
|
||||
// > Task :stripFatDebugDebugSymbols
|
||||
// Unable to strip the following libraries, packaging them as they are: libanimation-decoder-gif.so, libnative-utils.so.
|
||||
// See <https://issuetracker.google.com/issues/237187538> for details.
|
||||
ndkVersion "23.2.8568313"
|
||||
ndkVersion "27.0.12077973"
|
||||
useLibrary 'org.apache.http.legacy'
|
||||
|
||||
defaultConfig {
|
||||
versionCode 30000688
|
||||
versionName "1.46.16"
|
||||
versionCode 30000710
|
||||
versionName "1.54.0"
|
||||
|
||||
applicationId "chat.delta.lite"
|
||||
multiDexEnabled true
|
||||
@@ -87,15 +87,45 @@ android {
|
||||
storeFile file(DC_DEBUG_STORE_FILE )
|
||||
}
|
||||
}
|
||||
release {
|
||||
releaseFdroid {
|
||||
// can be defined at `~/.gradle/gradle.properties` or at "Build/Generate signed APK"
|
||||
if(project.hasProperty("DC_RELEASE_STORE_FILE")) {
|
||||
storeFile file(DC_RELEASE_STORE_FILE)
|
||||
storePassword DC_RELEASE_STORE_PASSWORD
|
||||
keyAlias DC_RELEASE_KEY_ALIAS
|
||||
keyAlias DC_RELEASE_KEY_ALIAS_FDROID
|
||||
keyPassword DC_RELEASE_KEY_PASSWORD
|
||||
}
|
||||
}
|
||||
releaseApk {
|
||||
// can be defined at `~/.gradle/gradle.properties` or at "Build/Generate signed APK"
|
||||
if(project.hasProperty("DC_RELEASE_STORE_FILE")) {
|
||||
storeFile file(DC_RELEASE_STORE_FILE)
|
||||
storePassword DC_RELEASE_STORE_PASSWORD
|
||||
keyAlias DC_RELEASE_KEY_ALIAS_GPLAY
|
||||
keyPassword DC_RELEASE_KEY_PASSWORD
|
||||
}
|
||||
}
|
||||
releaseBundle {
|
||||
if(project.hasProperty("DC_BUNDLE_STORE_FILE")) {
|
||||
storeFile file(DC_BUNDLE_STORE_FILE)
|
||||
storePassword DC_BUNDLE_STORE_PASSWORD
|
||||
keyAlias DC_BUNDLE_KEY_ALIAS
|
||||
keyPassword DC_BUNDLE_STORE_PASSWORD
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
foss {
|
||||
dimension "none"
|
||||
buildConfigField "boolean", "USE_PLAY_SERVICES", "false"
|
||||
}
|
||||
gplay {
|
||||
dimension "none"
|
||||
apply plugin: "com.google.gms.google-services"
|
||||
buildConfigField "boolean", "USE_PLAY_SERVICES", "true"
|
||||
applicationId "com.github.arcanechat"
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -114,23 +144,12 @@ android {
|
||||
// nb: it is highly recommended to use the same settings in debug+release -
|
||||
// otherwise problems might be noticed delayed only
|
||||
minifyEnabled true
|
||||
signingConfig signingConfigs.release
|
||||
productFlavors.foss.signingConfig signingConfigs.releaseFdroid
|
||||
productFlavors.gplay.signingConfig signingConfigs.releaseApk
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
|
||||
productFlavors {
|
||||
foss {
|
||||
dimension "none"
|
||||
buildConfigField "boolean", "USE_PLAY_SERVICES", "false"
|
||||
}
|
||||
gplay {
|
||||
dimension "none"
|
||||
apply plugin: "com.google.gms.google-services"
|
||||
buildConfigField "boolean", "USE_PLAY_SERVICES", "true"
|
||||
}
|
||||
}
|
||||
|
||||
if(!project.hasProperty("ABI_FILTER")) {
|
||||
splits {
|
||||
abi {
|
||||
@@ -190,7 +209,7 @@ dependencies {
|
||||
implementation 'com.airbnb.android:lottie:4.2.2' // Lottie animations support.
|
||||
|
||||
implementation 'androidx.sharetarget:sharetarget:1.2.0'
|
||||
implementation 'androidx.webkit:webkit:1.11.0'
|
||||
implementation 'androidx.webkit:webkit:1.12.1'
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
||||
implementation 'com.google.android.material:material:1.12.0'
|
||||
@@ -206,11 +225,11 @@ dependencies {
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel:2.6.2'
|
||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
|
||||
implementation 'androidx.work:work-runtime:2.9.1'
|
||||
implementation 'androidx.emoji2:emoji2-emojipicker:1.4.0'
|
||||
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-ui:2.19.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
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
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.1' // used as JSON library
|
||||
@@ -218,14 +237,13 @@ dependencies {
|
||||
implementation "me.leolin:ShortcutBadger:1.1.16" // display messagecount on the home screen icon.
|
||||
implementation 'com.jpardogo.materialtabstrip:library:1.0.9' // used in the emoji selector for the tab selection.
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.1.3' // does the zooming on photos / media
|
||||
implementation 'com.github.penfeizhou.android.animation:glide-plugin:2.25.0' // APNG & animated webp support.
|
||||
implementation 'com.github.penfeizhou.android.animation:awebp:3.0.2' // animated webp support.
|
||||
implementation 'com.caverock:androidsvg-aar:1.4' // SVG support.
|
||||
implementation 'com.github.bumptech.glide:glide:4.12.0'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
|
||||
annotationProcessor 'androidx.annotation:annotation:1.8.2'
|
||||
annotationProcessor 'androidx.annotation:annotation:1.9.1'
|
||||
implementation 'com.makeramen:roundedimageview:2.1.0' // crops the avatars to circles
|
||||
implementation 'com.pnikosis:materialish-progress:1.5' // used only in the "Progress Wheel" in Share Activity.
|
||||
implementation 'com.soundcloud.android:android-crop:1.0.1@aar' // used for profile and group avatar selection in Android SDK<19
|
||||
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
|
||||
@@ -240,7 +258,7 @@ dependencies {
|
||||
// <https://github.com/cketti/SafeContentResolver>
|
||||
implementation 'de.cketti.safecontentresolver:safe-content-resolver-v14:1.0.0'
|
||||
|
||||
gplayImplementation('com.google.firebase:firebase-messaging:24.0.0') { // for PUSH notifications
|
||||
gplayImplementation('com.google.firebase:firebase-messaging:24.1.0') { // for PUSH notifications
|
||||
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'
|
||||
@@ -254,7 +272,7 @@ dependencies {
|
||||
testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1'
|
||||
testImplementation 'org.powermock:powermock-classloading-xstream:1.6.1'
|
||||
|
||||
androidTestImplementation 'androidx.test:runner:1.6.1'
|
||||
androidTestImplementation 'androidx.test:runner:1.6.2'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.6.1'
|
||||
androidTestImplementation 'androidx.test:rules:1.6.1'
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
ArcaneChat is a decentralized and secure messenger app that is
|
||||
completely compatible with the existing e-mail infrastructure.
|
||||
ArcaneChat is a decentralized and secure messenger app that is compatible with the existing e-mail infrastructure.
|
||||
|
||||
Some features at a glance:
|
||||
|
||||
@@ -13,28 +12,28 @@ Some features at a glance:
|
||||
|
||||
🔒 Audited end-to-end encryption safe against network and server attacks.
|
||||
|
||||
ArcaneChat is a Delta Chat client and was created with a focus on usability,
|
||||
good user experience, and saving data plan. Also the app usually experiments with
|
||||
new features that eventually might get added to the official Delta Chat client.
|
||||
ArcaneChat is a Delta Chat client and was created with a focus on usability, good user experience, and saving data plan. Also the app usually experiments with new features that eventually might get added to the official Delta Chat client.
|
||||
|
||||
<b>Main differences with official Delta Chat client:</b>
|
||||
|
||||
<ul>
|
||||
<li>Basic markdown support (bold, italic, strike, etc.)</li>
|
||||
<li>Support for some markdown styles in text messages (bold, italic, strike, etc.)</li>
|
||||
<li>Support for displaying Telegram's animated stickers (.tgs files)</li>
|
||||
<li>Support for SVG images previews</li>
|
||||
<li>Multiple color themes/skins</li>
|
||||
<li>It is possible to enable/disable accounts</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>Replies to your messages in muted groups trigger notifications</li>
|
||||
<li>Location streaming feature enabled by default and have extra option to share location for 12 hours</li>
|
||||
<li>Location streaming feature enabled by default and extra option to share location for 12 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>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>Account's display name is shown in the app's title bar instead of the name of the app</li>
|
||||
<li>Profile's display name is always shown in the app's title bar instead of the name of the app</li>
|
||||
<li>Your avatar is visible to other users in Mailing Lists</li>
|
||||
<li>Can be selected as app to open .xdc files</li>
|
||||
<li>For mini-apps developers: there are some differences in the WebXDC API, check https://github.com/ArcaneChat/android/#webxdc</li>
|
||||
<li>For mini-apps developers: there are some extra features in the WebXDC API, check https://github.com/ArcaneChat/android/#webxdc</li>
|
||||
<li>Better settings organization with additional "Privacy" section</li>
|
||||
</ul>
|
||||
|
||||
Generated
+26
-94
@@ -3,15 +3,15 @@
|
||||
"android": {
|
||||
"inputs": {
|
||||
"devshell": "devshell",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710633978,
|
||||
"narHash": "sha256-yemnwSvW7cdWtXGpivFA5jDO35rGPs6fqxlQ4l6ODXs=",
|
||||
"lastModified": 1733948466,
|
||||
"narHash": "sha256-o/uq/tU458Ykudi8Zk3sRga5iazkuSczt9wDOCUDOSU=",
|
||||
"owner": "tadfisher",
|
||||
"repo": "android-nixpkgs",
|
||||
"rev": "e91fb3d8517538e5ad9b422c9a4f604b56008a9e",
|
||||
"rev": "0bf99ffaea6a7c0948ae10cf2e40c2905e4e4d6b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -22,18 +22,17 @@
|
||||
},
|
||||
"devshell": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": [
|
||||
"android",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1708939976,
|
||||
"narHash": "sha256-O5+nFozxz2Vubpdl1YZtPrilcIXPcRAjqNdNE8oCRoA=",
|
||||
"lastModified": 1728330715,
|
||||
"narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=",
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"rev": "5ddecd67edbd568ebe0a55905273e56cc82aabe3",
|
||||
"rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -47,11 +46,11 @@
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1701680307,
|
||||
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -65,47 +64,11 @@
|
||||
"systems": "systems_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709126324,
|
||||
"narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=",
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "d465f4819400de7c8d874d50b982301f28a84605",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_3": {
|
||||
"inputs": {
|
||||
"systems": "systems_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils_4": {
|
||||
"inputs": {
|
||||
"systems": "systems_4"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1705309234,
|
||||
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -116,11 +79,11 @@
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1709237383,
|
||||
"narHash": "sha256-cy6ArO4k5qTx+l5o+0mL9f5fa86tYUX3ozE1S+Txlds=",
|
||||
"lastModified": 1733759999,
|
||||
"narHash": "sha256-463SNPWmz46iLzJKRzO3Q2b0Aurff3U1n0nYItxq7jU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "1536926ef5621b09bba54035ae2bb6d806d72ac8",
|
||||
"rev": "a73246e2eef4c6ed172979932bc80e1404ba2d56",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -132,11 +95,11 @@
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1710889954,
|
||||
"narHash": "sha256-Pr6F5Pmd7JnNEMHHmspZ0qVqIBVxyZ13ik1pJtm2QXk=",
|
||||
"lastModified": 1733749988,
|
||||
"narHash": "sha256-+5qdtgXceqhK5ZR1YbP1fAUsweBIrhL38726oIEAtDs=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "7872526e9c5332274ea5932a0c3270d6e4724f3b",
|
||||
"rev": "bc27f0fde01ce4e1bfec1ab122d72b7380278e68",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -148,11 +111,11 @@
|
||||
},
|
||||
"nixpkgs_3": {
|
||||
"locked": {
|
||||
"lastModified": 1706487304,
|
||||
"narHash": "sha256-LE8lVX28MV2jWJsidW13D2qrHU/RUUONendL2Q/WlJg=",
|
||||
"lastModified": 1728538411,
|
||||
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "90f456026d284c22b3e3497be980b2e47d0b28ac",
|
||||
"rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -165,22 +128,21 @@
|
||||
"root": {
|
||||
"inputs": {
|
||||
"android": "android",
|
||||
"flake-utils": "flake-utils_3",
|
||||
"flake-utils": "flake-utils_2",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"rust-overlay": "rust-overlay"
|
||||
}
|
||||
},
|
||||
"rust-overlay": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils_4",
|
||||
"nixpkgs": "nixpkgs_3"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1711073443,
|
||||
"narHash": "sha256-PpNb4xq7U5Q/DdX40qe7CijUsqhVVM3VZrhN0+c6Lcw=",
|
||||
"lastModified": 1733970833,
|
||||
"narHash": "sha256-sPEKtSaZk2CtfF9cdhtbY93S6qGq+d2PKI1fcoDfDaI=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "eec55ba9fcde6be4c63942827247e42afef7fafe",
|
||||
"rev": "f7f4c59ccdf1bec3f1547d27398e9589aa94e3e8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -218,36 +180,6 @@
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_3": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems_4": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
|
||||
@@ -15,12 +15,11 @@
|
||||
pkgs = import nixpkgs { inherit system overlays; };
|
||||
android-sdk = android.sdk.${system} (sdkPkgs:
|
||||
with sdkPkgs; [
|
||||
build-tools-33-0-1
|
||||
build-tools-34-0-0
|
||||
cmdline-tools-latest
|
||||
ndk-bundle
|
||||
platform-tools
|
||||
platforms-android-34
|
||||
ndk-23-2-8568313
|
||||
ndk-27-0-11902837
|
||||
]);
|
||||
rust-version = pkgs.lib.removeSuffix "\n"
|
||||
(builtins.readFile ./scripts/rust-toolchain);
|
||||
@@ -28,7 +27,7 @@
|
||||
devShells.default = pkgs.mkShell {
|
||||
ANDROID_SDK_ROOT = "${android-sdk}/share/android-sdk";
|
||||
ANDROID_NDK_ROOT =
|
||||
"${android-sdk}/share/android-sdk/ndk/23.2.8568313";
|
||||
"${android-sdk}/share/android-sdk/ndk/27.0.11902837";
|
||||
buildInputs = [
|
||||
android-sdk
|
||||
pkgs.openjdk17
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:922391085500:android:6f54e2c4e49405673e2bb9",
|
||||
"android_client_info": {
|
||||
"package_name": "chat.delta.lite.beta"
|
||||
"package_name": "com.github.arcanechat.beta"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
@@ -47,7 +47,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:922391085500:android:aff82fbc40c8172e3e2bb9",
|
||||
"android_client_info": {
|
||||
"package_name": "chat.delta.lite"
|
||||
"package_name": "com.github.arcanechat"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
@@ -66,7 +66,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:922391085500:android:92b4cf12669cc2083e2bb9",
|
||||
"android_client_info": {
|
||||
"package_name": "com.github.arcanechat"
|
||||
"package_name": "chat.delta.lite"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
@@ -85,7 +85,7 @@
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:922391085500:android:228a205b8aa2bacc3e2bb9",
|
||||
"android_client_info": {
|
||||
"package_name": "com.github.arcanechat.beta"
|
||||
"package_name": "chat.delta.lite.beta"
|
||||
}
|
||||
},
|
||||
"oauth_client": [],
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
|
||||
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
+69
-78
@@ -7,57 +7,6 @@
|
||||
#include "deltachat-core-rust/deltachat-ffi/deltachat.h"
|
||||
|
||||
|
||||
#if __ANDROID_API__ == 16
|
||||
unsigned long getauxval(unsigned long type) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
|
||||
int flags)
|
||||
{
|
||||
if (flags != 0) {
|
||||
// Not supported by the fallback.
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vlen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t n = sendmsg(sockfd, &msgvec->msg_hdr, flags);
|
||||
if (n == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
(*msgvec).msg_len = n;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int recvmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,
|
||||
int flags, struct timespec *timeout)
|
||||
{
|
||||
if (flags != 0) {
|
||||
// Not supported by the fallback.
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vlen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n = recvmsg(sockfd, &msgvec->msg_hdr, flags);
|
||||
if (n == -1) {
|
||||
return -1;
|
||||
}
|
||||
(*msgvec).msg_len = n;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static dc_msg_t* get_dc_msg(JNIEnv *env, jobject obj);
|
||||
|
||||
|
||||
@@ -276,6 +225,12 @@ JNIEXPORT void Java_com_b44t_messenger_DcAccounts_setPushDeviceToken(JNIEnv *env
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcAccounts_backgroundFetch(JNIEnv *env, jobject obj, jint timeout_seconds)
|
||||
{
|
||||
return dc_accounts_background_fetch(get_dc_accounts(env, obj), timeout_seconds) != 0;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcAccounts_addAccount(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return dc_accounts_add_account(get_dc_accounts(env, obj));
|
||||
@@ -736,6 +691,13 @@ JNIEXPORT void Java_com_b44t_messenger_DcContext_forwardMsgs(JNIEnv *env, jobjec
|
||||
free(msg_ids_ptr);
|
||||
}
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcContext_saveMsgs(JNIEnv *env, jobject obj, jintArray msg_ids)
|
||||
{
|
||||
int msg_ids_cnt = 0;
|
||||
uint32_t* msg_ids_ptr = jintArray2uint32Pointer(env, msg_ids, &msg_ids_cnt);
|
||||
dc_save_msgs(get_dc_context(env, obj), msg_ids_ptr, msg_ids_cnt);
|
||||
free(msg_ids_ptr);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_resendMsgs(JNIEnv *env, jobject obj, jintArray msg_ids)
|
||||
{
|
||||
@@ -747,12 +709,6 @@ JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_resendMsgs(JNIEnv *env, job
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcContext_prepareMsg(JNIEnv *env, jobject obj, jint chat_id, jobject msg)
|
||||
{
|
||||
return dc_prepare_msg(get_dc_context(env, obj), chat_id, get_dc_msg(env, msg));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendMsg(JNIEnv *env, jobject obj, jint chat_id, jobject msg)
|
||||
{
|
||||
return dc_send_msg(get_dc_context(env, obj), chat_id, get_dc_msg(env, msg));
|
||||
@@ -774,12 +730,10 @@ JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendVideochatInvitation(JNIEnv
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_sendWebxdcStatusUpdate(JNIEnv *env, jobject obj, jint msg_id, jstring payload, jstring descr)
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_sendWebxdcStatusUpdate(JNIEnv *env, jobject obj, jint msg_id, jstring payload)
|
||||
{
|
||||
CHAR_REF(payload);
|
||||
CHAR_REF(descr);
|
||||
jboolean ret = dc_send_webxdc_status_update(get_dc_context(env, obj), msg_id, payloadPtr, descrPtr) != 0;
|
||||
CHAR_UNREF(descr);
|
||||
jboolean ret = dc_send_webxdc_status_update(get_dc_context(env, obj), msg_id, payloadPtr, NULL) != 0;
|
||||
CHAR_UNREF(payload);
|
||||
return ret;
|
||||
}
|
||||
@@ -848,7 +802,7 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcContext_getConfig(JNIEnv *env, jobje
|
||||
}
|
||||
dc_str_unref(temp);
|
||||
CHAR_UNREF(key);
|
||||
return ret; /* returns NULL only if key is unset and "def" is NULL */
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -878,6 +832,16 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcContext_getSecurejoinQrSvg(JNIEnv *e
|
||||
return ret;
|
||||
}
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcContext_createQrSvg(JNIEnv *env, jobject obj, jstring payload)
|
||||
{
|
||||
CHAR_REF(payload);
|
||||
char* temp = dc_create_qr_svg(payloadPtr);
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
dc_str_unref(temp);
|
||||
CHAR_UNREF(payload);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcContext_joinSecurejoin(JNIEnv *env, jobject obj, jstring qr)
|
||||
{
|
||||
CHAR_REF(qr);
|
||||
@@ -1325,12 +1289,6 @@ JNIEXPORT jintArray Java_com_b44t_messenger_DcContext_getChatMedia(JNIEnv *env,
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcContext_getNextMedia(JNIEnv *env, jobject obj, jint msg_id, jint dir, jint type1, jint type2, jint type3)
|
||||
{
|
||||
return dc_get_next_media(get_dc_context(env, obj), msg_id, dir, type1, type2, type3);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jintArray Java_com_b44t_messenger_DcContext_getChatMsgs(JNIEnv *env, jobject obj, jint chat_id, jint flags, jint marker1before)
|
||||
{
|
||||
dc_array_t* ca = dc_get_chat_msgs(get_dc_context(env, obj), chat_id, flags, marker1before);
|
||||
@@ -1413,12 +1371,6 @@ JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getId(JNIEnv *env, jobject obj)
|
||||
return dc_msg_get_id(get_dc_msg(env, obj));
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isOutgoing(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jboolean)(dc_msg_is_outgoing(get_dc_msg(env, obj))!=0);
|
||||
}
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getSenderColor(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return dc_msg_get_sender_color(get_dc_msg(env, obj));
|
||||
@@ -1616,15 +1568,18 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getWebxdcInfoJson(JNIEnv *env, j
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isForwarded(JNIEnv *env, jobject obj)
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getWebxdcHref(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return dc_msg_is_forwarded(get_dc_msg(env, obj))!=0;
|
||||
char* temp = dc_msg_get_webxdc_href(get_dc_msg(env, obj));
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
dc_str_unref(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isIncreation(JNIEnv *env, jobject obj)
|
||||
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isForwarded(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return dc_msg_is_increation(get_dc_msg(env, obj))!=0;
|
||||
return dc_msg_is_forwarded(get_dc_msg(env, obj))!=0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1704,6 +1659,33 @@ JNIEXPORT void Java_com_b44t_messenger_DcMsg_setFile(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));
|
||||
jstring ret = JSTRING_NEW(temp);
|
||||
dc_str_unref(temp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setFileAndDeduplicate(JNIEnv *env, jobject obj, jstring file, jstring name, jstring filemime)
|
||||
{
|
||||
CHAR_REF(file);
|
||||
CHAR_REF(name);
|
||||
CHAR_REF(filemime);
|
||||
dc_msg_set_file_and_deduplicate(get_dc_msg(env, obj), filePtr, namePtr, filemimePtr);
|
||||
CHAR_UNREF(filemime);
|
||||
CHAR_UNREF(name);
|
||||
CHAR_UNREF(file);
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setDimension(JNIEnv *env, jobject obj, int width, int height)
|
||||
{
|
||||
dc_msg_set_dimension(get_dc_msg(env, obj), width, height);
|
||||
@@ -1748,6 +1730,15 @@ JNIEXPORT jlong Java_com_b44t_messenger_DcMsg_getParentCPtr(JNIEnv *env, jobject
|
||||
return (jlong)dc_msg_get_parent(get_dc_msg(env, obj));
|
||||
}
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getOriginalMsgId(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jint)dc_msg_get_original_msg_id(get_dc_msg(env, obj));
|
||||
}
|
||||
|
||||
JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getSavedMsgId(JNIEnv *env, jobject obj)
|
||||
{
|
||||
return (jint)dc_msg_get_saved_msg_id(get_dc_msg(env, obj));
|
||||
}
|
||||
|
||||
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getError(JNIEnv *env, jobject obj)
|
||||
{
|
||||
|
||||
+1
-1
Submodule jni/deltachat-core-rust updated: 5221e6af3f...919337c95e
@@ -0,0 +1,7 @@
|
||||
- nuovo inserimento: puoi creare un nuovo profilo con un tocco su "Crea Nuovo Profilo" - oppure utilizzare un accesso esistente o la configurazione del secondo dispositivo come al solito
|
||||
i contatti possono essere allegati come "Schede" in "Allega/Contatto"; quando il destinatario tocca le carte, è possibile stabilire la crittografia end-to-end garantita
|
||||
- aggiungi contatti manualmente in "Nuova Chat / Nuovo Contatto / Aggiungi Contatto Manualmente"
|
||||
- invia qualsiasi emoji come reazione
|
||||
- mostrare le reazioni nei riepiloghi
|
||||
- blocca/archivia/ecc. le chat direttamente dai risultati di ricerca
|
||||
- Risolti bug e altro ancora
|
||||
@@ -0,0 +1,4 @@
|
||||
- aggiungi un'opzione per contrassegnare tutte le chat selezionate come "Lette" (tocca a lungo una chat per avviare la modalità di selezione)
|
||||
- i nuovi profili chatmail per dispositivo singolo hanno come impostazione predefinita "Elimina Messaggi Dopo il Download"
|
||||
- quando si utilizza un profilo chatmail su più dispositivi, la cancellazione viene modificata in "Automatica" (la strategia di cancellazione dipende quindi dal server)
|
||||
- Risolti bug e altro ancora
|
||||
@@ -1 +1 @@
|
||||
../deltachat-pages/tools/create-local-help.py ../deltachat-pages/_site src/main/assets/help
|
||||
../deltachat-pages/tools/create-local-help.py ../deltachat-pages/result src/main/assets/help
|
||||
|
||||
+12
-10
@@ -51,8 +51,7 @@ if test -z "$ANDROID_NDK_ROOT"; then
|
||||
fi
|
||||
|
||||
# for reproducible build:
|
||||
ROOT_DIR="$(realpath $(dirname $(dirname "$0")))"
|
||||
export RUSTFLAGS="-C link-args=-Wl,--build-id=none --remap-path-prefix=$HOME/.cargo= --remap-path-prefix=$ROOT_DIR="
|
||||
export RUSTFLAGS="-C link-args=-Wl,--build-id=none --remap-path-prefix=$HOME/.cargo= --remap-path-prefix=$(realpath $(dirname $(dirname "$0")))="
|
||||
export SOURCE_DATE_EPOCH=1
|
||||
export CARGO_TARGET_DIR=/tmp/arcanechat-build
|
||||
# always use the same path to NDK:
|
||||
@@ -76,9 +75,9 @@ if test -z "$NDK_HOST_TAG"; then
|
||||
fi
|
||||
|
||||
TOOLCHAIN="$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/$NDK_HOST_TAG"
|
||||
export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER="$TOOLCHAIN/bin/armv7a-linux-androideabi16-clang"
|
||||
export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER="$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang"
|
||||
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/aarch64-linux-android21-clang"
|
||||
export CARGO_TARGET_I686_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/i686-linux-android16-clang"
|
||||
export CARGO_TARGET_I686_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/i686-linux-android21-clang"
|
||||
export CARGO_TARGET_X86_64_LINUX_ANDROID_LINKER="$TOOLCHAIN/bin/x86_64-linux-android21-clang"
|
||||
|
||||
export RUSTUP_TOOLCHAIN=$(cat "$(dirname "$0")/rust-toolchain")
|
||||
@@ -124,10 +123,10 @@ unset CPATH
|
||||
|
||||
if test -z $1 || test $1 = armeabi-v7a; then
|
||||
echo "-- cross compiling to armv7-linux-androideabi (arm) --"
|
||||
TARGET_CC="$TOOLCHAIN/bin/armv7a-linux-androideabi16-clang" \
|
||||
TARGET_CC="$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang" \
|
||||
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
|
||||
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
|
||||
cargo build $RELEASEFLAG --target armv7-linux-androideabi -p deltachat_ffi --features jsonrpc
|
||||
cargo build $RELEASEFLAG --target armv7-linux-androideabi -p deltachat_ffi
|
||||
cp $CARGO_TARGET_DIR/armv7-linux-androideabi/$RELEASE/libdeltachat.a $jnidir/armeabi-v7a
|
||||
fi
|
||||
|
||||
@@ -136,16 +135,16 @@ if test -z $1 || test $1 = arm64-v8a; then
|
||||
TARGET_CC="$TOOLCHAIN/bin/aarch64-linux-android21-clang" \
|
||||
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
|
||||
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
|
||||
cargo build $RELEASEFLAG --target aarch64-linux-android -p deltachat_ffi --features jsonrpc
|
||||
cargo build $RELEASEFLAG --target aarch64-linux-android -p deltachat_ffi
|
||||
cp $CARGO_TARGET_DIR/aarch64-linux-android/$RELEASE/libdeltachat.a $jnidir/arm64-v8a
|
||||
fi
|
||||
|
||||
if test -z $1 || test $1 = x86; then
|
||||
echo "-- cross compiling to i686-linux-android (x86) --"
|
||||
TARGET_CC="$TOOLCHAIN/bin/i686-linux-android16-clang" \
|
||||
TARGET_CC="$TOOLCHAIN/bin/i686-linux-android21-clang" \
|
||||
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
|
||||
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
|
||||
cargo build $RELEASEFLAG --target i686-linux-android -p deltachat_ffi --features jsonrpc
|
||||
cargo build $RELEASEFLAG --target i686-linux-android -p deltachat_ffi
|
||||
cp $CARGO_TARGET_DIR/i686-linux-android/$RELEASE/libdeltachat.a $jnidir/x86
|
||||
fi
|
||||
|
||||
@@ -154,7 +153,7 @@ fi
|
||||
TARGET_CC="$TOOLCHAIN/bin/x86_64-linux-android21-clang" \
|
||||
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
|
||||
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
|
||||
cargo build $RELEASEFLAG --target x86_64-linux-android -p deltachat_ffi --features jsonrpc
|
||||
cargo build $RELEASEFLAG --target x86_64-linux-android -p deltachat_ffi
|
||||
cp $CARGO_TARGET_DIR/x86_64-linux-android/$RELEASE/libdeltachat.a $jnidir/x86_64
|
||||
fi
|
||||
|
||||
@@ -175,4 +174,7 @@ else
|
||||
rm -f ndkArch # Remove ndkArch, ignore if it doesn't exist
|
||||
fi
|
||||
|
||||
"$(dirname "$0")/rebrand.sh"
|
||||
|
||||
|
||||
echo "ending time: `date`"
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
# replace Delta Chat with ArcaneChat
|
||||
find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/get.delta.chat/github.com\/ArcaneChat/g'
|
||||
find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/Delta Chat/ArcaneChat/g'
|
||||
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/ArcaneChat/g'
|
||||
@@ -1 +1 @@
|
||||
1.77.0
|
||||
1.83.0
|
||||
|
||||
Executable
+7
@@ -0,0 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/github.com\/ArcaneChat/get.delta.chat/g'
|
||||
find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/ArcaneChat/Delta Chat/g'
|
||||
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/Delta Chat/g'
|
||||
sed -i 's/>Delta Chat</>ArcaneChat</g' ./src/main/res/values/strings.xml
|
||||
@@ -1,3 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e # stop on all errors
|
||||
|
||||
git submodule update --init --recursive
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
VERSION=$1
|
||||
|
||||
@@ -29,7 +30,6 @@ echo ""
|
||||
echo "and now: here is Delta Chat $VERSION - choose your flavour and mind your backups:"
|
||||
echo "- 🍋 https://download.delta.chat/android/beta/deltachat-gplay-release-$VERSION.apk (google play candidate, overwrites existing installs, should keep data)"
|
||||
echo "- 🍉 https://download.delta.chat/android/beta/deltachat-foss-debug-$VERSION.apk (f-droid candidate, can be installed beside google play)"
|
||||
echo "- 🍏 https://testflight.apple.com/join/uEMc1NxS (ios, update to $VERSION may take a day or so)"
|
||||
echo ""
|
||||
echo "what to test: PLEASE_FILL_OUT"
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
VERSION=$1
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ public class SharingTest {
|
||||
}
|
||||
}
|
||||
Uri uri = Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".attachments/" + Uri.encode(pngImage));
|
||||
DcHelper.sharedFiles.put("/" + pngImage, 1);
|
||||
DcHelper.sharedFiles.put(pngImage, "image/png");
|
||||
|
||||
Intent i = new Intent(Intent.ACTION_SEND);
|
||||
i.setType("image/png");
|
||||
|
||||
@@ -17,7 +17,7 @@ import com.google.firebase.messaging.RemoteMessage;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.BuildConfig;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.service.FetchForegroundService;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class FcmReceiveService extends FirebaseMessagingService {
|
||||
@@ -28,11 +28,6 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
||||
private static volatile String prefixedToken;
|
||||
|
||||
public static void register(Context context) {
|
||||
if (Build.VERSION.SDK_INT < 19) {
|
||||
Log.w(TAG, "FCM not available on SDK < 19");
|
||||
triedRegistering = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (FcmReceiveService.prefixedToken != null) {
|
||||
Log.i(TAG, "FCM already registered");
|
||||
@@ -92,18 +87,17 @@ public class FcmReceiveService extends FirebaseMessagingService {
|
||||
return prefixedToken;
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
@Override
|
||||
public void onMessageReceived(@NonNull RemoteMessage remoteMessage) {
|
||||
Log.i(TAG, "FCM push notification received");
|
||||
// the app is running (again) now and fetching and notifications should be processed as usual.
|
||||
// to support accounts that do not send PUSH notifications and for simplicity,
|
||||
// we just let the app run as long as possible.
|
||||
FetchForegroundService.start(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeletedMessages() {
|
||||
Log.i(TAG, "FCM push notifications dropped");
|
||||
// nothing special to do as we're running now and notifications should be processed as usual.
|
||||
FetchForegroundService.start(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
<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.ACCESS_BACKGROUND_LOCATION"/>
|
||||
<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" />
|
||||
@@ -66,6 +65,10 @@
|
||||
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"
|
||||
android:value="true" />
|
||||
|
||||
<activity android:name=".ShareActivity"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
android:excludeFromRecents="true"
|
||||
@@ -262,6 +265,26 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<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"/>
|
||||
<!-- 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" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
|
||||
<activity android:name=".LogViewActivity"
|
||||
android:label="@string/pref_log_header"
|
||||
android:windowSoftInputMode="stateHidden"
|
||||
@@ -305,8 +328,6 @@
|
||||
android:theme="@style/TextSecure.ScribbleTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
|
||||
|
||||
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
|
||||
|
||||
<activity android:name=".InstantOnboardingActivity"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:windowSoftInputMode="stateHidden|adjustResize"
|
||||
@@ -365,6 +386,11 @@
|
||||
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"
|
||||
android:theme="@style/TextSecure.LightTheme"
|
||||
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
|
||||
@@ -388,6 +414,10 @@
|
||||
android:name=".service.GenericForegroundService"
|
||||
android:foregroundServiceType="dataSync" />
|
||||
|
||||
<service
|
||||
android:name=".service.FetchForegroundService"
|
||||
android:foregroundServiceType="dataSync" />
|
||||
|
||||
<service
|
||||
android:name=".service.IPCAddAccountsService"
|
||||
android:foregroundServiceType="dataSync"
|
||||
|
||||
+277
-197
File diff suppressed because it is too large
Load Diff
+260
-181
File diff suppressed because it is too large
Load Diff
+277
-197
File diff suppressed because it is too large
Load Diff
+284
-202
File diff suppressed because it is too large
Load Diff
+307
-222
File diff suppressed because it is too large
Load Diff
+277
-197
File diff suppressed because it is too large
Load Diff
+282
-203
File diff suppressed because it is too large
Load Diff
+274
-194
File diff suppressed because it is too large
Load Diff
+227
-169
@@ -1,14 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html><head><meta charset="UTF-8" /><meta name="viewport" content="initial-scale=1.0" /><link rel="stylesheet" href="../help.css" /></head><body><ul id="top">
|
||||
<li><a href="#czym-jest-delta-chat">Czym jest ArcaneChat?</a>
|
||||
<li><a href="#czym-jest-delta-chat">Czym jest Delta Chat?</a>
|
||||
<ul>
|
||||
<li><a href="#jak-mogę-znaleźć-ludzi-z-którymi-mogę-czatować">Jak mogę znaleźć ludzi, z którymi mogę czatować?</a></li>
|
||||
<li><a href="#jakie-są-zalety-delta-chat-w-porównaniu-z-innymi-komunikatorami">Jakie są zalety ArcaneChat w porównaniu z innymi komunikatorami?</a></li>
|
||||
<li><a href="#jakie-są-zalety-delta-chat-w-porównaniu-z-innymi-komunikatorami">Jakie są zalety Delta Chat w porównaniu z innymi komunikatorami?</a></li>
|
||||
<li><a href="#co-zrobić-jeśli-oczekuję-wiadomości-od-osoby-do-której-nie-pisałem-w-przeszłości">Co zrobić, jeśli oczekuję wiadomości od osoby, do której nie pisałem w przeszłości?</a></li>
|
||||
<li><a href="#czy-delta-chat-obsługuje-obrazy-filmy-i-inne-załączniki">Czy ArcaneChat obsługuje obrazy, filmy i inne załączniki?</a></li>
|
||||
<li><a href="#czy-delta-chat-obsługuje-obrazy-filmy-i-inne-załączniki">Czy Delta Chat obsługuje obrazy, filmy i inne załączniki?</a></li>
|
||||
<li><a href="#multiple-accounts">Czym są profile? Jak mogę przełączać się między nimi?</a></li>
|
||||
<li><a href="#kto-widzi-moje-zdjęcie-profilowe">Kto widzi moje zdjęcie profilowe?</a></li>
|
||||
<li><a href="#signature">Czy w ArcaneChat mogę ustawić Biografię/Podpis/Status/Motto?</a></li>
|
||||
<li><a href="#signature">Czy w Delta Chat mogę ustawić Biografię/Podpis/Status/Motto?</a></li>
|
||||
<li><a href="#co-oznacza-przypinanie-wyciszanie-i-archiwizowanie">Co oznacza przypinanie, wyciszanie i archiwizowanie?</a></li>
|
||||
<li><a href="#co-oznacza-zielona-kropka">Co oznacza zielona kropka?</a></li>
|
||||
<li><a href="#ephemeralmsgs">Jak działają znikające wiadomości?</a></li>
|
||||
@@ -30,8 +30,8 @@
|
||||
<li><a href="#co-to-są-powiadomienia-push-jak-mogę-uzyskać-natychmiastowe-dostarczenie-wiadomości">Co to są powiadomienia push? Jak mogę uzyskać natychmiastowe dostarczenie wiadomości?</a></li>
|
||||
<li><a href="#czy-powiadomienia-push-są-włączone-na-urządzeniach-z-ios-czy-istnieje-alternatywa">Czy powiadomienia push są włączone na urządzeniach z iOS? Czy istnieje alternatywa?</a></li>
|
||||
<li><a href="#android-push">Czy powiadomienia Push są włączone/potrzebne na urządzeniach z Androidem?</a></li>
|
||||
<li><a href="#privacy-notifications">Jak prywatne są powiadomienia push na ArcaneChat?</a></li>
|
||||
<li><a href="#dlaczego-delta-chat-integruje-się-ze-scentralizowanymi-zastrzeżonymi-usługami-push-applegoogle">Dlaczego ArcaneChat integruje się ze scentralizowanymi, zastrzeżonymi usługami push Apple/Google?</a></li>
|
||||
<li><a href="#privacy-notifications">Jak prywatne są powiadomienia push na Delta Chat?</a></li>
|
||||
<li><a href="#dlaczego-delta-chat-integruje-się-ze-scentralizowanymi-zastrzeżonymi-usługami-push-applegoogle">Dlaczego Delta Chat integruje się ze scentralizowanymi, zastrzeżonymi usługami push Apple/Google?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#szyfrowanie-i-bezpieczeństwo">Szyfrowanie i bezpieczeństwo</a>
|
||||
@@ -44,28 +44,28 @@
|
||||
<li><a href="#czy-załączniki-zdjęcia-pliki-pliki-audio-itp-są-szyfrowane-metodą-end-to-end">Czy załączniki (zdjęcia, pliki, pliki audio itp.) są szyfrowane metodą end-to-end?</a></li>
|
||||
<li><a href="#openpgp-secure">Czy OpenPGP jest bezpieczny?</a></li>
|
||||
<li><a href="#openpgp-alternatives">Czy rozważałeś użycie alternatyw dla OpenPGP do szyfrowania typu end-to-end?</a></li>
|
||||
<li><a href="#czy-delta-chat-jest-podatny-na-efail">Czy ArcaneChat jest podatny na EFAIL?</a></li>
|
||||
<li><a href="#czy-delta-chat-jest-podatny-na-efail">Czy Delta Chat jest podatny na EFAIL?</a></li>
|
||||
<li><a href="#tls">Czy wiadomość jest udostępniana w postaci zwykłego tekstu, jeśli szyfrowanie end-to-end nie jest dostępne?</a></li>
|
||||
<li><a href="#message-metadata">W jaki sposób ArcaneChat chroni metadane w wiadomościach?</a></li>
|
||||
<li><a href="#message-metadata">W jaki sposób Delta Chat chroni metadane w wiadomościach?</a></li>
|
||||
<li><a href="#device-seizure">Jak chronić metadane i kontakty w przypadku przejęcia urządzenia?</a></li>
|
||||
<li><a href="#jak-mogę-sprawdzić-informacje-o-szyfrowaniu">Jak mogę sprawdzić informacje o szyfrowaniu?</a></li>
|
||||
<li><a href="#jak-mogę-sprawdzić-stan-szyfrowania-wiadomości">Jak mogę sprawdzić stan szyfrowania wiadomości?</a></li>
|
||||
<li><a href="#dlaczego-widzę-niezaszyfrowane-wiadomości">Dlaczego widzę niezaszyfrowane wiadomości?</a></li>
|
||||
<li><a href="#jak-mogę-uzyskać-zaszyfrowany-ened-to-end-czat-z-kontaktem-delta-chat-który-czasami-korzysta-z-poczty-internetowej-lub-innej-aplikacji-e-mail-bez-autocrypt">Jak mogę uzyskać zaszyfrowany ened-to-end czat z kontaktem ArcaneChat, który czasami korzysta z poczty internetowej lub innej aplikacji e-mail bez Autocrypt?</a></li>
|
||||
<li><a href="#jak-mogę-uzyskać-zaszyfrowany-ened-to-end-czat-z-kontaktem-delta-chat-który-czasami-korzysta-z-poczty-internetowej-lub-innej-aplikacji-e-mail-bez-autocrypt">Jak mogę uzyskać zaszyfrowany ened-to-end czat z kontaktem Delta Chat, który czasami korzysta z poczty internetowej lub innej aplikacji e-mail bez Autocrypt?</a></li>
|
||||
<li><a href="#jak-mogę-zapewnić-kompleksowe-szyfrowanie-i-usuwanie-wiadomości">Jak mogę zapewnić kompleksowe szyfrowanie i usuwanie wiadomości?</a></li>
|
||||
<li><a href="#pfs">Czy ArcaneChat obsługuje funkcję Perfect Forward Secrecy?</a></li>
|
||||
<li><a href="#czy-szyfrowanie-end-to-end-delta-chat-jest-tak-samo-bezpieczne-jak-signal">Czy szyfrowanie end-to-end ArcaneChat jest tak samo bezpieczne jak Signal?</a></li>
|
||||
<li><a href="#czy-mogę-ponownie-wykorzystać-mój-istniejący-klucz-prywatny">Czy mogę ponownie wykorzystać mój istniejący klucz prywatny?</a></li>
|
||||
<li><a href="#nie-mogę-zaimportować-istniejącego-klucza-pgp-do-delta-chat">Nie mogę zaimportować istniejącego klucza PGP do ArcaneChat.</a></li>
|
||||
<li><a href="#security-audits">Czy ArcaneChat był niezależnie kontrolowany pod kątem luk w zabezpieczeniach?</a></li>
|
||||
<li><a href="#pfs">Czy Delta Chat obsługuje funkcję Perfect Forward Secrecy?</a></li>
|
||||
<li><a href="#czy-szyfrowanie-end-to-end-delta-chat-jest-tak-samo-bezpieczne-jak-signal">Czy szyfrowanie end-to-end Delta Chat jest tak samo bezpieczne jak Signal?</a></li>
|
||||
<li><a href="#importkey">Czy mogę ponownie wykorzystać mój istniejący klucz prywatny?</a></li>
|
||||
<li><a href="#nie-mogę-zaimportować-istniejącego-klucza-pgp-do-delta-chat">Nie mogę zaimportować istniejącego klucza PGP do Delta Chat.</a></li>
|
||||
<li><a href="#security-audits">Czy Delta Chat był niezależnie kontrolowany pod kątem luk w zabezpieczeniach?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#multiclient">Multi-klient</a>
|
||||
<ul>
|
||||
<li><a href="#czy-mogę-korzystać-z-delta-chat-na-wielu-urządzeniach-w-tym-samym-czasie">Czy mogę korzystać z ArcaneChat na wielu urządzeniach w tym samym czasie?</a></li>
|
||||
<li><a href="#czy-mogę-korzystać-z-delta-chat-na-wielu-urządzeniach-w-tym-samym-czasie">Czy mogę korzystać z Delta Chat na wielu urządzeniach w tym samym czasie?</a></li>
|
||||
<li><a href="#rozwiązywanie-problemów">Rozwiązywanie problemów</a></li>
|
||||
<li><a href="#backup">Ręczny transfer</a></li>
|
||||
<li><a href="#czy-są-jakieś-plany-wprowadzenia-klienta-web-delta-chat">Czy są jakieś plany wprowadzenia klienta Web ArcaneChat?</a></li>
|
||||
<li><a href="#czy-są-jakieś-plany-wprowadzenia-klienta-web-delta-chat">Czy są jakieś plany wprowadzenia klienta Web Delta Chat?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#webxdc">Aplikacje webxdc</a>
|
||||
@@ -77,7 +77,7 @@
|
||||
</li>
|
||||
<li><a href="#funkcje-eksperymentalne">Funkcje eksperymentalne</a>
|
||||
<ul>
|
||||
<li><a href="#jak-mogę-korzystać-z-połączeń-audiowideo-z-delta-chat">Jak mogę korzystać z połączeń audio/wideo z ArcaneChat?</a></li>
|
||||
<li><a href="#jak-mogę-korzystać-z-połączeń-audiowideo-z-delta-chat">Jak mogę korzystać z połączeń audio/wideo z Delta Chat?</a></li>
|
||||
<li><a href="#co-to-są-listy-rozgłoszeniowe-i-jak-mogę-ich-używać">Co to są Listy rozgłoszeniowe i jak mogę ich używać?</a></li>
|
||||
<li><a href="#jak-mogę-udostępnić-swoją-lokalizację-moim-rozmówcom">Jak mogę udostępnić swoją lokalizację moim rozmówcom?</a></li>
|
||||
<li><a href="#dlaczego-mogę-wybrać-aby-widzieć-tylko-folder-deltachat">Dlaczego mogę wybrać, aby widzieć tylko folder DeltaChat?</a></li>
|
||||
@@ -86,20 +86,21 @@
|
||||
</li>
|
||||
<li><a href="#różne">Różne</a>
|
||||
<ul>
|
||||
<li><a href="#jakich-uprawnień-potrzebuje-delta-chat">Jakich uprawnień potrzebuje ArcaneChat?</a></li>
|
||||
<li><a href="#czy-delta-chat-działa-z-moim-dostawcą-poczty-e-mail">Czy ArcaneChat działa z <em>moim</em> dostawcą poczty e-mail?</a></li>
|
||||
<li><a href="#chcę-zarządzać-własnym-serwerem-e-mail-dla-delta-chat-co-polecacie">Chcę zarządzać własnym serwerem e-mail dla ArcaneChat. Co polecacie?</a></li>
|
||||
<li><a href="#dlaczego-muszę-wpisać-moje-hasło-e-mail-do-delta-chat-czy-to-jest-bezpieczne">Dlaczego muszę wpisać moje hasło e-mail do ArcaneChat? Czy to jest bezpieczne?</a></li>
|
||||
<li><a href="#jakie-wiadomości-pojawiają-się-w-delta-chat">Jakie wiadomości pojawiają się w ArcaneChat?</a></li>
|
||||
<li><a href="#czy-delta-chat-obsługuje-wiadomości-e-mail-w-formacie-html">Czy ArcaneChat obsługuje wiadomości e-mail w formacie HTML?</a></li>
|
||||
<li><a href="#czy-w-delta-chat-mogę-ustawić-temat-wiadomości-e-mail">Czy w ArcaneChat mogę ustawić temat wiadomości e-mail?</a></li>
|
||||
<li><a href="#jakich-uprawnień-potrzebuje-delta-chat">Jakich uprawnień potrzebuje Delta Chat?</a></li>
|
||||
<li><a href="#czy-delta-chat-działa-z-moim-dostawcą-poczty-e-mail">Czy Delta Chat działa z <em>moim</em> dostawcą poczty e-mail?</a></li>
|
||||
<li><a href="#chcę-zarządzać-własnym-serwerem-e-mail-dla-delta-chat-co-polecacie">Chcę zarządzać własnym serwerem e-mail dla Delta Chat. Co polecacie?</a></li>
|
||||
<li><a href="#dlaczego-muszę-wpisać-moje-hasło-e-mail-do-delta-chat-czy-to-jest-bezpieczne">Dlaczego muszę wpisać moje hasło e-mail do Delta Chat? Czy to jest bezpieczne?</a></li>
|
||||
<li><a href="#jakie-wiadomości-pojawiają-się-w-delta-chat">Jakie wiadomości pojawiają się w Delta Chat?</a></li>
|
||||
<li><a href="#czy-delta-chat-obsługuje-wiadomości-e-mail-w-formacie-html">Czy Delta Chat obsługuje wiadomości e-mail w formacie HTML?</a></li>
|
||||
<li><a href="#czy-w-delta-chat-mogę-ustawić-temat-wiadomości-e-mail">Czy w Delta Chat mogę ustawić temat wiadomości e-mail?</a></li>
|
||||
<li><a href="#do-czego-służy-ustawienie-wyślij-kopię-do-siebie">Do czego służy ustawienie „Wyślij kopię do siebie”?</a></li>
|
||||
<li><a href="#po-co-mam-wybrać-opcję-oglądania-folderu-wysłane">Po co mam wybrać opcję oglądania folderu „Wysłane”?</a></li>
|
||||
<li><a href="#dlaczego-mogę-nie-widzieć-folderu-deltachat">Dlaczego mogę nie widzieć folderu DeltaChat?</a></li>
|
||||
<li><a href="#czy-delta-chat-jest-kompatybilny-z-protonmail--tutanota--criptext">Czy ArcaneChat jest kompatybilny z Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#jak-mogę-usunąć-swoje-konto">Jak mogę usunąć swoje konto?</a></li>
|
||||
<li><a href="#czy-delta-chat-jest-kompatybilny-z-protonmail--tutanota--criptext">Czy Delta Chat jest kompatybilny z Protonmail / Tutanota / Criptext?</a></li>
|
||||
<li><a href="#remove-account">Jak mogę usunąć swoje konto?</a></li>
|
||||
<li><a href="#interesują-mnie-szczegóły-techniczne-możesz-powiedzieć-mi-coś-więcej">Interesują mnie szczegóły techniczne. Możesz powiedzieć mi coś więcej?</a></li>
|
||||
<li><a href="#w-jaki-sposób-finansowany-jest-rozwój-delta-chat">W jaki sposób finansowany jest rozwój ArcaneChat?</a></li>
|
||||
<li><a href="#gdzie-moi-znajomi-mogą-znaleźć-delta-chat">Gdzie moi znajomi mogą znaleźć Delta Chat?</a></li>
|
||||
<li><a href="#w-jaki-sposób-finansowany-jest-rozwój-delta-chat">W jaki sposób finansowany jest rozwój Delta Chat?</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -109,14 +110,14 @@
|
||||
<h2 id="czym-jest-delta-chat">
|
||||
|
||||
|
||||
Czym jest ArcaneChat? <a href="#czym-jest-delta-chat" class="anchor"></a>
|
||||
Czym jest Delta Chat? <a href="#czym-jest-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h2>
|
||||
|
||||
<p>ArcaneChat to niezawodna, zdecentralizowana i bezpieczna aplikacja do przesyłania wiadomości, dostępna na platformy mobilne i stacjonarne.</p>
|
||||
<p>Delta Chat to niezawodna, zdecentralizowana i bezpieczna aplikacja do przesyłania wiadomości, dostępna na platformy mobilne i stacjonarne.</p>
|
||||
|
||||
<p>ArcaneChat przypomina Whatsapp lub Telegram, ale możesz go również używać i traktować jako aplikację e-mail. Możesz zarejestrować się anonimowo na różnych <a href="https://delta.chat/chatmail">interoperacyjnych serwerach chatmail</a>, które są minimalnymi serwerami poczty e-mail zoptymalizowanymi pod kątem szybkich i bezpiecznych operacji. Możesz też skorzystać z klasycznych serwerów pocztowych i istniejącego konta e-mail, w którym to przypadku ArcaneChat będzie pełnić funkcję aplikacji pocztowej. </p>
|
||||
<p>Delta Chat przypomina Whatsapp lub Telegram, ale możesz go również używać i traktować jako aplikację e-mail. Możesz zarejestrować się anonimowo na różnych <a href="https://delta.chat/chatmail">interoperacyjnych serwerach chatmail</a>, które są minimalnymi serwerami poczty e-mail zoptymalizowanymi pod kątem szybkich i bezpiecznych operacji. Możesz też skorzystać z klasycznych serwerów pocztowych i istniejącego konta e-mail, w którym to przypadku Delta Chat będzie pełnić funkcję aplikacji pocztowej. </p>
|
||||
|
||||
<p><img style="float:right; width:50%; max-width:360%; margin:1em;" src="../delta-what-optim.png" /></p>
|
||||
|
||||
@@ -130,12 +131,12 @@
|
||||
|
||||
<p>Aby bezpiecznie skonfigurować kontakt z innymi, <a href="#howtoe2ee">zeskanuj kod QR zaproszenia lub udostępnij link zaproszenia</a>. Jest to wymagane w przypadku korzystania z (domyślnego) profilu czatu opartego na poczcie chatmail, ponieważ serwery chatmail odrzucają niezaszyfrowane wiadomości wychodzące.</p>
|
||||
|
||||
<p>Jeśli utworzysz profil czatu z klasycznym adresem e-mail, możesz ręcznie utworzyć kontakt, jeśli znasz jego adres e-mail, a następnie napisać do niego wiadomość, nawet jeśli odbiorca nie korzysta z ArcaneChat.</p>
|
||||
<p>Jeśli utworzysz profil czatu z klasycznym adresem e-mail, możesz ręcznie utworzyć kontakt, jeśli znasz jego adres e-mail, a następnie napisać do niego wiadomość, nawet jeśli odbiorca nie korzysta z Delta Chat.</p>
|
||||
|
||||
<h3 id="jakie-są-zalety-delta-chat-w-porównaniu-z-innymi-komunikatorami">
|
||||
|
||||
|
||||
Jakie są zalety ArcaneChat w porównaniu z innymi komunikatorami? <a href="#jakie-są-zalety-delta-chat-w-porównaniu-z-innymi-komunikatorami" class="anchor"></a>
|
||||
Jakie są zalety Delta Chat w porównaniu z innymi komunikatorami? <a href="#jakie-są-zalety-delta-chat-w-porównaniu-z-innymi-komunikatorami" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -174,7 +175,7 @@
|
||||
<h3 id="czy-delta-chat-obsługuje-obrazy-filmy-i-inne-załączniki">
|
||||
|
||||
|
||||
Czy ArcaneChat obsługuje obrazy, filmy i inne załączniki? <a href="#czy-delta-chat-obsługuje-obrazy-filmy-i-inne-załączniki" class="anchor"></a>
|
||||
Czy Delta Chat obsługuje obrazy, filmy i inne załączniki? <a href="#czy-delta-chat-obsługuje-obrazy-filmy-i-inne-załączniki" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -198,7 +199,7 @@
|
||||
|
||||
<p>Profil to <strong>nazwa, zdjęcie</strong> i dodatkowe informacje umożliwiające szyfrowanie wiadomości. Profil znajduje się wyłącznie na twoim urządzeniu (urządzeniach) i do przesyłania wiadomości wykorzystuje chatmail lub klasyczny serwer e-mail.</p>
|
||||
|
||||
<p>Podczas pierwszej instalacji ArcaneChat tworzony jest pierwszy profil.</p>
|
||||
<p>Podczas pierwszej instalacji Delta Chat tworzony jest pierwszy profil.</p>
|
||||
|
||||
<p>Później możesz dotknąć swojego zdjęcia profilowego w lewym górnym rogu, aby <strong>Dodać profile</strong> lub <strong>Przełączyć profile</strong>.</p>
|
||||
|
||||
@@ -219,7 +220,7 @@
|
||||
<p>Możesz dodać zdjęcie profilowe w swoich ustawieniach. Jeśli napiszesz do swoich kontaktów lub dodasz je za pomocą kodu QR, automatycznie zobaczą je jako Twoje zdjęcie profilowe.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Kontakty, które nie korzystają z ArcaneChat nie widzą zdjęcia profilowego (jednak oczywiście mogą zainstalować ArcaneChat :)</p>
|
||||
<p>Kontakty, które nie korzystają z Delta Chat nie widzą zdjęcia profilowego (jednak oczywiście mogą zainstalować Delta Chat :)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Ze względów prywatności nikt nie widzi Twojego zdjęcia profilowego, dopóki nie napiszesz do niego wiadomości.</p>
|
||||
@@ -232,12 +233,12 @@
|
||||
<h3 id="signature">
|
||||
|
||||
|
||||
Czy w ArcaneChat mogę ustawić Biografię/Podpis/Status/Motto? <a href="#signature" class="anchor"></a>
|
||||
Czy w Delta Chat mogę ustawić Biografię/Podpis/Status/Motto? <a href="#signature" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Tak, możesz to zrobić w <strong>Ustawienia » Profil » Biografia</strong>. Twoje kontakty korzystające z ArcaneChat, zobaczą go, przeglądając twoje dane kontaktowe. Ponadto będzie on wyglądał jak klasyczny podpis w wiadomości e-mail.</p>
|
||||
<p>Tak, możesz to zrobić w <strong>Ustawienia » Profil » Biografia</strong>. Twoje kontakty korzystające z Delta Chat, zobaczą go, przeglądając twoje dane kontaktowe. Ponadto będzie on wyglądał jak klasyczny podpis w wiadomości e-mail.</p>
|
||||
|
||||
<h3 id="co-oznacza-przypinanie-wyciszanie-i-archiwizowanie">
|
||||
|
||||
@@ -265,8 +266,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Aby zarchiwizować lub przypiąć czat, dotknij i przytrzymaj (Android), użyj menu czatu (Android/Desktop) lub przesuń palcem w lewo (iOS);
|
||||
aby wyciszyć czat, użyj menu czatu (Android/Desktop) lub profilu czatu (iOS).</p>
|
||||
<p>Aby skorzystać z tych funkcji, przytrzymaj dłużej lub kliknij prawym przyciskiem myszy czat na liście czatów.</p>
|
||||
|
||||
<h3 id="co-oznacza-zielona-kropka">
|
||||
|
||||
@@ -277,12 +277,12 @@ aby wyciszyć czat, użyj menu czatu (Android/Desktop) lub profilu czatu (iOS).<
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Od wersji ArcaneChat 1.34 czasami można zobaczyć „zieloną kropkę” obok awatara kontaktu. Oznacza to, że był on „niedawno widziany”.</li>
|
||||
<li>Dokładnie oznacza to, że w ciągu ostatnich 10 minut ArcaneChat widział go:</li>
|
||||
<li>Od wersji Delta Chat 1.34 czasami można zobaczyć „zieloną kropkę” obok awatara kontaktu. Oznacza to, że był on „niedawno widziany”.</li>
|
||||
<li>Dokładnie oznacza to, że w ciągu ostatnich 10 minut Delta Chat widział go:</li>
|
||||
<li>dlatego, że wysłał Ci bezpośrednio wiadomość,</li>
|
||||
<li>ponieważ napisał coś do grupy, której oboje jesteście członkami,</li>
|
||||
<li>ponieważ wysłał Ci potwierdzenie przeczytania napisanej przez Ciebie wiadomości,</li>
|
||||
<li>lub dlatego, że wysłał dane do Twojej aplikacji ArcaneChat za pomocą <a href="#webxdc">Webxdc aplikacji</a>.</li>
|
||||
<li>lub dlatego, że wysłał dane do Twojej aplikacji Delta Chat za pomocą <a href="#webxdc">Webxdc aplikacji</a>.</li>
|
||||
<li>Nie jest to więc status online w czasie rzeczywistym – a jeśli ktoś nie odpowie od razu, mimo że wydaje się, że jest online, nie martw się i daj mu trochę miejsca ;-)</li>
|
||||
<li>Z drugiej strony inni nie zawsze „zobaczą, że jesteś online”. Jeśli wyłączyłeś potwierdzenia odczytu, nie zobaczą oni zielonej kropki, dopóki nie wyślesz do nich wiadomości lub nie napiszesz do grupy, w której również się znajdują.</li>
|
||||
</ul>
|
||||
@@ -297,11 +297,11 @@ aby wyciszyć czat, użyj menu czatu (Android/Desktop) lub profilu czatu (iOS).<
|
||||
|
||||
<p>Możesz włączyć „znikające wiadomości” w ustawieniach czatu, w prawym górnym rogu okna czatu, wybierając przedział czasu od 1 minuty do 5 tygodni.</p>
|
||||
|
||||
<p>Dopóki ustawienie nie zostanie ponownie wyłączone, aplikacja ArcaneChat u każdego członka czatu zajmie się usuwaniem wiadomości po wybranym okresie. Przedział czasu rozpoczyna się w momencie, gdy odbiorca po raz pierwszy zobaczy wiadomość w ArcaneChat. Wiadomości są usuwane zarówno na każdym koncie e-mail na serwerze, jak i w samej aplikacji.</p>
|
||||
<p>Dopóki ustawienie nie zostanie ponownie wyłączone, aplikacja Delta Chat u każdego członka czatu zajmie się usuwaniem wiadomości po wybranym okresie. Przedział czasu rozpoczyna się w momencie, gdy odbiorca po raz pierwszy zobaczy wiadomość w Delta Chat. Wiadomości są usuwane zarówno na każdym koncie e-mail na serwerze, jak i w samej aplikacji.</p>
|
||||
|
||||
<p>Pamiętaj, że na znikających wiadomościach możesz polegać tylko wtedy, gdy ufasz swoim partnerom czatu; złośliwi partnerzy czatu mogą robić zdjęcia lub w inny sposób zapisywać, kopiować lub przesyłać dalej wiadomości przed usunięciem.</p>
|
||||
|
||||
<p>Poza tym, jeśli jeden z partnerów czatu odinstaluje ArcaneChat, wiadomości nie zostaną usunięte z jego konta e-mail. Najprawdopodobniej nie będzie już można ich odszyfrować (o ile zostały najpierw zaszyfrowane).</p>
|
||||
<p>Poza tym, jeśli jeden z partnerów czatu odinstaluje Delta Chat, wiadomości nie zostaną usunięte z jego konta e-mail. Najprawdopodobniej nie będzie już można ich odszyfrować (o ile zostały najpierw zaszyfrowane).</p>
|
||||
|
||||
<h2 id="grupy">
|
||||
|
||||
@@ -395,13 +395,13 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Domyślnie ArcaneChat przechowuje wszystkie wiadomości lokalnie na Twoim urządzeniu. Jeśli np. chcesz zaoszczędzić miejsce u swojego dostawcy poczty, możesz wybrać automatyczne usuwanie starych wiadomości. Pozostają one nadal na Twoim urządzeniu, dopóki nie usuniesz ich również tam.</p>
|
||||
<p>Domyślnie Delta Chat przechowuje wszystkie wiadomości lokalnie na Twoim urządzeniu. Jeśli np. chcesz zaoszczędzić miejsce u swojego dostawcy poczty, możesz wybrać automatyczne usuwanie starych wiadomości. Pozostają one nadal na Twoim urządzeniu, dopóki nie usuniesz ich również tam.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Aby ją włączyć, w ustawieniach „Czaty i media” przejdź do <strong>Usuwanie starych wiadomości → Usuń wiadomości z serwera</strong>. Możesz ustawić przedział czasowy pomiędzy „Od razu” a „Po 1 roku”. Wszystkie e-maile otrzymane przez ArcaneChat zostaną usunięte z serwera po tym czasie.</p>
|
||||
<p>Aby ją włączyć, w ustawieniach „Czaty i media” przejdź do <strong>Usuwanie starych wiadomości → Usuń wiadomości z serwera</strong>. Możesz ustawić przedział czasowy pomiędzy „Od razu” a „Po 1 roku”. Wszystkie e-maile otrzymane przez Delta Chat zostaną usunięte z serwera po tym czasie.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Zauważ, że jeśli używasz ArcaneChat na więcej niż jednym urządzeniu, powinieneś pozostawić wiadomości na serwerze, do czasu, aż inne urządzenie/urządzenia będzie mogło je pobrać.</p>
|
||||
<p>Zauważ, że jeśli używasz Delta Chat na więcej niż jednym urządzeniu, powinieneś pozostawić wiadomości na serwerze, do czasu, aż inne urządzenie/urządzenia będzie mogło je pobrać.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -434,7 +434,7 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Powiadomienia push są wysyłane przez „usługi push” Apple i Google do urządzenia użytkownika, dzięki czemu nieaktywna aplikacja ArcaneChat może pobierać wiadomości w tle i w razie potrzeby wyświetlać powiadomienia na telefonie użytkownika.</p>
|
||||
<p>Powiadomienia push są wysyłane przez „usługi push” Apple i Google do urządzenia użytkownika, dzięki czemu nieaktywna aplikacja Delta Chat może pobierać wiadomości w tle i w razie potrzeby wyświetlać powiadomienia na telefonie użytkownika.</p>
|
||||
|
||||
<p>Powiadomienia push działają na wszystkich włączonych serwerach <a href="https://delta.chat/chatmail">chatmail</a></p>
|
||||
|
||||
@@ -447,7 +447,7 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Od maja 2024 r. klasyczne serwery poczty e-mail nie obsługują powiadomień push dla użytkowników ArcaneChat.</p>
|
||||
<p>Od maja 2024 r. klasyczne serwery poczty e-mail nie obsługują powiadomień push dla użytkowników Delta Chat.</p>
|
||||
|
||||
<h3 id="czy-powiadomienia-push-są-włączone-na-urządzeniach-z-ios-czy-istnieje-alternatywa">
|
||||
|
||||
@@ -457,8 +457,8 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Tak, ArcaneChat automatycznie korzysta z powiadomień push dla profili <a href="https://delta.chat/chatmail">chatmail</a>
|
||||
. I nie, w telefonach Apple nie ma alternatywy umożliwiającej natychmiastowe dostarczanie wiadomości, ponieważ urządzenia Apple nie pozwalają ArcaneChat na pobieranie danych w tle. Powiadomienia push są automatycznie aktywowane dla użytkowników iOS, ponieważ <a href="#privacy-notifications">system prywatności powiadomień ArcaneChat</a> nie udostępnia Apple danych, których jeszcze nie posiada.</p>
|
||||
<p>Tak, Delta Chat automatycznie korzysta z powiadomień push dla profili <a href="https://delta.chat/chatmail">chatmail</a>
|
||||
. I nie, w telefonach Apple nie ma alternatywy umożliwiającej natychmiastowe dostarczanie wiadomości, ponieważ urządzenia Apple nie pozwalają Delta Chat na pobieranie danych w tle. Powiadomienia push są automatycznie aktywowane dla użytkowników iOS, ponieważ <a href="#privacy-notifications">system prywatności powiadomień Delta Chat</a> nie udostępnia Apple danych, których jeszcze nie posiada.</p>
|
||||
|
||||
<h3 id="android-push">
|
||||
|
||||
@@ -468,12 +468,12 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Jeśli dostępna jest „Usługa Push”, ArcaneChat włącza Powiadomienia Push w celu zapewnienia natychmiastowego dostarczania wiadomości dla wszystkich użytkowników chatmail. Jeśli zamiast serwerów <a href="https://delta.chat/chatmail">chatmail</a> korzystasz z klasycznego dostawcy poczty e-mail, powiadomienia push nie są dostępne.</p>
|
||||
<p>Jeśli dostępna jest „Usługa Push”, Delta Chat włącza Powiadomienia Push w celu zapewnienia natychmiastowego dostarczania wiadomości dla wszystkich użytkowników chatmail. Jeśli zamiast serwerów <a href="https://delta.chat/chatmail">chatmail</a> korzystasz z klasycznego dostawcy poczty e-mail, powiadomienia push nie są dostępne.</p>
|
||||
|
||||
<p>W ustawieniach „Powiadomień” ArcaneChat dla „Natychmiastowej dostawy” możesz zmienić następujące ustawienia wpływające na wszystkie profile czatu:</p>
|
||||
<p>W ustawieniach „Powiadomień” Delta Chat dla „Natychmiastowej dostawy” możesz zmienić następujące ustawienia wpływające na wszystkie profile czatu:</p>
|
||||
|
||||
<ul>
|
||||
<li>Użyj połączenia w tle: Jeśli nie korzystasz z usługi Push, możesz wyłączyć „optymalizację baterii” dla ArcaneChat, umożliwiając mu pobieranie wiadomości w tle. Mogą jednak wystąpić opóźnienia od minut do godzin. Niektórzy dostawcy Androida nawet całkowicie ograniczają aplikacje (zobacz <a href="https://dontkillmyapp.com">dontkillmyapp.com</a>), a ArcaneChat może nie wyświetlać wiadomości przychodzących, dopóki ręcznie ponownie nie otworzysz aplikacji.</li>
|
||||
<li>Użyj połączenia w tle: Jeśli nie korzystasz z usługi Push, możesz wyłączyć „optymalizację baterii” dla Delta Chat, umożliwiając mu pobieranie wiadomości w tle. Mogą jednak wystąpić opóźnienia od minut do godzin. Niektórzy dostawcy Androida nawet całkowicie ograniczają aplikacje (zobacz <a href="https://dontkillmyapp.com">dontkillmyapp.com</a>), a Delta Chat może nie wyświetlać wiadomości przychodzących, dopóki ręcznie ponownie nie otworzysz aplikacji.</li>
|
||||
</ul>
|
||||
|
||||
<p>Wymuś połączenie w tle: Jest to opcja awaryjna, jeśli poprzednie opcje nie są dostępne lub nie zapewniają „natychmiastowej dostawy”. Włączenie tej opcji powoduje stałe powiadomienie na twoim telefonie, które czasami może zostać „minifikowane” w przypadku najnowszych telefonów z Androidem.</p>
|
||||
@@ -483,47 +483,47 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
<h3 id="privacy-notifications">
|
||||
|
||||
|
||||
Jak prywatne są powiadomienia push na ArcaneChat? <a href="#privacy-notifications" class="anchor"></a>
|
||||
Jak prywatne są powiadomienia push na Delta Chat? <a href="#privacy-notifications" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Obsługa powiadomień push w ArcaneChat pozwala uniknąć wycieku prywatnych informacji. Nie powoduje wycieku wiadomości e-mail, adresu IP ani zawartości wiadomości (nawet niezaszyfrowanej) do żadnego systemu zaangażowanego w dostarczanie powiadomień push.</p>
|
||||
<p>Obsługa powiadomień push w Delta Chat pozwala uniknąć wycieku prywatnych informacji. Nie powoduje wycieku wiadomości e-mail, adresu IP ani zawartości wiadomości (nawet niezaszyfrowanej) do żadnego systemu zaangażowanego w dostarczanie powiadomień push.</p>
|
||||
|
||||
<p>Oto jak aplikacje ArcaneChat realizują dostarczanie powiadomień push:</p>
|
||||
<p>Oto jak aplikacje Delta Chat realizują dostarczanie powiadomień push:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Aplikacja ArcaneChat uzyskuje lokalnie „token urządzenia” i przechowuje go na serwerze <a href="https://delta.chat/chatmail">chatmail</a>.</p>
|
||||
<p>Aplikacja Delta Chat uzyskuje lokalnie „token urządzenia”, szyfruje i przechowuje go na serwerze <a href="https://delta.chat/chatmail">chatmail</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Kiedy serwer <a href="https://delta.chat/chatmail">chatmail</a> odbierze wiadomość e-mail od użytkownika ArcaneChat, przekazuje „token urządzenia” do centralnego serwera proxy powiadomień ArcaneChat.</p>
|
||||
<p>Kiedy serwer <a href="https://delta.chat/chatmail">chatmail</a> odbierze wiadomość e-mail od użytkownika Delta Chat, przekazuje zaszyfrowany token urządzenia do centralnego serwera proxy powiadomień Delta Chat.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Centralny serwer proxy powiadomień ArcaneChat przekazuje „token urządzenia” do odpowiedniej usługi Push (Apple, Google itp.), nie znając nawet adresu IP ani adresu e-mail użytkowników ArcaneChat.</p>
|
||||
<p>Centralny serwer proxy powiadomień Delta Chat deszyfruje token urządzenia i przekazuje go do odpowiedniej usługi Push (Apple, Google itp.), nie znając nawet adresu IP ani adresu e-mail użytkowników Delta Chat.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Centralna usługa Push (Apple, Google itp.) budzi aplikację ArcaneChat na twoim urządzeniu, aby sprawdzić w tle nowe wiadomości. Nie zna chatmaila ani adresu e-mail urządzenia, na którym się budzi. Centralne usługi push Apple/Google nigdy nie widzą adresu e-mail (nadawcy ani odbiorcy), a także nigdy nie widzą treści wiadomości (również w formie zaszyfrowanej).</p>
|
||||
<p>Centralna usługa Push (Apple, Google itp.) budzi aplikację Delta Chat na twoim urządzeniu, aby sprawdzić w tle nowe wiadomości. Nie zna chatmaila ani adresu e-mail urządzenia, na którym się budzi. Centralne usługi push Apple/Google nigdy nie widzą adresu e-mail (nadawcy ani odbiorcy), a także nigdy nie widzą treści wiadomości (również w formie zaszyfrowanej).</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Od maja 2024 r. serwery chatmail znają „tokeny urządzenia”, ale planujemy szyfrować te informacje na serwerze proxy powiadomień, tak aby serwer chatmail nigdy nie poznał tokena urządzenia.</p>
|
||||
<p>Centralny serwer proxy powiadomień Delta Chat <a href="https://github.com/deltachat/notifiers">jest mały i w pełni zaimplementowany w Rust</a> i zapomina o tokenach urządzeń zaraz po ich przetworzeniu przez Apple/Google/itp, zwykle w ciągu kilku milisekund.</p>
|
||||
|
||||
<p>Centralny serwer proxy powiadomień ArcaneChat <a href="https://github.com/deltachat/notifiers">jest mały i w pełni zaimplementowany w Rust</a> i zapomina o tokenach urządzeń zaraz po ich przetworzeniu przez Apple/Google/itp, zwykle w ciągu kilku milisekund.</p>
|
||||
<p>Pamiętaj, że token urządzenia jest szyfrowany między aplikacjami a serwerem proxy powiadomień, ale nie jest podpisany. Serwer proxy powiadomień nigdy nie widzi adresów e-mail, adresów IP ani żadnych kryptograficznych informacji identyfikujących powiązanych z urządzeniem użytkownika (tokenem).</p>
|
||||
|
||||
<p>W wyniku tego ogólnego projektu ochrony prywatności nawet przejęcie serwera chatmail lub pełne przejęcie centralnego serwera proxy powiadomień ArcaneChat nie spowodowałoby ujawnienia prywatnych informacji, których usługi Push jeszcze nie posiadają.</p>
|
||||
<p>W wyniku tego ogólnego projektu ochrony prywatności nawet przejęcie serwera chatmail lub pełne przejęcie centralnego serwera proxy powiadomień Delta Chat nie spowodowałoby ujawnienia prywatnych informacji, których usługi Push jeszcze nie posiadają.</p>
|
||||
|
||||
<h3 id="dlaczego-delta-chat-integruje-się-ze-scentralizowanymi-zastrzeżonymi-usługami-push-applegoogle">
|
||||
|
||||
|
||||
Dlaczego ArcaneChat integruje się ze scentralizowanymi, zastrzeżonymi usługami push Apple/Google? <a href="#dlaczego-delta-chat-integruje-się-ze-scentralizowanymi-zastrzeżonymi-usługami-push-applegoogle" class="anchor"></a>
|
||||
Dlaczego Delta Chat integruje się ze scentralizowanymi, zastrzeżonymi usługami push Apple/Google? <a href="#dlaczego-delta-chat-integruje-się-ze-scentralizowanymi-zastrzeżonymi-usługami-push-applegoogle" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>ArcaneChat to darmowy i otwartoźródłowy zdecentralizowany komunikator z możliwością wyboru serwera, ale chcemy, aby użytkownicy mogli niezawodnie doświadczać „natychmiastowego dostarczania” wiadomości, tak jak w przypadku aplikacji Whatsapp, Signal lub Telegram, bez zadawania z góry pytań, które są bardziej odpowiednie dla doświadczonych użytkowników lub programistów.</p>
|
||||
<p>Delta Chat to darmowy i otwartoźródłowy zdecentralizowany komunikator z możliwością wyboru serwera, ale chcemy, aby użytkownicy mogli niezawodnie doświadczać „natychmiastowego dostarczania” wiadomości, tak jak w przypadku aplikacji Whatsapp, Signal lub Telegram, bez zadawania z góry pytań, które są bardziej odpowiednie dla doświadczonych użytkowników lub programistów.</p>
|
||||
|
||||
<p>Pamiętaj, że ArcaneChat posiada <a href="#privacy-notifications">mały i chroniący prywatność system powiadomień push</a>, który zapewnia „natychmiastowe dostarczanie” wiadomości ze wszystkich serwerów chatmail, w tym potencjalnego, który <a href="https://delta.chat/chatmail#selfhosted">możesz skonfigurować samodzielnie bez naszej zgody</a>. Witamy w potędze interoperacyjnego i ogromnego systemu chatmail i e-mail :)</p>
|
||||
<p>Pamiętaj, że Delta Chat posiada <a href="#privacy-notifications">mały i chroniący prywatność system powiadomień push</a>, który zapewnia „natychmiastowe dostarczanie” wiadomości ze wszystkich serwerów chatmail, w tym potencjalnego, który <a href="https://delta.chat/chatmail#selfhosted">możesz skonfigurować samodzielnie bez naszej zgody</a>. Witamy w potędze interoperacyjnego i ogromnego systemu chatmail i e-mail :)</p>
|
||||
|
||||
<h2 id="szyfrowanie-i-bezpieczeństwo">
|
||||
|
||||
@@ -578,11 +578,11 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
<p>W przypadku <strong>zaproszeń grupowych</strong> dotknij tytułu czatu grupy, aby wyświetlić listę jej członków, i wybierz „Kod QR zaproszenia”.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Aby uzyskać <strong>bezpośrednie zaproszenia na czat 1:1</strong>, dotknij ikony kodu QR <img style="vertical-align:middle; width:1.8em; margin:1px" src="../qr-icon.png" /> na ekranie głównym aplikacji ArcaneChat.</p>
|
||||
<p>Aby uzyskać <strong>bezpośrednie zaproszenia na czat 1:1</strong>, dotknij ikony kodu QR <img style="vertical-align:middle; width:1.8em; margin:1px" src="../qr-icon.png" /> na ekranie głównym aplikacji Delta Chat.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>Pozwól swojemu partnerowi czatu zeskanować obraz QR za pomocą aplikacji ArcaneChat lub dotknij „Kopiuj” lub „Udostępnij”, aby utworzyć link zaproszenia i udostępnić go swojemu partnerowi czatu.</p>
|
||||
<p>Pozwól swojemu partnerowi czatu zeskanować obraz QR za pomocą aplikacji Delta Chat lub dotknij „Kopiuj” lub „Udostępnij”, aby utworzyć link zaproszenia i udostępnić go swojemu partnerowi czatu.</p>
|
||||
|
||||
<p>Teraz poczekaj, aż między obydwoma urządzeniami <a href="https://securejoin.delta.chat/en/latest/new.html#setup-contact-protocol">nastąpi wymiana wiadomości sieciowych Secure-Join</a>.</p>
|
||||
|
||||
@@ -625,27 +625,27 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
<p>Jeśli twój kontakt rzeczywiście spowodował spadek gwarantowanego szyfrowania typu end-to-end, zapoznaj się z kolejnymi akapitami, aby poznać typowe przyczyny i sposoby ich łagodzenia. Niezależnie od tego, wszystkie inne czaty oznaczone zielonym znacznikiem są w pełni szyfrowane, nawet jeśli kontakt jest ich członkiem.</p>
|
||||
|
||||
<p><strong>Twój kontakt korzysta z ArcaneChat na drugim urządzeniu (telefonie lub laptopie)</strong></p>
|
||||
<p><strong>Twój kontakt korzysta z Delta Chat na drugim urządzeniu (telefonie lub laptopie)</strong></p>
|
||||
|
||||
<p>Jeśli ma inne urządzenie z uruchomioną aplikacją ArcaneChat, powinien usunąć konto z nowego urządzenia i dodać je <a href="#multiclient">jako drugie urządzenie zgodnie z opisem tutaj</a>. Gdy tylko skontaktuje się z tobą później, ostrzeżenie zniknie, a na obu urządzeniach twojego kontaktu zostanie ustanowione gwarantowane szyfrowanie.</p>
|
||||
<p>Jeśli ma inne urządzenie z uruchomioną aplikacją Delta Chat, powinien usunąć konto z nowego urządzenia i dodać je <a href="#multiclient">jako drugie urządzenie zgodnie z opisem tutaj</a>. Gdy tylko skontaktuje się z tobą później, ostrzeżenie zniknie, a na obu urządzeniach twojego kontaktu zostanie ustanowione gwarantowane szyfrowanie.</p>
|
||||
|
||||
<p><strong>Twój kontakt ponownie zainstalował ArcaneChat, używając swojego starego loginu do konta</strong></p>
|
||||
<p><strong>Twój kontakt ponownie zainstalował Delta Chat, używając swojego starego loginu do konta</strong></p>
|
||||
|
||||
<p>Jeśli ma <a href="#backup">plik kopii zapasowej</a>, powinien usunąć konto z nowego urządzenia i zamiast tego zaimportować plik kopii zapasowej, aby ponownie utworzyć konto. Gdy tylko skontaktuje się z tobą później, ostrzeżenie zniknie, a dla tego kontaktu zostanie przywrócone gwarantowane szyfrowanie.</p>
|
||||
|
||||
<p>Jeśli nie ma pliku kopii zapasowej, najlepiej wykonać <a href="#howtoe2ee">skanowanie QR</a> ze swoim partnerem czatu, aby przywrócić gwarantowane szyfrowanie end-to-end.</p>
|
||||
|
||||
<p><strong>Twój kontakt wysłał wiadomość e-mail za pośrednictwem interfejsu poczty internetowej lub innej aplikacji e-mail i wkrótce ponownie zacznie korzystać z ArcaneChat.</strong></p>
|
||||
<p><strong>Twój kontakt wysłał wiadomość e-mail za pośrednictwem interfejsu poczty internetowej lub innej aplikacji e-mail i wkrótce ponownie zacznie korzystać z Delta Chat.</strong></p>
|
||||
|
||||
<p>Jeśli masz pewność, że kontakt czasami korzysta z poczty internetowej lub innej aplikacji pocztowej, która nie zapewnia szyfrowania end-to-end, możesz zaakceptować ostrzeżenie. Gdy tylko twój kontakt ponownie skorzysta z ArcaneChat, gwarantowane szyfrowanie end-to-end zostanie automatycznie przywrócone.</p>
|
||||
<p>Jeśli masz pewność, że kontakt czasami korzysta z poczty internetowej lub innej aplikacji pocztowej, która nie zapewnia szyfrowania end-to-end, możesz zaakceptować ostrzeżenie. Gdy tylko twój kontakt ponownie skorzysta z Delta Chat, gwarantowane szyfrowanie end-to-end zostanie automatycznie przywrócone.</p>
|
||||
|
||||
<p><strong>Twój kontakt całkowicie przestał korzystać z ArcaneChat</strong></p>
|
||||
<p><strong>Twój kontakt całkowicie przestał korzystać z Delta Chat</strong></p>
|
||||
|
||||
<p>Czasami utrzymanie kontaktu jest ważniejsze niż szyfrowanie end-to-end. <a href="#tls">„Szyfrowanie warstwy transportowej” (TLS)</a> może w dalszym ciągu w znaczący sposób chronić poufność wiadomości przesyłanych między urządzeniem a serwerem poczty e-mail. Jednak bez kompleksowego szyfrowania Ty i Twój kontakt ufacie swojemu serwerowi poczty e-mail, że nie będzie czytać ani manipulować waszymi wiadomościami i nie będzie przekazywać ich osobom trzecim.</p>
|
||||
|
||||
<p>W każdym razie nie możesz zrobić nic innego, jak zaakceptować ostrzeżenie. Usuń także kontakt z aktywnej grupy oznaczonej zielonym znacznikiem, którą znajdziesz w sekcji „Współdzielone czaty” w profilu kontaktu. Dzięki temu twój kontakt nie otrzyma „nieczytelnych” wiadomości.</p>
|
||||
|
||||
<p>Jeśli kontakt usunął ArcaneChat z powodu błędów lub niepożądanego zachowania, rozważ opublikowanie postu na naszym <a href="https://support.delta.chat">forum pomocy</a>, aby pomóc nam zidentyfikować i rozwiązać typowe problemy. Dzięki!</p>
|
||||
<p>Jeśli kontakt usunął Delta Chat z powodu błędów lub niepożądanego zachowania, rozważ opublikowanie postu na naszym <a href="https://support.delta.chat">forum pomocy</a>, aby pomóc nam zidentyfikować i rozwiązać typowe problemy. Dzięki!</p>
|
||||
|
||||
<h3 id="czy-załączniki-zdjęcia-pliki-pliki-audio-itp-są-szyfrowane-metodą-end-to-end">
|
||||
|
||||
@@ -667,9 +667,9 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Tak, ArcaneChat korzysta z bezpiecznego podzbioru OpenPGP i wyświetla wskaźnik bezpieczeństwa kłódki na wiadomości tylko wtedy, gdy cała wiadomość jest prawidłowo zaszyfrowana i podpisana. Na przykład „Odłączone podpisy” nie są traktowane jako bezpieczne.</p>
|
||||
<p>Tak, Delta Chat korzysta z bezpiecznego podzbioru OpenPGP i wyświetla wskaźnik bezpieczeństwa kłódki na wiadomości tylko wtedy, gdy cała wiadomość jest prawidłowo zaszyfrowana i podpisana. Na przykład „Odłączone podpisy” nie są traktowane jako bezpieczne.</p>
|
||||
|
||||
<p>OpenPGP samo w sobie nie jest niebezpieczne. Większość publicznie omawianych problemów związanych z bezpieczeństwem OpenPGP tak naprawdę wynika ze złej użyteczności lub złej implementacji narzędzi, lub aplikacji (lub obu). Szczególnie ważne jest rozróżnienie pomiędzy OpenPGP, standardem szyfrowania IETF, a GnuPG (GPG), narzędziem wiersza poleceń implementującym OpenPGP. Wiele publicznych komentarzy krytycznych na temat OpenPGP tak naprawdę omawia GnuPG, którego ArcaneChat nigdy nie używał. ArcaneChat korzysta raczej z implementacji OpenPGP Rust <a href="https://github.com/rpgp/rpgp">rPGP</a>, dostępnej jako <a href="https://crates.io/crates/pgp">niezależny pakiet „pgp”</a> i poddanej <a href="https://delta.chat/assets/blog/2019-first-security-review.pdf">audytowi bezpieczeństwa w 2019 roku</a>.</p>
|
||||
<p>OpenPGP samo w sobie nie jest niebezpieczne. Większość publicznie omawianych problemów związanych z bezpieczeństwem OpenPGP tak naprawdę wynika ze złej użyteczności lub złej implementacji narzędzi, lub aplikacji (lub obu). Szczególnie ważne jest rozróżnienie pomiędzy OpenPGP, standardem szyfrowania IETF, a GnuPG (GPG), narzędziem wiersza poleceń implementującym OpenPGP. Wiele publicznych komentarzy krytycznych na temat OpenPGP tak naprawdę omawia GnuPG, którego Delta Chat nigdy nie używał. Delta Chat korzysta raczej z implementacji OpenPGP Rust <a href="https://github.com/rpgp/rpgp">rPGP</a>, dostępnej jako <a href="https://crates.io/crates/pgp">niezależny pakiet „pgp”</a> i poddanej <a href="https://delta.chat/assets/blog/2019-first-security-review.pdf">audytowi bezpieczeństwa w 2019 roku</a>.</p>
|
||||
|
||||
<p>Naszym celem, wraz z innymi wdrażającymi OpenPGP, jest dalsza poprawa parametrów bezpieczeństwa poprzez wdrożenie <a href="https://datatracker.ietf.org/doc/draft-ietf-openpgp-crypto-refresh/">nowego IETF OpenPGP Crypto-Refresh</a>, który na szczęście został przyjęty latem 2023 roku.</p>
|
||||
|
||||
@@ -683,19 +683,19 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
<p>Tak, podążamy za rozwiązaniami takimi jak <a href="https://en.wikipedia.org/wiki/Messaging_Layer_Security">MLS</a> lub <a href="https://saltpack.org/">Saltpack</a>, ale przyjęcie ich oznaczałoby zerwanie kompleksowej interoperacyjności szyfrowania ze wszystkimi innymi aplikacjami e-mail, które zazwyczaj obsługują szyfrowanie OpenPGP. Nie byłaby to więc łatwa decyzja i użytkownicy muszą wprowadzić wymierne ulepszenia.</p>
|
||||
|
||||
<p>ArcaneChat przyjmuje holistyczne podejście do „użytecznego bezpieczeństwa” i współpracuje z szeroką gamą grup aktywistów, a także renomowanymi badaczami, takimi jak <a href="https://teamusec.de">TeamUSEC</a>, aby poprawić rzeczywiste wyniki użytkowników przed zagrożeniami bezpieczeństwa. Protokół przewodowy i standard ustanawiania szyfrowania end-to-end to tylko jedna część „wyników użytkownika”. Zobacz także nasze odpowiedzi na pytania dotyczące <a href="#device-seizure">przejęcia urządzenia</a> i <a href="#message-metadata">metadanych wiadomości</a>.</p>
|
||||
<p>Delta Chat przyjmuje holistyczne podejście do „użytecznego bezpieczeństwa” i współpracuje z szeroką gamą grup aktywistów, a także renomowanymi badaczami, takimi jak <a href="https://teamusec.de">TeamUSEC</a>, aby poprawić rzeczywiste wyniki użytkowników przed zagrożeniami bezpieczeństwa. Protokół przewodowy i standard ustanawiania szyfrowania end-to-end to tylko jedna część „wyników użytkownika”. Zobacz także nasze odpowiedzi na pytania dotyczące <a href="#device-seizure">przejęcia urządzenia</a> i <a href="#message-metadata">metadanych wiadomości</a>.</p>
|
||||
|
||||
<h3 id="czy-delta-chat-jest-podatny-na-efail">
|
||||
|
||||
|
||||
Czy ArcaneChat jest podatny na EFAIL? <a href="#czy-delta-chat-jest-podatny-na-efail" class="anchor"></a>
|
||||
Czy Delta Chat jest podatny na EFAIL? <a href="#czy-delta-chat-jest-podatny-na-efail" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Nie, <a href="https://delta.chat/en/2018-05-15-delta-chat-not-vulnerable-to-efail">ArcaneChat nigdy nie był podatny na atak EFAIL</a>, ponieważ jego implementacja OpenPGP <a href="https://github.com/rpgp/rpgp">rPGP</a> używa kodu wykrywania modyfikacji podczas szyfrowania wiadomości i zwraca <a href="https://docs.rs/pgp/latest/pgp/errors/enum.Error.html#variant.MdcError">błąd</a>, jeśli kod wykrywania modyfikacji jest nieprawidłowy.</p>
|
||||
<p>Nie, <a href="https://delta.chat/en/2018-05-15-delta-chat-not-vulnerable-to-efail">Delta Chat nigdy nie był podatny na atak EFAIL</a>, ponieważ jego implementacja OpenPGP <a href="https://github.com/rpgp/rpgp">rPGP</a> używa kodu wykrywania modyfikacji podczas szyfrowania wiadomości i zwraca <a href="https://docs.rs/pgp/latest/pgp/errors/enum.Error.html#variant.MdcError">błąd</a>, jeśli kod wykrywania modyfikacji jest nieprawidłowy.</p>
|
||||
|
||||
<p>ArcaneChat również nigdy nie był podatny na atak EFAIL „Direct Exfiltration”, ponieważ odszyfrowuje jedynie wiadomości <code class="language-plaintext highlighter-rouge">multipart/encrypted</code>, które zawierają dokładnie jedną zaszyfrowaną i podpisaną część, zgodnie ze specyfikacją Autocrypt Level 1.</p>
|
||||
<p>Delta Chat również nigdy nie był podatny na atak EFAIL „Direct Exfiltration”, ponieważ odszyfrowuje jedynie wiadomości <code class="language-plaintext highlighter-rouge">multipart/encrypted</code>, które zawierają dokładnie jedną zaszyfrowaną i podpisaną część, zgodnie ze specyfikacją Autocrypt Level 1.</p>
|
||||
|
||||
<h3 id="tls">
|
||||
|
||||
@@ -707,19 +707,19 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
<p>Nawet jeśli nie ma gwarancji, że twoje wiadomości będą zaszyfrowane metodą end-to-end, nadal są chronione przed dostawcami Internetu, takimi jak operatorzy komórkowi lub telewizji kablowej. Jednakże dostawcy poczty e-mail zarówno twoi, jak i twojego odbiorcy mogą czytać, analizować, a nawet modyfikować twoje wiadomości, w tym wszelkie załączniki, jeśli nie są one w pełni zaszyfrowane.</p>
|
||||
|
||||
<p>ArcaneChat domyślnie korzysta ze ścisłego <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">szyfrowania TLS</a>, które zabezpiecza połączenia pomiędzy twoim urządzeniem a dostawcą poczty e-mail. Cała obsługa TLS ArcaneChat została poddana niezależnemu <a href="#security-audits">audytowi bezpieczeństwa</a>. Co więcej, połączenie między tobą a dostawcą poczty e-mail odbiorcy będzie zazwyczaj również szyfrowane. Jeśli zaangażowane serwery poczty e-mail obsługują <a href="https://datatracker.ietf.org/doc/html/rfc8461">MTA-STS</a>, pomiędzy dostawcami poczty e-mail będzie egzekwowane szyfrowanie transportu. W takim przypadku komunikacja ArcaneChat nigdy nie będzie udostępniana w Internecie w postaci zwykłego tekstu, nawet jeśli wiadomość nie została zaszyfrowana metodą end-to-end.</p>
|
||||
<p>Delta Chat domyślnie korzysta ze ścisłego <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">szyfrowania TLS</a>, które zabezpiecza połączenia pomiędzy twoim urządzeniem a dostawcą poczty e-mail. Cała obsługa TLS Delta Chat została poddana niezależnemu <a href="#security-audits">audytowi bezpieczeństwa</a>. Co więcej, połączenie między tobą a dostawcą poczty e-mail odbiorcy będzie zazwyczaj również szyfrowane. Jeśli zaangażowane serwery poczty e-mail obsługują <a href="https://datatracker.ietf.org/doc/html/rfc8461">MTA-STS</a>, pomiędzy dostawcami poczty e-mail będzie egzekwowane szyfrowanie transportu. W takim przypadku komunikacja Delta Chat nigdy nie będzie udostępniana w Internecie w postaci zwykłego tekstu, nawet jeśli wiadomość nie została zaszyfrowana metodą end-to-end.</p>
|
||||
|
||||
<p>Pamiętaj, że <a href="#howtoe2ee">utrzymywanie gwarantowanego szyfrowania typu end-to-end</a> oprócz szyfrowania TLS zapewnia wszechstronne bezpieczeństwo między urządzeniami twoimi i odbiorców. Nawet twój dostawca poczty e-mail lub Internetu nie będzie w stanie przeczytać ani zmodyfikować twoich wiadomości.</p>
|
||||
|
||||
<h3 id="message-metadata">
|
||||
|
||||
|
||||
W jaki sposób ArcaneChat chroni metadane w wiadomościach? <a href="#message-metadata" class="anchor"></a>
|
||||
W jaki sposób Delta Chat chroni metadane w wiadomościach? <a href="#message-metadata" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>ArcaneChat chroni większość metadanych wiadomości, umieszczając następujące informacje w całkowicie zaszyfrowanej części wiadomości:</p>
|
||||
<p>Delta Chat chroni większość metadanych wiadomości, umieszczając następujące informacje w całkowicie zaszyfrowanej części wiadomości:</p>
|
||||
|
||||
<ul>
|
||||
<li>Wiersz tematu</li>
|
||||
@@ -742,7 +742,7 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Zarówno w celu ochrony przed serwerami poczty e-mail gromadzącymi metadane, jak i przed zagrożeniem przejęcia urządzenia, zalecamy użycie zoptymalizowanej <a href="https://delta.chat/pl/serverguide">instancji serwera poczty e-mail</a> ArcaneChat w celu tworzenia pseudonimowych kont tymczasowych poprzez skanowanie kodów QR. Pamiętaj, że aplikacje ArcaneChat na wszystkich platformach obsługują wiele kont, dzięki czemu możesz z łatwością korzystać z kont „1-tygodniowych” lub „1-miesięcznych” związanych z konkretnymi działaniami obok konta „głównego”, wiedząc, że wszystkie tymczasowe dane konta wraz ze wszystkimi metadanymi zostaną usunięte. Co więcej, jeśli urządzenie zostanie przejęte, nie będzie można łatwo zidentyfikować kontaktów korzystających z tymczasowych kont e-mail, w porównaniu z komunikatorami, które ujawniają numery telefonów w grupach czatów, które z kolei często są powiązane z tożsamością prawną.</p>
|
||||
<p>Zarówno w celu ochrony przed serwerami poczty e-mail gromadzącymi metadane, jak i przed zagrożeniem przejęcia urządzenia, zalecamy użycie zoptymalizowanej <a href="https://delta.chat/pl/serverguide">instancji serwera poczty e-mail</a> Delta Chat w celu tworzenia pseudonimowych kont tymczasowych poprzez skanowanie kodów QR. Pamiętaj, że aplikacje Delta Chat na wszystkich platformach obsługują wiele kont, dzięki czemu możesz z łatwością korzystać z kont „1-tygodniowych” lub „1-miesięcznych” związanych z konkretnymi działaniami obok konta „głównego”, wiedząc, że wszystkie tymczasowe dane konta wraz ze wszystkimi metadanymi zostaną usunięte. Co więcej, jeśli urządzenie zostanie przejęte, nie będzie można łatwo zidentyfikować kontaktów korzystających z tymczasowych kont e-mail, w porównaniu z komunikatorami, które ujawniają numery telefonów w grupach czatów, które z kolei często są powiązane z tożsamością prawną.</p>
|
||||
|
||||
<h3 id="jak-mogę-sprawdzić-informacje-o-szyfrowaniu">
|
||||
|
||||
@@ -752,7 +752,7 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Możesz sprawdzić stan szyfrowania end-to-end ręcznie w oknie dialogowym „Szyfrowanie” (profil użytkownika w systemie Android/iOS lub kliknij prawym przyciskiem myszy element listy czatu użytkownika na komputerze). ArcaneChat pokazuje tam dwa odciski palców. Jeśli te same odciski palców pojawią się u ciebie i urządzeniu twojego kontaktu, połączenie jest bezpieczne.</p>
|
||||
<p>Możesz sprawdzić stan szyfrowania end-to-end ręcznie w oknie dialogowym „Szyfrowanie” (profil użytkownika w systemie Android/iOS lub kliknij prawym przyciskiem myszy element listy czatu użytkownika na komputerze). Delta Chat pokazuje tam dwa odciski palców. Jeśli te same odciski palców pojawią się u ciebie i urządzeniu twojego kontaktu, połączenie jest bezpieczne.</p>
|
||||
|
||||
<h3 id="jak-mogę-sprawdzić-stan-szyfrowania-wiadomości">
|
||||
|
||||
@@ -772,17 +772,17 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Jeśli kontakt korzysta z aplikacji e-mail bez Autocrypt, wszystkie wiadomości od tego kontaktu (w czacie grupowym lub 1:1) nie będą w pełni szyfrowane, w związku z czym nie będą wyświetlane z „kłódką” przy wiadomościach. Pamiętaj, że nawet jeśli twoje kontakty korzystają z ArcaneChat na swoim koncie, mogą również używać na tym koncie aplikacji e-mail bez Autocrypt, co może powodować sporadyczne wysyłanie niezaszyfrowanych wiadomości. Odpowiadanie niezaszyfrowanych wiadomości na niezaszyfrowane wiadomości jest wymagane przez funkcję Autocrypt, aby zapobiec nieczytelnym wiadomościom po stronie twoich kontaktów i ich aplikacji e-mail bez Autocrypt.</p>
|
||||
<p>Jeśli kontakt korzysta z aplikacji e-mail bez Autocrypt, wszystkie wiadomości od tego kontaktu (w czacie grupowym lub 1:1) nie będą w pełni szyfrowane, w związku z czym nie będą wyświetlane z „kłódką” przy wiadomościach. Pamiętaj, że nawet jeśli twoje kontakty korzystają z Delta Chat na swoim koncie, mogą również używać na tym koncie aplikacji e-mail bez Autocrypt, co może powodować sporadyczne wysyłanie niezaszyfrowanych wiadomości. Odpowiadanie niezaszyfrowanych wiadomości na niezaszyfrowane wiadomości jest wymagane przez funkcję Autocrypt, aby zapobiec nieczytelnym wiadomościom po stronie twoich kontaktów i ich aplikacji e-mail bez Autocrypt.</p>
|
||||
|
||||
<h3 id="jak-mogę-uzyskać-zaszyfrowany-ened-to-end-czat-z-kontaktem-delta-chat-który-czasami-korzysta-z-poczty-internetowej-lub-innej-aplikacji-e-mail-bez-autocrypt">
|
||||
|
||||
|
||||
Jak mogę uzyskać zaszyfrowany ened-to-end czat z kontaktem ArcaneChat, który czasami korzysta z poczty internetowej lub innej aplikacji e-mail bez Autocrypt? <a href="#jak-mogę-uzyskać-zaszyfrowany-ened-to-end-czat-z-kontaktem-delta-chat-który-czasami-korzysta-z-poczty-internetowej-lub-innej-aplikacji-e-mail-bez-autocrypt" class="anchor"></a>
|
||||
Jak mogę uzyskać zaszyfrowany ened-to-end czat z kontaktem Delta Chat, który czasami korzysta z poczty internetowej lub innej aplikacji e-mail bez Autocrypt? <a href="#jak-mogę-uzyskać-zaszyfrowany-ened-to-end-czat-z-kontaktem-delta-chat-który-czasami-korzysta-z-poczty-internetowej-lub-innej-aplikacji-e-mail-bez-autocrypt" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Jeśli potrzebujesz bezpiecznie, kompleksowo zaszyfrowanego czatu z kontaktem, który korzysta ze swojego konta zarówno w ArcaneChat, jak i w aplikacjach bez Autocrypt (np. poczta internetowa), najlepiej skonfigurować z nim gwarantowane szyfrowanie typu end-to-end, a następnie utworzyć <a href="#howtoe2ee">gwarantowany zaszyfrowany end-to-end</a> czat grupowy z wami dwoma jako członkami. W tym czacie grupowym wszystkie wiadomości będą w pełni szyfrowane, nawet jeśli bezpośredni czat między wami zawiera ostrzeżenie <a href="#nocryptanymore">„…wysłano wiadomość z innego urządzenia”</a>.</p>
|
||||
<p>Jeśli potrzebujesz bezpiecznie, kompleksowo zaszyfrowanego czatu z kontaktem, który korzysta ze swojego konta zarówno w Delta Chat, jak i w aplikacjach bez Autocrypt (np. poczta internetowa), najlepiej skonfigurować z nim gwarantowane szyfrowanie typu end-to-end, a następnie utworzyć <a href="#howtoe2ee">gwarantowany zaszyfrowany end-to-end</a> czat grupowy z wami dwoma jako członkami. W tym czacie grupowym wszystkie wiadomości będą w pełni szyfrowane, nawet jeśli bezpośredni czat między wami zawiera ostrzeżenie <a href="#nocryptanymore">„…wysłano wiadomość z innego urządzenia”</a>.</p>
|
||||
|
||||
<h3 id="jak-mogę-zapewnić-kompleksowe-szyfrowanie-i-usuwanie-wiadomości">
|
||||
|
||||
@@ -801,33 +801,33 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
|
||||
<h3 id="pfs">
|
||||
|
||||
|
||||
Czy ArcaneChat obsługuje funkcję Perfect Forward Secrecy? <a href="#pfs" class="anchor"></a>
|
||||
Czy Delta Chat obsługuje funkcję Perfect Forward Secrecy? <a href="#pfs" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Nie, ArcaneChat nie obsługuje funkcji Perfect Forward Secrecy (PFS). Oznacza to, że jeśli twój prywatny klucz deszyfrujący ArcaneChat wycieknie i ktoś zdobędzie twoje wcześniejsze wiadomości w trakcie przesyłania, będzie mógł je odszyfrować i odczytać przy użyciu ujawnionego klucza deszyfrowania.</p>
|
||||
<p>Nie, Delta Chat nie obsługuje funkcji Perfect Forward Secrecy (PFS). Oznacza to, że jeśli twój prywatny klucz deszyfrujący Delta Chat wycieknie i ktoś zdobędzie twoje wcześniejsze wiadomości w trakcie przesyłania, będzie mógł je odszyfrować i odczytać przy użyciu ujawnionego klucza deszyfrowania.</p>
|
||||
|
||||
<p>Należy jednak pamiętać, że jeśli ktoś zdobędzie twoje klucze deszyfrujące, zazwyczaj będzie mógł również uzyskać twoje wiadomości, niezależnie od tego, czy obowiązuje zasada Perfect Forward Secrecy, czy nie. Typową sytuacją w świecie rzeczywistym w przypadku wycieku kluczy deszyfrujących jest przejęcie urządzenia, które omawiamy w naszej odpowiedzi na temat <a href="#device-seizure">przejęcia metadanych i urządzenia</a>.</p>
|
||||
|
||||
<p>Możliwe, że ArcaneChat ewoluuje, aby wspierać Perfect Forward Secrecy, ponieważ OpenPGP to tylko kontener na zaszyfrowane wiadomości, ale zarządzanie kluczami szyfrowania (a tym samym rotacja kluczy lub „zapadanie kluczy”) mogłoby być zorganizowane w elastyczny sposób. Zobacz <a href="https://gitlab.com/sequoia-pgp/openpgp-dr">prototyp PFS firmy Seqouia</a>, aby zapoznać się z istniejącymi eksperymentami w społeczności implementatorów OpenPGP.</p>
|
||||
<p>Możliwe, że Delta Chat ewoluuje, aby wspierać Perfect Forward Secrecy, ponieważ OpenPGP to tylko kontener na zaszyfrowane wiadomości, ale zarządzanie kluczami szyfrowania (a tym samym rotacja kluczy lub „zapadanie kluczy”) mogłoby być zorganizowane w elastyczny sposób. Zobacz <a href="https://gitlab.com/sequoia-pgp/openpgp-dr">prototyp PFS firmy Seqouia</a>, aby zapoznać się z istniejącymi eksperymentami w społeczności implementatorów OpenPGP.</p>
|
||||
|
||||
<h3 id="czy-szyfrowanie-end-to-end-delta-chat-jest-tak-samo-bezpieczne-jak-signal">
|
||||
|
||||
|
||||
Czy szyfrowanie end-to-end ArcaneChat jest tak samo bezpieczne jak Signal? <a href="#czy-szyfrowanie-end-to-end-delta-chat-jest-tak-samo-bezpieczne-jak-signal" class="anchor"></a>
|
||||
Czy szyfrowanie end-to-end Delta Chat jest tak samo bezpieczne jak Signal? <a href="#czy-szyfrowanie-end-to-end-delta-chat-jest-tak-samo-bezpieczne-jak-signal" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>To zależy od tego, co jest dla ciebie ważne. ArcaneChat <a href="#pfs">nie obsługuje PFS</a> tak jak Signal, ale zapewnia <a href="#e2eeguarantee">gwarantowane szyfrowane end-to-end czatów</a>, które jest zabezpieczeniem przed zaatakowanymi serwerami lub uszkodzonymi sieciami. Signal i większość innych komunikatorów obsługujących PFS nie zapewniają praktycznego schematu ochrony czatów grupowych przed atakami sieciowymi, które są prawdopodobnie bardziej niepokojące niż potencjalny atakujący, który przejmuje twój telefon i prywatne ustawienia szyfrowania i w ten sposób nie twoje wiadomości i mimo to ma pełny zapis wszystkich poprzednio zaszyfrowanych wiadomości.</p>
|
||||
<p>To zależy od tego, co jest dla ciebie ważne. Delta Chat <a href="#pfs">nie obsługuje PFS</a> tak jak Signal, ale zapewnia <a href="#e2eeguarantee">gwarantowane szyfrowane end-to-end czatów</a>, które jest zabezpieczeniem przed zaatakowanymi serwerami lub uszkodzonymi sieciami. Signal i większość innych komunikatorów obsługujących PFS nie zapewniają praktycznego schematu ochrony czatów grupowych przed atakami sieciowymi, które są prawdopodobnie bardziej niepokojące niż potencjalny atakujący, który przejmuje twój telefon i prywatne ustawienia szyfrowania i w ten sposób nie twoje wiadomości i mimo to ma pełny zapis wszystkich poprzednio zaszyfrowanych wiadomości.</p>
|
||||
|
||||
<p>W każdym razie szyfrowanie end-to-end ArcaneChat wykorzystuje <a href="#openpgp-secure">bezpieczny podzbiór OpenPGP</a>, który został poddany <a href="https://delta.chat/assets/blog/2019-first-security-review.pdf">niezależnemu audytowi bezpieczeństwa</a>.</p>
|
||||
<p>W każdym razie szyfrowanie end-to-end Delta Chat wykorzystuje <a href="#openpgp-secure">bezpieczny podzbiór OpenPGP</a>, który został poddany <a href="https://delta.chat/assets/blog/2019-first-security-review.pdf">niezależnemu audytowi bezpieczeństwa</a>.</p>
|
||||
|
||||
<h3 id="czy-mogę-ponownie-wykorzystać-mój-istniejący-klucz-prywatny">
|
||||
<h3 id="importkey">
|
||||
|
||||
|
||||
Czy mogę ponownie wykorzystać mój istniejący klucz prywatny? <a href="#czy-mogę-ponownie-wykorzystać-mój-istniejący-klucz-prywatny" class="anchor"></a>
|
||||
Czy mogę ponownie wykorzystać mój istniejący klucz prywatny? <a href="#importkey" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -838,22 +838,22 @@ Look for something like <strong>Start Autocrypt Setup Transfer</strong> in the s
|
||||
|
||||
<p>Alternatywnie możesz zaimportować klucz ręcznie w „Ustawienia » Zaawansowane » Importuj tajne klucze”. Uwaga: Upewnij się, że klucz nie jest chroniony hasłem lub wcześniej usuń hasło.</p>
|
||||
|
||||
<p>Jeśli nie masz klucza lub nawet nie wiesz, że go potrzebujesz nie przejmuj się: ArcaneChat generuje go w razie potrzeby, nie trzeba naciskać przycisku, aby to zrobić.</p>
|
||||
<p>Jeśli nie masz klucza lub nawet nie wiesz, że go potrzebujesz nie przejmuj się: Delta Chat generuje go w razie potrzeby, nie trzeba naciskać przycisku, aby to zrobić.</p>
|
||||
|
||||
<h3 id="nie-mogę-zaimportować-istniejącego-klucza-pgp-do-delta-chat">
|
||||
|
||||
|
||||
Nie mogę zaimportować istniejącego klucza PGP do ArcaneChat. <a href="#nie-mogę-zaimportować-istniejącego-klucza-pgp-do-delta-chat" class="anchor"></a>
|
||||
Nie mogę zaimportować istniejącego klucza PGP do Delta Chat. <a href="#nie-mogę-zaimportować-istniejącego-klucza-pgp-do-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Jest wielce prawdopodobne, że problemem jest klucz, który jest zaszyfrowany i/lub używa hasła. Takie klucze nie są obsługiwane przez ArcaneChat. Usuń szyfrowanie i hasło i spróbować ponownie zaimportować klucz.</p>
|
||||
<p>Jest wielce prawdopodobne, że problemem jest klucz, który jest zaszyfrowany i/lub używa hasła. Takie klucze nie są obsługiwane przez Delta Chat. Usuń szyfrowanie i hasło i spróbować ponownie zaimportować klucz.</p>
|
||||
|
||||
<p>Innym częstym błędem jest nieprawidłowe zakończenie pliku.
|
||||
Użyj opancerzonego formatu ASCII i końcówki pliku <code class="language-plaintext highlighter-rouge">.asc</code>.</p>
|
||||
|
||||
<p>Rozsądny format, ArcaneChat obsługuje popularne formaty kluczy prywatnych OpenPGP, jednak jest mało prawdopodobne, że będziemy obsługiwać 100% wszystkich kluczy prywatnych z dowolnych źródeł. To również nie jest głównym celem ArcaneChat (w rzeczywistości, znaczna większość użytkowników ArcaneChat nie będzie miała żadnego klucza przed rozpoczęciem korzystania z Delta). Jednak staramy się wspierać klucze prywatne z innych źródeł tak dobrze jak to tylko możliwe.</p>
|
||||
<p>Rozsądny format, Delta Chat obsługuje popularne formaty kluczy prywatnych OpenPGP, jednak jest mało prawdopodobne, że będziemy obsługiwać 100% wszystkich kluczy prywatnych z dowolnych źródeł. To również nie jest głównym celem Delta Chat (w rzeczywistości, znaczna większość użytkowników Delta Chat nie będzie miała żadnego klucza przed rozpoczęciem korzystania z Delta). Jednak staramy się wspierać klucze prywatne z innych źródeł tak dobrze jak to tylko możliwe.</p>
|
||||
|
||||
<p>Usunięcie hasła z klucza prywatnego będzie się różnić w zależności od
|
||||
oprogramowania używanego do zarządzania kluczami PGP. Za pomocą programu Enigmail można ustawić
|
||||
@@ -863,28 +863,44 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
<h3 id="security-audits">
|
||||
|
||||
|
||||
Czy ArcaneChat był niezależnie kontrolowany pod kątem luk w zabezpieczeniach? <a href="#security-audits" class="anchor"></a>
|
||||
Czy Delta Chat był niezależnie kontrolowany pod kątem luk w zabezpieczeniach? <a href="#security-audits" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Projekt ArcaneChat przeszedł cztery niezależne audyty bezpieczeństwa i jedną niezależną analizę bezpieczeństwa, od najnowszego do najstarszego:</p>
|
||||
<p>Yes, multiple times.
|
||||
The Delta Chat project continuously undergoes independent security audits and analysis,
|
||||
from most recent to older:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>W marcu 2024 r. otrzymaliśmy dogłębną analizę bezpieczeństwa od grupy badawczej ds. kryptografii stosowanej w ETH Zuerich i zajęliśmy się wszystkimi poruszonymi kwestiami. Więcej szczegółowych informacji można znaleźć na naszym blogu na temat <a href="https://delta.chat/en/2024-03-25-crypto-analysis-securejoin">szyfrowania typu End-to-End z gwarancją Hardening</a> oraz opublikowanym później artykule badawczym <a href="https://eprint.iacr.org/2024/918.pdf">Cryptographic Analysis of ArcaneChat</a>.</p>
|
||||
<p>2024 December, an <a href="https://github.com/rpgp/docs/blob/main/audits/NGI%20Core%20rPGP%20penetration%20test%20report%202024%201.0.pdf">NLNET-commissioned Evaluation of
|
||||
rPGP</a> by <a href="https://www.radicallyopensecurity.com/">Radically Open Security</a> took place.
|
||||
rPGP serves as the end-to-end encyption <a href="https://openpgp.org">OpenPGP</a> engine of Delta Chat.
|
||||
Two advisories were released related to the findings of this audit:</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://github.com/rpgp/rpgp/security/advisories/GHSA-9rmp-2568-59rv">“Panics on Malformed Untrusted Input”</a> CVE-2024-53856</li>
|
||||
<li><a href="https://github.com/rpgp/rpgp/security/advisories/GHSA-4grw-m28r-q285">“Potential Resource Exhaustion when handling Untrusted Messages”</a> CVE-2024-53857</li>
|
||||
</ul>
|
||||
|
||||
<p>The issues outlined in these advisories have been fixed and are part of Delta Chat
|
||||
releases on all appstores since December 2024.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>W marcu 2024 r. otrzymaliśmy dogłębną analizę bezpieczeństwa od grupy badawczej ds. kryptografii stosowanej w ETH Zuerich i zajęliśmy się wszystkimi poruszonymi kwestiami. Więcej szczegółowych informacji można znaleźć na naszym blogu na temat <a href="https://delta.chat/en/2024-03-25-crypto-analysis-securejoin">szyfrowania typu End-to-End z gwarancją Hardening</a> oraz opublikowanym później artykule badawczym <a href="https://eprint.iacr.org/2024/918.pdf">Cryptographic Analysis of Delta Chat</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>W kwietniu 2023 r. naprawiliśmy problemy z bezpieczeństwem i prywatnością w funkcji „aplikacje internetowe udostępniane na czacie”, związane z awariami piaskownicy, szczególnie w przypadku Chromium. Następnie przeprowadziliśmy niezależny audyt bezpieczeństwa od Cure53 i wszystkie wykryte problemy zostały naprawione w aplikacji z serii 1.36 wydanej w kwietniu 2023 r. <a href="https://delta.chat/en/2023-05-22-webxdc-security">Pełną historię bezpieczeństwa end-to-end w sieci można znaleźć tutaj</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>W marcu 2023 r. firma <a href="https://cure53.de">Cure53</a> przeanalizowała zarówno szyfrowanie transportu połączeń sieciowych ArcaneChat, jak i powtarzalną konfigurację serwera pocztowego zgodnie z <a href="https://delta.chat/pl/serverguide">zaleceniami na tej stronie</a>. Możesz przeczytać więcej o audycie <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">na naszym blogu</a> lub przeczytać pełny raport <a href="https://delta.chat/assets/blog/MER-01-report.pdf">tutaj</a>.</p>
|
||||
<p>W marcu 2023 r. firma <a href="https://cure53.de">Cure53</a> przeanalizowała zarówno szyfrowanie transportu połączeń sieciowych Delta Chat, jak i powtarzalną konfigurację serwera pocztowego zgodnie z <a href="https://delta.chat/pl/serverguide">zaleceniami na tej stronie</a>. Możesz przeczytać więcej o audycie <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">na naszym blogu</a> lub przeczytać pełny raport <a href="https://delta.chat/assets/blog/MER-01-report.pdf">tutaj</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>W 2020 r. firma <a href="https://includesecurity.com">Include Security</a> przeanalizowała biblioteki Rust <a href="https://github.com/deltachat/deltachat-core-rust/">core</a>, <a href="https://github.com/async-email/async-imap">IMAP</a>, <a href="https://github.com/async-email/async-smtp">SMTP</a> i <a href="https://github.com/async-email/async-native-tls">TLS</a> ArcaneChat. Nie znalazła żadnych problemów krytycznych ani poważnych. W raporcie zwrócono uwagę na kilka słabych punktów o średniej wadze – same w sobie nie stanowią zagrożenia dla użytkowników ArcaneChat, ponieważ zależą od środowiska, w którym używany jest ArcaneChat. Ze względu na użyteczność i kompatybilność nie możemy złagodzić wszystkich z nich i zdecydowaliśmy się przedstawić zalecenia dotyczące bezpieczeństwa zagrożonym użytkownikom. Pełny raport można przeczytać <a href="https://delta.chat/assets/blog/2020-second-security-review.pdf">tutaj</a>.</p>
|
||||
<p>W 2020 r. firma <a href="https://includesecurity.com">Include Security</a> przeanalizowała biblioteki Rust <a href="https://github.com/deltachat/deltachat-core-rust/">core</a>, <a href="https://github.com/async-email/async-imap">IMAP</a>, <a href="https://github.com/async-email/async-smtp">SMTP</a> i <a href="https://github.com/async-email/async-native-tls">TLS</a> Delta Chat. Nie znalazła żadnych problemów krytycznych ani poważnych. W raporcie zwrócono uwagę na kilka słabych punktów o średniej wadze – same w sobie nie stanowią zagrożenia dla użytkowników Delta Chat, ponieważ zależą od środowiska, w którym używany jest Delta Chat. Ze względu na użyteczność i kompatybilność nie możemy złagodzić wszystkich z nich i zdecydowaliśmy się przedstawić zalecenia dotyczące bezpieczeństwa zagrożonym użytkownikom. Pełny raport można przeczytać <a href="https://delta.chat/assets/blog/2020-second-security-review.pdf">tutaj</a>.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>W 2019 r. firma <a href="https://includesecurity.com">Include Security</a> przeanalizowała biblioteki <a href="https://github.com/rpgp/rpgp">PGP</a> i <a href="https://github.com/RustCrypto/RSA">RSA</a> ArcaneChat. Nie znaleziono żadnych krytycznych problemów, ale dwa poważne problemy, które później naprawiliśmy. Ujawniła również jeden problem o średniej wadze i kilka mniej poważnych, ale nie było możliwości wykorzystania tych luk w implementacji ArcaneChat. Niektóre z nich jednak naprawiliśmy od czasu zakończenia kontroli. Pełny raport można przeczytać <a href="https://delta.chat/assets/blog/2019-first-security-review.pdf">tutaj</a>.</p>
|
||||
<p>W 2019 r. firma <a href="https://includesecurity.com">Include Security</a> przeanalizowała biblioteki <a href="https://github.com/rpgp/rpgp">PGP</a> i <a href="https://github.com/RustCrypto/RSA">RSA</a> Delta Chat. Nie znaleziono żadnych krytycznych problemów, ale dwa poważne problemy, które później naprawiliśmy. Ujawniła również jeden problem o średniej wadze i kilka mniej poważnych, ale nie było możliwości wykorzystania tych luk w implementacji Delta Chat. Niektóre z nich jednak naprawiliśmy od czasu zakończenia kontroli. Pełny raport można przeczytać <a href="https://delta.chat/assets/blog/2019-first-security-review.pdf">tutaj</a>.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -899,12 +915,12 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
<h3 id="czy-mogę-korzystać-z-delta-chat-na-wielu-urządzeniach-w-tym-samym-czasie">
|
||||
|
||||
|
||||
Czy mogę korzystać z ArcaneChat na wielu urządzeniach w tym samym czasie? <a href="#czy-mogę-korzystać-z-delta-chat-na-wielu-urządzeniach-w-tym-samym-czasie" class="anchor"></a>
|
||||
Czy mogę korzystać z Delta Chat na wielu urządzeniach w tym samym czasie? <a href="#czy-mogę-korzystać-z-delta-chat-na-wielu-urządzeniach-w-tym-samym-czasie" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Tak. ArcaneChat 1.36 comes with a new, experimental function for using the same profile on different devices:</p>
|
||||
<p>Tak. Delta Chat 1.36 comes with a new, experimental function for using the same profile on different devices:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
@@ -914,10 +930,10 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
<p>Na pierwszym urządzeniu przejdź do <strong>Ustawienia → Dodaj kolejne urządzenie</strong>, w razie potrzeby odblokuj ekran i poczekaj chwilę, aż pojawi się kod QR</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Na drugim urządzeniu <a href="https://get.delta.chat">zainstaluj ArcaneChat</a></p>
|
||||
<p>Na drugim urządzeniu <a href="https://get.delta.chat">zainstaluj Delta Chat</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Na drugim urządzeniu uruchom ArcaneChat, wybierz <strong>Dodaj jako kolejne urządzenie</strong> i zeskanuj kod QR z pierwszego urządzenia</p>
|
||||
<p>Na drugim urządzeniu uruchom Delta Chat, wybierz <strong>Dodaj jako kolejne urządzenie</strong> i zeskanuj kod QR z pierwszego urządzenia</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -941,9 +957,15 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
<p>Na <strong>Windowsie</strong>, przejdź do <strong>Panel sterowania / Sieć i internet</strong> i upewnij się, że <strong>Sieć prywatna</strong> jest wybrana jako “Typ profilu sieci”
|
||||
(po przeniesieniu możesz wrócić do pierwotnej wartości)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>W systemie <strong>iOS</strong> upewnij się, że jest przydzielony dostęp do opcji „Ustawienia » Aplikacje » Delta Chat » <strong>Sieć lokalna</strong>”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>W systemie <strong>macOS</strong> włącz „Preferencje systemowe » Ochrona i prywatność » <strong>Sieć lokalna</strong> » Delta Chat”</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Twój system może mieć „zaporę ogniową”, o której wiadomo, że powoduje problemy (szczególnie w systemie Windows).
|
||||
<strong>Wyłącz zaporę</strong> dla ArcaneChat po obu stronach i spróbuj ponownie</p>
|
||||
<strong>Wyłącz zaporę</strong> dla Delta Chat po obu stronach i spróbuj ponownie</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Sieci dla gości</strong> mogą nie pozwalać urządzeniom na komunikację między sobą. Jeśli to możliwe, korzystaj z sieci innej niż gość.</p>
|
||||
@@ -952,10 +974,10 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
<p>Upewnij się, że na urządzeniu docelowym jest <strong>wystarczająca ilość miejsca</strong></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Jeśli przenoszenie się rozpoczęło, upewnij się, że urządzenia <strong>pozostają aktywne</strong> i nie zasypiają. Nie wychodź z ArcaneChat. (dokładamy wszelkich starań, aby aplikacja działała w tle, ale <a href="https://dontkillmyapp.com">systemy mają tendencję do ubijania aplikacji</a>, niestety)</p>
|
||||
<p>Jeśli przenoszenie się rozpoczęło, upewnij się, że urządzenia <strong>pozostają aktywne</strong> i nie zasypiają. Nie wychodź z Delta Chat. (dokładamy wszelkich starań, aby aplikacja działała w tle, ale <a href="https://dontkillmyapp.com">systemy mają tendencję do ubijania aplikacji</a>, niestety)</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>ArcaneChat jest już zalogowany na urządzeniu docelowym? Możesz używać wielu kont na urządzeniu, po prostu <a href="#multiple-accounts">dodaj kolejne konto</a></p>
|
||||
<p>Delta Chat jest już zalogowany na urządzeniu docelowym? Możesz używać wielu kont na urządzeniu, po prostu <a href="#multiple-accounts">dodaj kolejne konto</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Jeśli nadal masz problemy lub <strong>nie możesz zeskanować kodu QR</strong>, wypróbuj <strong>ręczne przenoszenie</strong> opisane poniżej</p>
|
||||
@@ -985,14 +1007,14 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
<h3 id="czy-są-jakieś-plany-wprowadzenia-klienta-web-delta-chat">
|
||||
|
||||
|
||||
Czy są jakieś plany wprowadzenia klienta Web ArcaneChat? <a href="#czy-są-jakieś-plany-wprowadzenia-klienta-web-delta-chat" class="anchor"></a>
|
||||
Czy są jakieś plany wprowadzenia klienta Web Delta Chat? <a href="#czy-są-jakieś-plany-wprowadzenia-klienta-web-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Nie ma bezpośrednich planów, ale wstępne przemyślenia.</li>
|
||||
<li>Istnieją 2-3 możliwości wprowadzenia klienta Web ArcaneChat, ale wszystkie wymagają znaczącej pracy. Na razie skupiamy się na udostępnianiu stabilnych wersji we wszystkich sklepach z aplikacjami (repozytoria Google Play/iOS/Windows/macOS/Linux) jako aplikacji natywnych.</li>
|
||||
<li>Istnieją 2-3 możliwości wprowadzenia klienta Web Delta Chat, ale wszystkie wymagają znaczącej pracy. Na razie skupiamy się na udostępnianiu stabilnych wersji we wszystkich sklepach z aplikacjami (repozytoria Google Play/iOS/Windows/macOS/Linux) jako aplikacji natywnych.</li>
|
||||
<li>Jeśli potrzebujesz klienta Web, ponieważ nie możesz instalować oprogramowania na komputerze, na którym pracujesz, możesz użyć przenośnego klienta Windows Desktop lub AppImage dla Linuxa. Możesz je znaleźć na <a href="https://get.delta.chat">get.delta.chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
@@ -1004,7 +1026,7 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
|
||||
</h2>
|
||||
|
||||
<p>W ArcaneChat możesz udostępniać <a href="https://webxdc.org">aplikacje webxdc</a> i załączniki z rozszerzeniem pliku .xdc. Mogą robić bardzo różne rzeczy i uczynić ArcaneChat naprawdę rozszerzalnym komunikatorem.</p>
|
||||
<p>W Delta Chat możesz udostępniać <a href="https://webxdc.org">aplikacje webxdc</a> i załączniki z rozszerzeniem pliku .xdc. Mogą robić bardzo różne rzeczy i uczynić Delta Chat naprawdę rozszerzalnym komunikatorem.</p>
|
||||
|
||||
<h3 id="jak-prywatne-są-aplikacje-webxdc">
|
||||
|
||||
@@ -1016,7 +1038,7 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
|
||||
<ul>
|
||||
<li>Aplikacje webxdc nie mogą wysyłać danych do Internetu ani niczego pobierać.</li>
|
||||
<li>Aplikacja webxdc może wymieniać dane wyłącznie w ramach czatu ArcaneChat, a ich kopie znajdują się na urządzeniach twoich partnerów czatu. Poza tym jest całkowicie odizolowana od Internetu.</li>
|
||||
<li>Aplikacja webxdc może wymieniać dane wyłącznie w ramach czatu Delta Chat, a ich kopie znajdują się na urządzeniach twoich partnerów czatu. Poza tym jest całkowicie odizolowana od Internetu.</li>
|
||||
<li>Prywatność, jaką oferuje aplikacja webxdc, to prywatność twojego czatu – jeśli ufasz osobom, z którymi rozmawiasz, możesz ufać także aplikacji webxdc.</li>
|
||||
<li>Oznacza to również: otwieranie aplikacji webxdc na czatach, w przypadku których nie ufa się członkom, może stanowić ryzyko dla prywatności – tak jak załączniki do wiadomości e-mail, gdzie otwiera się tylko załączniki od nadawców, którym ufasz, a nie od spamerów.</li>
|
||||
</ul>
|
||||
@@ -1031,8 +1053,9 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
|
||||
<ul>
|
||||
<li>Ogólnie rzecz biorąc, każdy może udostępniać sobie aplikacje webxdc bez ograniczeń.</li>
|
||||
<li>Od <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
|
||||
<li>Możesz <a href="https://delta.chat/en/2023-08-11-xstore">wysłać „hi” na adres xstore@testrun.org</a>, aby zobaczyć eksperymentalny sklep z aplikacjami webxdc. Wszystkie aplikacje są otwarto źródłowe i są bezpłatne.</li>
|
||||
<li>Wiele osób pisze własne, aplikacje webxdc i publikuje je na <a href="https://support.delta.chat/c/webxdc/20">forum ArcaneChat</a>.</li>
|
||||
<li>Wiele osób pisze własne, aplikacje webxdc i publikuje je na <a href="https://support.delta.chat/c/webxdc/20">forum Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="jak-mogę-tworzyć-własne-aplikacje-webxdc">
|
||||
@@ -1047,7 +1070,7 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
<li>Aplikacje webxdc to po prostu pliki ZIP zawierające kod html, css i javascript.</li>
|
||||
<li>Aby rozpocząć, możesz rozszerzyć <a href="https://github.com/webxdc/hello">przykładową aplikację Hello World</a>.</li>
|
||||
<li>Wszystko, co musisz wiedzieć, jest napisane w <a href="https://docs.webxdc.org/">dokumentacji</a>.</li>
|
||||
<li>Jeśli masz pytania, możesz zadać je innym osobom z doświadczeniem na <a href="https://support.delta.chat/c/webxdc/20">forum ArcaneChat</a>.</li>
|
||||
<li>Jeśli masz pytania, możesz zadać je innym osobom z doświadczeniem na <a href="https://support.delta.chat/c/webxdc/20">forum Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="funkcje-eksperymentalne">
|
||||
@@ -1058,19 +1081,19 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
|
||||
</h2>
|
||||
|
||||
<p>Jesteśmy bardzo wdzięczni za opinie na temat tych funkcji — chcesz podzielić się swoimi pomysłami? Dołącz do <a href="https://support.delta.chat">forum</a>, aby wnieść swój wkład. Możesz wygodnie zalogować się za pośrednictwem ArcaneChat i skanowaniu kodu QR, co jest kolejnym dość stabilnym eksperymentem, który przeprowadzamy na boku (sic!).</p>
|
||||
<p>Jesteśmy bardzo wdzięczni za opinie na temat tych funkcji — chcesz podzielić się swoimi pomysłami? Dołącz do <a href="https://support.delta.chat">forum</a>, aby wnieść swój wkład. Możesz wygodnie zalogować się za pośrednictwem Delta Chat i skanowaniu kodu QR, co jest kolejnym dość stabilnym eksperymentem, który przeprowadzamy na boku (sic!).</p>
|
||||
|
||||
<h3 id="jak-mogę-korzystać-z-połączeń-audiowideo-z-delta-chat">
|
||||
|
||||
|
||||
Jak mogę korzystać z połączeń audio/wideo z ArcaneChat? <a href="#jak-mogę-korzystać-z-połączeń-audiowideo-z-delta-chat" class="anchor"></a>
|
||||
Jak mogę korzystać z połączeń audio/wideo z Delta Chat? <a href="#jak-mogę-korzystać-z-połączeń-audiowideo-z-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Aby włączyć połączenia audio/wideo, przejdź do sekcji „Funkcje eksperymentalne” w ustawieniach zaawansowanych i wybierz „Instancja czatu wideo”.</li>
|
||||
<li>Kiedy zapraszasz innych do czatu wideo, jest on od razu otwierany w Twojej przeglądarce/aplikacji. Inne osoby otrzymują e-mail z linkiem do twojego czatu wideo. W ten sposób jest to kompatybilne również wtedy, gdy partnerzy czatu nie używają ArcaneChat.</li>
|
||||
<li>Kiedy zapraszasz innych do czatu wideo, jest on od razu otwierany w Twojej przeglądarce/aplikacji. Inne osoby otrzymują e-mail z linkiem do twojego czatu wideo. W ten sposób jest to kompatybilne również wtedy, gdy partnerzy czatu nie używają Delta Chat.</li>
|
||||
<li>Zwróć uwagę, że po drugiej stronie nie ma dzwonka, a Twoim rozmówcom nie zostanie przerwana praca przez zaproszenie do czatu wideo.</li>
|
||||
<li>Możesz użyć dowolnej usługi czatu wideo, która pozwala na dołączenie przez link. Wystarczy dodać link w ustawieniach.</li>
|
||||
<li>Na przykład, aby użyć flagowej instancji Jitsi Meet, możesz wpisać https://meet.jit.si/$ROOM. Zmienna $ROOM będzie wartością losową; w ten sposób będziesz miał nowy losowy pokój jitsi za każdym razem, gdy do kogoś zadzwonisz.</li>
|
||||
@@ -1117,7 +1140,7 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
|
||||
</h3>
|
||||
|
||||
<p>To jest ustawienie eksperymentalne dla niektórych osób, które eksperymentują z regułami po stronie serwera. Nie wszyscy dostawcy to obsługują, ale w przypadku niektórych możesz przenieść wszystkie wiadomości z nagłówkiem „Chat-Version” do folderu DeltaChat. Zwykle byłoby to zrobione przez aplikację ArcaneChat.</p>
|
||||
<p>To jest ustawienie eksperymentalne dla niektórych osób, które eksperymentują z regułami po stronie serwera. Nie wszyscy dostawcy to obsługują, ale w przypadku niektórych możesz przenieść wszystkie wiadomości z nagłówkiem „Chat-Version” do folderu DeltaChat. Zwykle byłoby to zrobione przez aplikację Delta Chat.</p>
|
||||
|
||||
<p>Włączenie „Pobieraj tylko z folderu DeltaChat” ma sens, jeśli masz:</p>
|
||||
|
||||
@@ -1126,7 +1149,7 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
<li>ustawioną opcję „Pokaż klasyczne e-maile” na „Nie, tylko czaty”.</li>
|
||||
</ul>
|
||||
|
||||
<p>W tym przypadku ArcaneChat nie musi obserwować skrzynki odbiorczej, a wystarczy, że będzie obserwować tylko folder DeltaChat.</p>
|
||||
<p>W tym przypadku Delta Chat nie musi obserwować skrzynki odbiorczej, a wystarczy, że będzie obserwować tylko folder DeltaChat.</p>
|
||||
|
||||
<h3 id="jak-mogę-zmienić-moje-konto-na-inny-adres-e-mail">
|
||||
|
||||
@@ -1148,7 +1171,7 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<p>Pamiętaj, że ArcaneChat nie będzie już pobierać wiadomości od twojego starego dostawcy poczty e-mail. Jeśli nie skonfigurowałeś swojego dostawcy poczty e-mail do przekazywania wiadomości (krok 2.), tylko te kontakty, do których wysłałeś wiadomość w gwarantowanym szyfrowaniem end-to-end czacie, wyślą wiadomości na twój nowy adres.</p>
|
||||
<p>Pamiętaj, że Delta Chat nie będzie już pobierać wiadomości od twojego starego dostawcy poczty e-mail. Jeśli nie skonfigurowałeś swojego dostawcy poczty e-mail do przekazywania wiadomości (krok 2.), tylko te kontakty, do których wysłałeś wiadomość w gwarantowanym szyfrowaniem end-to-end czacie, wyślą wiadomości na twój nowy adres.</p>
|
||||
|
||||
<p>Aby dowiedzieć się więcej na ten temat, <a href="https://delta.chat/en/2022-09-14-aeap">przeczytaj nasz wpis na blogu na ten temat</a>.</p>
|
||||
|
||||
@@ -1163,14 +1186,14 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
|
||||
<h3 id="jakich-uprawnień-potrzebuje-delta-chat">
|
||||
|
||||
|
||||
Jakich uprawnień potrzebuje ArcaneChat? <a href="#jakich-uprawnień-potrzebuje-delta-chat" class="anchor"></a>
|
||||
Jakich uprawnień potrzebuje Delta Chat? <a href="#jakich-uprawnień-potrzebuje-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>W zależności od używanego systemu operacyjnego możesz
|
||||
zostać poproszony o przyznanie uprawnień aplikacji.
|
||||
Oto, co robi ArcaneChat z tymi uprawnieniami:</p>
|
||||
Oto, co robi Delta Chat z tymi uprawnieniami:</p>
|
||||
|
||||
<ul>
|
||||
<li>Aparat <em>(można zablokować)</em></li>
|
||||
@@ -1187,7 +1210,7 @@ Oto, co robi ArcaneChat z tymi uprawnieniami:</p>
|
||||
<li>czytanie zawartość twojej karty SD: aby udostępniać pliki swoim kontaktom</li>
|
||||
<li>Inne możliwości aplikacji</li>
|
||||
<li>zmiana ustawienia dźwięku: możesz wybrać dzwonki i głośność dla powiadomień i wiadomości audio</li>
|
||||
<li>uruchamianie przy starcie: więc nie musisz ręcznie uruchamiać ArcaneChat</li>
|
||||
<li>uruchamianie przy starcie: więc nie musisz ręcznie uruchamiać Delta Chat</li>
|
||||
<li>kontrola wibracji: do powiadomień</li>
|
||||
<li>przeglądanie połączenia sieciowych: aby połączyć się z dostawcą poczty e-mail</li>
|
||||
<li>zapobieganie uśpieniu telefonu: dzięki czemu możesz łatwiej skopiować kod zabezpieczający podczas komunikatu konfiguracyjnego Autocrypt</li>
|
||||
@@ -1199,7 +1222,7 @@ Oto, co robi ArcaneChat z tymi uprawnieniami:</p>
|
||||
<h3 id="czy-delta-chat-działa-z-moim-dostawcą-poczty-e-mail">
|
||||
|
||||
|
||||
Czy ArcaneChat działa z <em>moim</em> dostawcą poczty e-mail? <a href="#czy-delta-chat-działa-z-moim-dostawcą-poczty-e-mail" class="anchor"></a>
|
||||
Czy Delta Chat działa z <em>moim</em> dostawcą poczty e-mail? <a href="#czy-delta-chat-działa-z-moim-dostawcą-poczty-e-mail" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -1212,7 +1235,7 @@ Jednak niektórzy dostawcy potrzebują specjalnych opcji, aby działać poprawni
|
||||
<h3 id="chcę-zarządzać-własnym-serwerem-e-mail-dla-delta-chat-co-polecacie">
|
||||
|
||||
|
||||
Chcę zarządzać własnym serwerem e-mail dla ArcaneChat. Co polecacie? <a href="#chcę-zarządzać-własnym-serwerem-e-mail-dla-delta-chat-co-polecacie" class="anchor"></a>
|
||||
Chcę zarządzać własnym serwerem e-mail dla Delta Chat. Co polecacie? <a href="#chcę-zarządzać-własnym-serwerem-e-mail-dla-delta-chat-co-polecacie" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -1225,38 +1248,38 @@ Jednak niektórzy dostawcy potrzebują specjalnych opcji, aby działać poprawni
|
||||
<h3 id="dlaczego-muszę-wpisać-moje-hasło-e-mail-do-delta-chat-czy-to-jest-bezpieczne">
|
||||
|
||||
|
||||
Dlaczego muszę wpisać moje hasło e-mail do ArcaneChat? Czy to jest bezpieczne? <a href="#dlaczego-muszę-wpisać-moje-hasło-e-mail-do-delta-chat-czy-to-jest-bezpieczne" class="anchor"></a>
|
||||
Dlaczego muszę wpisać moje hasło e-mail do Delta Chat? Czy to jest bezpieczne? <a href="#dlaczego-muszę-wpisać-moje-hasło-e-mail-do-delta-chat-czy-to-jest-bezpieczne" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Podobnie jak w przypadku innych programów pocztowych, takich jak Thunderbird, K9-Mail lub Outlook, program potrzebuje hasła, aby można było go używać do wysyłania i odbierania e-maili. Oczywiście hasło jest przechowywane tylko na Twoim urządzeniu. Hasło jest przesyłane tylko do Twojego dostawcy poczty e-mail (po zalogowaniu), który i tak ma dostęp do Twojej poczty</p>
|
||||
|
||||
<p>Ponieważ ArcaneChat jest Open Source, możesz sprawdzić <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/src/login_param.rs">Kod źródłowy</a>
|
||||
<p>Ponieważ Delta Chat jest Open Source, możesz sprawdzić <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/src/login_param.rs">Kod źródłowy</a>
|
||||
jeśli chcesz sprawdzić, czy Twoje poświadczenia są przetwarzane w bezpieczny sposób. Cieszymy się z opinii, które sprawiają, że aplikacja jest bezpieczniejsza dla wszystkich naszych użytkowników.</p>
|
||||
|
||||
<h3 id="jakie-wiadomości-pojawiają-się-w-delta-chat">
|
||||
|
||||
|
||||
Jakie wiadomości pojawiają się w ArcaneChat? <a href="#jakie-wiadomości-pojawiają-się-w-delta-chat" class="anchor"></a>
|
||||
Jakie wiadomości pojawiają się w Delta Chat? <a href="#jakie-wiadomości-pojawiają-się-w-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Domyślnie ArcaneChat pokazuje wszystkie e-maile.</p>
|
||||
<p>Domyślnie Delta Chat pokazuje wszystkie e-maile.</p>
|
||||
|
||||
<p>Możesz to zmienić w „Ustawienia → Zaawansowane → Pokaż klasyczne e-maile”. Masz następujące opcje:</p>
|
||||
|
||||
<ul>
|
||||
<li>„Nie, tylko czaty”: Wyświetlane są tylko wiadomości wysłane przez innych użytkowników ArcaneChat i odpowiedzi na Twoje wiadomości ArcaneChat. Ma to największy sens, jeśli używasz tego samego konta e-mail również do wysyłania zwykłych wiadomości e-mail. To jest ustawienie domyślne.</li>
|
||||
<li>„Wszystkie”: ArcaneChat pokazuje wszystkie e-maile, które są wysyłane na Twój adres e-mail. Ma to sens, jeśli chcesz używać ArcaneChat do wszystkich swoich e-maili, więc żadna wiadomość nie zostanie utracona. To jest ustawienie domyślne.</li>
|
||||
<li>„Dla zaakceptowanych kontaktów”: ArcaneChat pokazuje wszystkie e-maile od kontaktów, z którymi już prowadzisz czat, ale nowe czaty pojawiają się tylko dla wiadomości ArcaneChat. Pomaga to zdecydować indywidualnie dla każdego przypadku, czy chcesz prowadzić rozmowę w ArcaneChat, czy w „normalnej” aplikacji e-mail.</li>
|
||||
<li>„Nie, tylko czaty”: Wyświetlane są tylko wiadomości wysłane przez innych użytkowników Delta Chat i odpowiedzi na Twoje wiadomości Delta Chat. Ma to największy sens, jeśli używasz tego samego konta e-mail również do wysyłania zwykłych wiadomości e-mail. To jest ustawienie domyślne.</li>
|
||||
<li>„Wszystkie”: Delta Chat pokazuje wszystkie e-maile, które są wysyłane na Twój adres e-mail. Ma to sens, jeśli chcesz używać Delta Chat do wszystkich swoich e-maili, więc żadna wiadomość nie zostanie utracona. To jest ustawienie domyślne.</li>
|
||||
<li>„Dla zaakceptowanych kontaktów”: Delta Chat pokazuje wszystkie e-maile od kontaktów, z którymi już prowadzisz czat, ale nowe czaty pojawiają się tylko dla wiadomości Delta Chat. Pomaga to zdecydować indywidualnie dla każdego przypadku, czy chcesz prowadzić rozmowę w Delta Chat, czy w „normalnej” aplikacji e-mail.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="czy-delta-chat-obsługuje-wiadomości-e-mail-w-formacie-html">
|
||||
|
||||
|
||||
Czy ArcaneChat obsługuje wiadomości e-mail w formacie HTML? <a href="#czy-delta-chat-obsługuje-wiadomości-e-mail-w-formacie-html" class="anchor"></a>
|
||||
Czy Delta Chat obsługuje wiadomości e-mail w formacie HTML? <a href="#czy-delta-chat-obsługuje-wiadomości-e-mail-w-formacie-html" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
@@ -1266,14 +1289,14 @@ jeśli chcesz sprawdzić, czy Twoje poświadczenia są przetwarzane w bezpieczny
|
||||
<h3 id="czy-w-delta-chat-mogę-ustawić-temat-wiadomości-e-mail">
|
||||
|
||||
|
||||
Czy w ArcaneChat mogę ustawić temat wiadomości e-mail? <a href="#czy-w-delta-chat-mogę-ustawić-temat-wiadomości-e-mail" class="anchor"></a>
|
||||
Czy w Delta Chat mogę ustawić temat wiadomości e-mail? <a href="#czy-w-delta-chat-mogę-ustawić-temat-wiadomości-e-mail" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>ArcaneChat automatycznie ustawia (i <a href="#message-metadata">szyfruje</a>!) klasyczny temat wiadomości e-mail na nazwę grupy lub nazwę nadawcy.</p>
|
||||
<p>Delta Chat automatycznie ustawia (i <a href="#message-metadata">szyfruje</a>!) klasyczny temat wiadomości e-mail na nazwę grupy lub nazwę nadawcy.</p>
|
||||
|
||||
<p>Jeśli więc chcesz samodzielnie ustawić temat, na przykład w przypadku oficjalnego e-maila do kontaktu biznesowego, możesz utworzyć grupę składającą się tylko z ciebie i odbiorców. Ustaw tytuł czatu na żądany temat, a następnie wyślij swój e-mail jako pierwszą wiadomość. Jeśli odbiorcy nie korzystają z ArcaneChat, będzie to dla nich wyglądać jak zwykły, formalny e-mail. Jeśli ustawisz <a href="#signature">tekst podpisu</a>, otrzymasz dodatkowe punkty profesjonalizmu.</p>
|
||||
<p>Jeśli więc chcesz samodzielnie ustawić temat, na przykład w przypadku oficjalnego e-maila do kontaktu biznesowego, możesz utworzyć grupę składającą się tylko z ciebie i odbiorców. Ustaw tytuł czatu na żądany temat, a następnie wyślij swój e-mail jako pierwszą wiadomość. Jeśli odbiorcy nie korzystają z Delta Chat, będzie to dla nich wyglądać jak zwykły, formalny e-mail. Jeśli ustawisz <a href="#signature">tekst podpisu</a>, otrzymasz dodatkowe punkty profesjonalizmu.</p>
|
||||
|
||||
<h3 id="do-czego-służy-ustawienie-wyślij-kopię-do-siebie">
|
||||
|
||||
@@ -1285,7 +1308,7 @@ jeśli chcesz sprawdzić, czy Twoje poświadczenia są przetwarzane w bezpieczny
|
||||
|
||||
<p>Wysłanie kopii wiadomości do siebie zapewnia otrzymywanie własnych wiadomości na wszystkich urządzeniach. Jeśli masz wiele urządzeń i jej nie włączysz, zobaczysz tylko wiadomości od innych osób oraz wiadomości, które wysyłasz z bieżącego urządzenia.</p>
|
||||
|
||||
<p>Kopia jest wysyłana do skrzynki odbiorczej, a następnie przenoszona do folderu DeltaChat; nie jest umieszczana w folderze „Wysłane”. ArcaneChat nigdy nie przesyła niczego do folderu Wysłane, ponieważ oznaczałoby to dwukrotne przesłanie wiadomości (raz przez SMTP i raz przez IMAP do folderu Wysłane).</p>
|
||||
<p>Kopia jest wysyłana do skrzynki odbiorczej, a następnie przenoszona do folderu DeltaChat; nie jest umieszczana w folderze „Wysłane”. Delta Chat nigdy nie przesyła niczego do folderu Wysłane, ponieważ oznaczałoby to dwukrotne przesłanie wiadomości (raz przez SMTP i raz przez IMAP do folderu Wysłane).</p>
|
||||
|
||||
<p>Domyślne ustawienie „Wyślij kopię do siebie” jest „włączone”.</p>
|
||||
|
||||
@@ -1297,9 +1320,9 @@ jeśli chcesz sprawdzić, czy Twoje poświadczenia są przetwarzane w bezpieczny
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Jedynym powodem, dla którego ktoś chce oglądać folder Wysłane, jest to, że używa innego programu pocztowego (takiego jak Thunderbird) razem z aplikacją ArcaneChat i chce, aby jego program pocztowy „uczestniczył” w rozmowach na czacie.</p>
|
||||
<p>Jedynym powodem, dla którego ktoś chce oglądać folder Wysłane, jest to, że używa innego programu pocztowego (takiego jak Thunderbird) razem z aplikacją Delta Chat i chce, aby jego program pocztowy „uczestniczył” w rozmowach na czacie.</p>
|
||||
|
||||
<p>Jednak zalecamy używanie klienta ArcaneChat Desktop; możesz go pobrać z <a href="https://get.delta.chat">get.delta.chat</a>. Opcja oglądania folderu „Wysłane” może w przyszłości zniknąć. Została wprowadzona w czasie, gdy na żadnej platformie nie był dostępny klient ArcaneChat Desktop.</p>
|
||||
<p>Jednak zalecamy używanie klienta Delta Chat Desktop; możesz go pobrać z <a href="https://get.delta.chat">get.delta.chat</a>. Opcja oglądania folderu „Wysłane” może w przyszłości zniknąć. Została wprowadzona w czasie, gdy na żadnej platformie nie był dostępny klient Delta Chat Desktop.</p>
|
||||
|
||||
<h3 id="dlaczego-mogę-nie-widzieć-folderu-deltachat">
|
||||
|
||||
@@ -1309,35 +1332,40 @@ jeśli chcesz sprawdzić, czy Twoje poświadczenia są przetwarzane w bezpieczny
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Niektórzy używają ArcaneChat jako zwykłego klienta poczty e-mail i chcą używać folderu Skrzynka odbiorcza dla swojej poczty zamiast folderu DeltaChat. Jeśli wyłączysz opcję „Oglądaj folder DeltaChat”, powinieneś również wyłączyć opcję „Automatyczne przenoszenie do folderu DeltaChat”. W przeciwnym razie usuwanie wiadomości lub konfiguracja wielu urządzeń może nie działać poprawnie.</p>
|
||||
<p>Niektórzy używają Delta Chat jako zwykłego klienta poczty e-mail i chcą używać folderu Skrzynka odbiorcza dla swojej poczty zamiast folderu DeltaChat. Jeśli wyłączysz opcję „Oglądaj folder DeltaChat”, powinieneś również wyłączyć opcję „Automatyczne przenoszenie do folderu DeltaChat”. W przeciwnym razie usuwanie wiadomości lub konfiguracja wielu urządzeń może nie działać poprawnie.</p>
|
||||
|
||||
<h3 id="czy-delta-chat-jest-kompatybilny-z-protonmail--tutanota--criptext">
|
||||
|
||||
|
||||
Czy ArcaneChat jest kompatybilny z Protonmail / Tutanota / Criptext? <a href="#czy-delta-chat-jest-kompatybilny-z-protonmail--tutanota--criptext" class="anchor"></a>
|
||||
Czy Delta Chat jest kompatybilny z Protonmail / Tutanota / Criptext? <a href="#czy-delta-chat-jest-kompatybilny-z-protonmail--tutanota--criptext" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>I tak i nie.</li>
|
||||
<li>Nie, nie możesz używać swojego konta Protonmail, Tutanota lub Criptext z ArcaneChat; nie oferują one odbierania poczty przez IMAP.</li>
|
||||
<li>W każdym przypadku możesz użyć ArcaneChat do wysyłania wiadomości do osób, które używają Protonmail, Tutanota lub Criptext. Te wiadomości nie będą jednak szyfrowane metodą end-to-end. Szyfrowanie typu end-to-end, które oferują ci dostawcy, nie jest kompatybilne z <a href="https://autocrypt.org/">Autocrypt</a> stosowanym standardowo w ArcaneChat.</li>
|
||||
<li>ArcaneChat może zaszyfrować metodą end-to-end za pośrednictwem dowolnego dostawcy poczty e-mail z dowolną <a href="https://autocrypt.org/dev-status.html">aplikacją e-mail z włączoną funkcją Autocrypt</a>.</li>
|
||||
<li>Nie, nie możesz używać swojego konta Protonmail, Tutanota lub Criptext z Delta Chat; nie oferują one odbierania poczty przez IMAP.</li>
|
||||
<li>W każdym przypadku możesz użyć Delta Chat do wysyłania wiadomości do osób, które używają Protonmail, Tutanota lub Criptext. Te wiadomości nie będą jednak szyfrowane metodą end-to-end. Szyfrowanie typu end-to-end, które oferują ci dostawcy, nie jest kompatybilne z <a href="https://autocrypt.org/">Autocrypt</a> stosowanym standardowo w Delta Chat.</li>
|
||||
<li>Delta Chat może zaszyfrować metodą end-to-end za pośrednictwem dowolnego dostawcy poczty e-mail z dowolną <a href="https://autocrypt.org/dev-status.html">aplikacją e-mail z włączoną funkcją Autocrypt</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="jak-mogę-usunąć-swoje-konto">
|
||||
<h3 id="remove-account">
|
||||
|
||||
|
||||
Jak mogę usunąć swoje konto? <a href="#jak-mogę-usunąć-swoje-konto" class="anchor"></a>
|
||||
Jak mogę usunąć swoje konto? <a href="#remove-account" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Gdy korzystasz z konta e-mail w ArcaneChat, sposób usunięcia konta zależy od dostawcy poczty e-mail.
|
||||
Nie mamy żadnej kontroli nad twoim kontem e-mail, więc niestety nie możemy ci w tym pomóc.</p>
|
||||
<p>Jeśli używasz domyślnego profilu czatu, możesz po prostu odinstalować aplikację. Spowoduje to automatyczne usunięcie wszystkich powiązanych danych konta na serwerze czatu. Aby uzyskać więcej informacji, zapoznaj się z <a href="https://nine.testrun.org/info.html#account-deletion">nine.testrun.org usuwanie kont</a> dla domyślnego serwera powitalnego lub odpowiednią stroną wybranego <a href="https://delta.chat/chatmail">serwera czatu innej firmy</a>.</p>
|
||||
|
||||
<p>Jeśli chcesz zachować konto, ale odinstalować ArcaneChat, zaleca się opuszczenie każdego czatu grupowego przed odinstalowaniem ArcaneChat.</p>
|
||||
<p>Jeśli skonfigurowałeś swój profil czatu na wielu urządzeniach, musisz go usunąć ze wszystkich urządzeń.</p>
|
||||
|
||||
<p>Jeśli używasz więcej niż jednego konta, ale nie chcesz pozbywać się ich wszystkich, możesz je usunąć w menu przełączania kont (na Androidzie i iOS) lub w pasku bocznym, klikając prawym przyciskiem myszy (w kliencie komputerowym).</p>
|
||||
|
||||
<p>Konta u <a href="https://providers.delta.chat">klasycznych dostawców poczty e-mail</a> nie zostaną usunięte automatycznie; sposób usunięcia konta zależy od dostawcy poczty e-mail. Nie mamy żadnej kontroli nad kontami e-mail u tych dostawców, więc niestety nie możemy ci w tym pomóc.</p>
|
||||
|
||||
<p>Jeśli chcesz nadal używać klasycznego konta e-mail z innymi aplikacjami, ale odinstalować Delta Chat, zaleca się opuszczenie każdego czatu grupowego przed odinstalowaniem Delta Chat. W przeciwnym razie możesz otrzymywać nieodszyfrowywane wiadomości z tych czatów grupowych.</p>
|
||||
|
||||
<h3 id="interesują-mnie-szczegóły-techniczne-możesz-powiedzieć-mi-coś-więcej">
|
||||
|
||||
@@ -1348,21 +1376,49 @@ Nie mamy żadnej kontroli nad twoim kontem e-mail, więc niestety nie możemy ci
|
||||
</h3>
|
||||
|
||||
<ul>
|
||||
<li>Zobacz <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Standardy używane w ArcaneChat</a>.</li>
|
||||
<li>Zobacz <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md#standards-used-in-delta-chat">Standardy używane w Delta Chat</a>.</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="gdzie-moi-znajomi-mogą-znaleźć-delta-chat">
|
||||
|
||||
|
||||
Gdzie moi znajomi mogą znaleźć Delta Chat? <a href="#gdzie-moi-znajomi-mogą-znaleźć-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>Delta Chat jest dostępny na wszystkich głównych i niektórych mniejszych platformach:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<p>Oficjalna <strong>strona internetowa</strong> <a href="https://delta.chat/download">https://delta.chat/download</a> pokazuje wszystkie opcje szczegółowo</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Jeśli nie jest dostępna, użyj <strong>kopii strony</strong> pod adresem <a href="https://deltachat.github.io/deltachat-pages">https://deltachat.github.io/deltachat-pages</a></p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Otwórz jeden z następujących <strong>sklepów z aplikacjami i wyszukaj „Delta Chat”</strong>: Google Play Store, F-Droid, Huawei App Gallery, Amazon App Store, iOS i macOS App Store, Microsoft Store</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Sprawdź <strong>menedżera pakietów</strong> swoich dystrybucji Linuksa</p>
|
||||
</li>
|
||||
<li>
|
||||
<p><strong>Aplikacje na Androida</strong> są również dostępne na <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a></p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h3 id="w-jaki-sposób-finansowany-jest-rozwój-delta-chat">
|
||||
|
||||
|
||||
W jaki sposób finansowany jest rozwój ArcaneChat? <a href="#w-jaki-sposób-finansowany-jest-rozwój-delta-chat" class="anchor"></a>
|
||||
W jaki sposób finansowany jest rozwój Delta Chat? <a href="#w-jaki-sposób-finansowany-jest-rozwój-delta-chat" class="anchor"></a>
|
||||
|
||||
|
||||
</h3>
|
||||
|
||||
<p>ArcaneChat nie otrzymuje żadnego kapitału wysokiego ryzyka, nie jest zadłużony i nie jest pod presją generowania ogromnych zysków lub sprzedawania reklamodawcom użytkowników i ich przyjaciół oraz rodziny (lub gorzej).
|
||||
<p>Delta Chat nie otrzymuje żadnego kapitału wysokiego ryzyka, nie jest zadłużony i nie jest pod presją generowania ogromnych zysków lub sprzedawania reklamodawcom użytkowników i ich przyjaciół oraz rodziny (lub gorzej).
|
||||
Raczej korzystamy z publicznych źródeł finansowania, jak dotąd pochodzących z UE i USA, aby wspomóc nasze wysiłki w inicjowaniu zdecentralizowanego i zróżnicowanego ekosystemu komunikatora, opartego na rozwoju społeczności Free i Open-Source.</p>
|
||||
|
||||
<p>Konkretnie, rozwój ArcaneChat był dotychczas finansowany z tych źródeł:</p>
|
||||
<p>Konkretnie, rozwój Delta Chat był dotychczas finansowany z tych źródeł, uporządkowanych chronologicznie:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
@@ -1380,25 +1436,27 @@ Druga dotacja w 2019/2020 (~300 000 4) pomogła nam wydać wersje Delta/iOS, prz
|
||||
</li>
|
||||
<li>
|
||||
<p>Od końca 2021 do marca 2023 otrzymaliśmy dofinansowanie <em>Wolność Internetu</em> (~500 tys. $) z amerykańskiego Biura Demokracji, Praw Człowieka i Pracy (DRL).
|
||||
Fundusze te wspierają nasze długofalowe cele, aby uczynić ArcaneChat bardziej użytecznym i kompatybilnym z szeroką gamą serwerów e-mail na całym świecie, a także bardziej odpornym i bezpiecznym w miejscach często dotkniętych cenzurą i wyłączeniami Internetu.</p>
|
||||
Fundusze te wspierają nasze długofalowe cele, aby uczynić Delta Chat bardziej użytecznym i kompatybilnym z szeroką gamą serwerów e-mail na całym świecie, a także bardziej odpornym i bezpiecznym w miejscach często dotkniętych cenzurą i wyłączeniami Internetu.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Od 2023 roku zostaliśmy zaakceptowani w programie Next Generation Internet (NGI) Entrust dla naszych propozycji „Prywatnych zdecentralizowanych aplikacji”. Dokładna kwota do ustalenia (około 100 tys. EUR). Finansowanie to wspiera dalszy rozwój <a href="https://webxdc.org">„aplikacji udostępnianych na czacie” webxdc</a>.</p>
|
||||
<p>W latach 2023-2024 pomyślnie ukończyliśmy finansowany przez OTF <a href="https://www.opentech.fund/projects-we-support/supported-projects/secure-chat-mail-with-delta-chat/">projekt Secure Chatmail</a>, co pozwoliło nam wprowadzić gwarantowane szyfrowanie, stworzyć <a href="https://delta.chat/chatmail">sieć serwerów chatmail</a> i zapewnić „natychmiastowe wdrażanie” we wszystkich aplikacjach wydanych od kwietnia 2024 r.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>W latach 2023 i 2024 zostaliśmy przyjęci do programu Next Generation Internet (NGI) za naszą pracę w <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a>, wraz z partnerami współpracującymi pracującymi nad <a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>, <a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>, <a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> i <a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>. Wszystkie te projekty są częściowo ukończone lub zostaną ukończone na początku 2025 r.</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>Czasami otrzymujemy jednorazowe darowizny od osób prywatnych. Na przykład w 2021 roku pewna hojna osoba przekazała nam 4K EUR w formie przelewu bankowego tytułem “kontynuujcie dobry rozwój!”. 💜 Takie pieniądze przeznaczamy na finansowanie spotkań rozwojowych lub na doraźne wydatki, których nie da się łatwo przewidzieć lub zrefundować z publicznych dotacji. Otrzymywanie większej ilości darowizn pomaga nam również stać się bardziej niezależnymi i długoterminowo rentownymi jako społeczność współpracowników.</p>
|
||||
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<p>Wreszcie, ale zdecydowanie nie najmniej ważne, kilku ekspertów i entuzjastów pro-bono wniosło wkład i przyczyniło się do rozwoju Delta Chat bez otrzymywania pieniędzy lub tylko niewielkich kwot. Bez nich Delta Chat nie byłby tam, gdzie jest dzisiaj, nawet w pobliżu.</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<ul>
|
||||
<li>Wreszcie, ale zdecydowanie nie najmniej ważne, kilku ekspertów i entuzjastów pro-bono wniosło wkład i przyczyniło się do rozwoju ArcaneChat bez otrzymywania pieniędzy lub tylko niewielkich kwot. Bez nich ArcaneChat nie byłby tam, gdzie jest dzisiaj, nawet w pobliżu.</li>
|
||||
</ul>
|
||||
|
||||
<p>Wspomniane powyżej finansowanie pieniężne jest w większości organizowane przez merlinux GmbH we Freiburgu (Niemcy) i jest dystrybuowane do kilkunastu podmiotów na całym świecie.</p>
|
||||
|
||||
<p>Zapoznaj się z <a href="https://delta.chat/pl/contribute">kanałami wpłat dla ArcaneChat</a>, aby uzyskać informacje o możliwościach wpłat zarówno pieniężnych, jak i innych.</p>
|
||||
<p>Zapoznaj się z <a href="https://delta.chat/pl/contribute">kanałami wpłat dla Delta Chat</a>, aby uzyskać informacje o możliwościach wpłat zarówno pieniężnych, jak i innych.</p>
|
||||
|
||||
|
||||
|
||||
|
||||
+277
-197
File diff suppressed because it is too large
Load Diff
+842
-736
File diff suppressed because it is too large
Load Diff
+277
-197
File diff suppressed because it is too large
Load Diff
+276
-196
File diff suppressed because it is too large
Load Diff
+235
-176
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -33,6 +33,7 @@ public class DcAccounts {
|
||||
public native void stopIo ();
|
||||
public native void maybeNetwork ();
|
||||
public native void setPushDeviceToken (String token);
|
||||
public native boolean backgroundFetch (int timeoutSeconds);
|
||||
|
||||
public native int addAccount ();
|
||||
public native int migrateAccount (String dbfile);
|
||||
|
||||
@@ -2,16 +2,14 @@ package com.b44t.messenger;
|
||||
|
||||
public class DcContext {
|
||||
|
||||
public final static int DC_PREF_DEFAULT_MDNS_ENABLED = 1;
|
||||
public final static int DC_PREF_DEFAULT_TRIM_ENABLED = 0;
|
||||
public final static int DC_PREF_DEFAULT_TRIM_LENGTH = 500;
|
||||
|
||||
public final static int DC_EVENT_INFO = 100;
|
||||
public final static int DC_EVENT_WARNING = 300;
|
||||
public final static int DC_EVENT_ERROR = 400;
|
||||
public final static int DC_EVENT_ERROR_SELF_NOT_IN_GROUP = 410;
|
||||
public final static int DC_EVENT_MSGS_CHANGED = 2000;
|
||||
public final static int DC_EVENT_REACTIONS_CHANGED = 2001;
|
||||
public final static int DC_EVENT_INCOMING_REACTION = 2002;
|
||||
public final static int DC_EVENT_INCOMING_WEBXDC_NOTIFY = 2003;
|
||||
public final static int DC_EVENT_INCOMING_MSG = 2005;
|
||||
public final static int DC_EVENT_MSGS_NOTICED = 2008;
|
||||
public final static int DC_EVENT_MSG_DELIVERED = 2010;
|
||||
@@ -31,6 +29,7 @@ public class DcContext {
|
||||
public final static int DC_EVENT_WEBXDC_STATUS_UPDATE = 2120;
|
||||
public final static int DC_EVENT_WEBXDC_INSTANCE_DELETED = 2121;
|
||||
public final static int DC_EVENT_WEBXDC_REALTIME_DATA = 2150;
|
||||
public final static int DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE = 2200;
|
||||
|
||||
public final static int DC_IMEX_EXPORT_SELF_KEYS = 1;
|
||||
public final static int DC_IMEX_IMPORT_SELF_KEYS = 2;
|
||||
@@ -55,6 +54,7 @@ public class DcContext {
|
||||
public final static int DC_QR_BACKUP = 251;
|
||||
public final static int DC_QR_BACKUP2 = 252;
|
||||
public final static int DC_QR_WEBRTC = 260;
|
||||
public final static int DC_QR_PROXY = 271;
|
||||
public final static int DC_QR_ADDR = 320;
|
||||
public final static int DC_QR_TEXT = 330;
|
||||
public final static int DC_QR_URL = 332;
|
||||
@@ -80,16 +80,13 @@ public class DcContext {
|
||||
public final static int DC_MEDIA_QUALITY_BALANCED = 0;
|
||||
public final static int DC_MEDIA_QUALITY_WORSE = 1;
|
||||
|
||||
public final static int DC_DECISION_START_CHAT = 0;
|
||||
public final static int DC_DECISION_BLOCK = 1;
|
||||
public final static int DC_DECISION_NOT_NOW = 2;
|
||||
|
||||
public final static int DC_CONNECTIVITY_NOT_CONNECTED = 1000;
|
||||
public final static int DC_CONNECTIVITY_CONNECTING = 2000;
|
||||
public final static int DC_CONNECTIVITY_WORKING = 3000;
|
||||
public final static int DC_CONNECTIVITY_CONNECTED = 4000;
|
||||
|
||||
private static final String CONFIG_ACCOUNT_ENABLED = "ui.enabled";
|
||||
private static final String CONFIG_MUTE_MENTIONS_IF_MUTED = "ui.mute_mentions_if_muted";
|
||||
|
||||
// when using DcAccounts, use DcAccounts.addAccount() instead
|
||||
public DcContext(String osName, String dbfile) {
|
||||
@@ -182,7 +179,6 @@ public class DcContext {
|
||||
public native int[] searchMsgs (int chat_id, String query);
|
||||
public native int[] getFreshMsgs ();
|
||||
public native int[] getChatMedia (int chat_id, int type1, int type2, int type3);
|
||||
public native int getNextMedia (int msg_id, int dir, int type1, int type2, int type3);
|
||||
public native int[] getChatContacts (int chat_id);
|
||||
public native int getChatEphemeralTimer (int chat_id);
|
||||
public native boolean setChatEphemeralTimer (int chat_id, int timer);
|
||||
@@ -198,12 +194,12 @@ public class DcContext {
|
||||
public native int estimateDeletionCount(boolean from_server, long seconds);
|
||||
public native void deleteMsgs (int msg_ids[]);
|
||||
public native void forwardMsgs (int msg_ids[], int chat_id);
|
||||
public native void saveMsgs (int msg_ids[]);
|
||||
public native boolean resendMsgs (int msg_ids[]);
|
||||
public native int prepareMsg (int chat_id, DcMsg msg);
|
||||
public native int sendMsg (int chat_id, DcMsg msg);
|
||||
public native int sendTextMsg (int chat_id, String text);
|
||||
public native int sendVideochatInvitation(int chat_id);
|
||||
public native boolean sendWebxdcStatusUpdate(int msg_id, String payload, String descr);
|
||||
public native boolean sendWebxdcStatusUpdate(int msg_id, String payload);
|
||||
public native String getWebxdcStatusUpdates(int msg_id, int last_known_serial);
|
||||
public native void setWebxdcIntegration (String file);
|
||||
public native int initWebxdcIntegration(int chat_id);
|
||||
@@ -212,6 +208,7 @@ public class DcContext {
|
||||
public DcLot checkQr (String qr) { return new DcLot(checkQrCPtr(qr)); }
|
||||
public native String getSecurejoinQr (int chat_id);
|
||||
public native String getSecurejoinQrSvg (int chat_id);
|
||||
public native String createQrSvg (String payload);
|
||||
public native int joinSecurejoin (String qr);
|
||||
public native void sendLocationsToChat (int chat_id, int seconds);
|
||||
public native boolean isSendingLocationsToChat(int chat_id);
|
||||
@@ -230,22 +227,20 @@ public class DcContext {
|
||||
}
|
||||
}
|
||||
|
||||
public String getNameNAddr() {
|
||||
public boolean isMentionsEnabled() {
|
||||
return getConfigInt(CONFIG_MUTE_MENTIONS_IF_MUTED) != 1;
|
||||
}
|
||||
|
||||
public void setMentionsEnabled(boolean enabled) {
|
||||
setConfigInt(CONFIG_MUTE_MENTIONS_IF_MUTED, enabled? 0 : 1);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
String displayname = getConfig("displayname");
|
||||
String addr = getConfig("addr");
|
||||
String ret = "";
|
||||
|
||||
if (!displayname.isEmpty() && !addr.isEmpty()) {
|
||||
ret = String.format("%s (%s)", displayname, addr);
|
||||
} else if (!addr.isEmpty()) {
|
||||
ret = addr;
|
||||
if (displayname.isEmpty()) {
|
||||
displayname = getContact(DcContact.DC_CONTACT_ID_SELF).getAddr();
|
||||
}
|
||||
|
||||
if (ret.isEmpty() || isConfigured() == 0) {
|
||||
ret += " (not configured)";
|
||||
}
|
||||
|
||||
return ret.trim();
|
||||
return displayname;
|
||||
}
|
||||
|
||||
public boolean isCommunity() {
|
||||
@@ -277,21 +272,6 @@ public class DcContext {
|
||||
setConfigInt("is_muted", muted? 1 : 0);
|
||||
}
|
||||
|
||||
// Called for new profiles on chatmail servers that are "single device" initially;
|
||||
// to save server disk space, we make use of that delete all messages immediately after download.
|
||||
public void assumeSingleDevice() {
|
||||
if (isChatmail()) {
|
||||
setConfigInt("delete_server_after", 1 /*at once*/);
|
||||
}
|
||||
}
|
||||
|
||||
// Called when we get a hint that another device may be set up.
|
||||
public void assumeMultiDevice() {
|
||||
if (isChatmail() && getConfigInt("delete_server_after") == 1 /*at once*/) {
|
||||
setConfigInt("delete_server_after", 0 /*never/automatic*/);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isGmailOauth2Addr(String addr) {
|
||||
final String oauth2url = getOauth2Url(addr, "chat.delta:/foo");
|
||||
return isGmailOauth2Url(oauth2url);
|
||||
@@ -301,6 +281,12 @@ public class DcContext {
|
||||
return oauth2url.startsWith("https://accounts.google.com/");
|
||||
}
|
||||
|
||||
public void restartIo() {
|
||||
if (!isEnabled()) return;
|
||||
stopIo();
|
||||
startIo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if at least one chat has location streaming enabled
|
||||
*/
|
||||
|
||||
@@ -148,6 +148,7 @@ public class DcMsg {
|
||||
return new JSONObject();
|
||||
}
|
||||
}
|
||||
public native String getWebxdcHref ();
|
||||
public native boolean isForwarded ();
|
||||
public native boolean isInfo ();
|
||||
public native boolean isSetupMessage ();
|
||||
@@ -155,25 +156,26 @@ public class DcMsg {
|
||||
public native String getSetupCodeBegin ();
|
||||
public native String getVideochatUrl ();
|
||||
public native int getVideochatType ();
|
||||
public native boolean isIncreation ();
|
||||
public native void setText (String text);
|
||||
public native void setSubject (String text);
|
||||
public native void setHtml (String text);
|
||||
public native void setFile (String file, String filemime);
|
||||
public native void forceSticker ();
|
||||
public native void setFileAndDeduplicate(String file, String name, String filemime);
|
||||
public native void setDimension (int width, int height);
|
||||
public native void setDuration (int duration);
|
||||
public native void setLocation (float latitude, float longitude);
|
||||
public native String getPOILocation ();
|
||||
public void setQuote (DcMsg quote) { setQuoteCPtr(quote.msgCPtr); }
|
||||
public native String getQuotedText ();
|
||||
public native String getError ();
|
||||
public native String getOverrideSenderName();
|
||||
public native boolean isOutgoing();
|
||||
public native int getSenderColor();
|
||||
|
||||
public String getSenderName(DcContact dcContact, boolean markOverride) {
|
||||
public String getSenderName(DcContact dcContact) {
|
||||
String overrideName = getOverrideSenderName();
|
||||
if (overrideName != null) {
|
||||
return (markOverride ? "~" : "") + overrideName;
|
||||
return "~" + overrideName;
|
||||
} else {
|
||||
return dcContact.getDisplayName();
|
||||
}
|
||||
@@ -189,6 +191,14 @@ public class DcMsg {
|
||||
return cPtr != 0 ? new DcMsg(cPtr) : null;
|
||||
}
|
||||
|
||||
public native int getOriginalMsgId ();
|
||||
public native int getSavedMsgId ();
|
||||
|
||||
public boolean canSave() {
|
||||
// saving info-messages out of context results in confusion, see https://github.com/deltachat/deltachat-ios/issues/2567
|
||||
return !isInfo() && getType() != DC_MSG_VIDEOCHAT_INVITATION;
|
||||
}
|
||||
|
||||
public File getFileAsFile() {
|
||||
if(getFile()==null)
|
||||
throw new AssertionError("expected a file to be present.");
|
||||
@@ -208,6 +218,10 @@ public class DcMsg {
|
||||
return ids;
|
||||
}
|
||||
|
||||
public boolean isOutgoing() {
|
||||
return getFromId() == DcContact.DC_CONTACT_ID_SELF;
|
||||
}
|
||||
|
||||
public String getDisplayBody() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@@ -79,23 +79,6 @@ public class Rpc {
|
||||
}
|
||||
}
|
||||
|
||||
public int addAccount() throws RpcException {
|
||||
return gson.fromJson(getResult("add_account"), int.class);
|
||||
}
|
||||
|
||||
public void startIO() throws RpcException {
|
||||
getResult("start_io_for_all_accounts");
|
||||
}
|
||||
|
||||
public void stopIO() throws RpcException {
|
||||
getResult("stop_io_for_all_accounts");
|
||||
}
|
||||
|
||||
public Map<String, String> getSystemInfo() throws RpcException {
|
||||
TypeToken<Map<String, String>> mapType = new TypeToken<Map<String, String>>(){};
|
||||
return gson.fromJson(getResult("get_system_info"), mapType.getType());
|
||||
}
|
||||
|
||||
public List<VcardContact> parseVcard(String path) throws RpcException {
|
||||
TypeToken<List<VcardContact>> listType = new TypeToken<List<VcardContact>>(){};
|
||||
return gson.fromJson(getResult("parse_vcard", path), listType.getType());
|
||||
@@ -138,6 +121,10 @@ public class Rpc {
|
||||
getResult("leave_webxdc_realtime", accountId, instanceMessageId);
|
||||
}
|
||||
|
||||
public int getAccountFileSize(int accountId) throws RpcException {
|
||||
return getResult("get_account_file_size", accountId).getAsInt();
|
||||
}
|
||||
|
||||
private static class Request {
|
||||
private final String jsonrpc = "2.0";
|
||||
public final String method;
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.DcEventEmitter;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
@@ -37,7 +36,6 @@ import org.thoughtcrime.securesms.connect.KeepAliveService;
|
||||
import org.thoughtcrime.securesms.connect.NetworkStateReceiver;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSecret;
|
||||
import org.thoughtcrime.securesms.crypto.DatabaseSecretProvider;
|
||||
import org.thoughtcrime.securesms.crypto.PRNGFixes;
|
||||
import org.thoughtcrime.securesms.geolocation.DcLocationManager;
|
||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||
import org.thoughtcrime.securesms.notifications.FcmReceiveService;
|
||||
@@ -107,11 +105,6 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
|
||||
Log.i("DeltaChat", "++++++++++++++++++ ApplicationContext.onCreate() ++++++++++++++++++");
|
||||
|
||||
// The first call to `getInstance` takes about 100ms-300ms, so, do it on a background thread
|
||||
Thread t = new Thread(() -> EmojiProvider.getInstance(this), "InitEmojiProviderThread");
|
||||
t.setPriority(Thread.MIN_PRIORITY);
|
||||
t.start();
|
||||
|
||||
System.loadLibrary("native-utils");
|
||||
|
||||
dcAccounts = new DcAccounts(new File(getFilesDir(), "accounts").getAbsolutePath());
|
||||
@@ -131,9 +124,6 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if ("deltafans@nine.testrun.org".equals(ac.getConfig("configured_addr")) && !ac.isCommunity()) {
|
||||
ac.setCommunityMode(true);
|
||||
}
|
||||
}
|
||||
if (allAccounts.length == 0) {
|
||||
dcAccounts.addAccount();
|
||||
@@ -209,7 +199,6 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
|
||||
KeepAliveService.maybeStartSelf(this);
|
||||
|
||||
initializeRandomNumberFix();
|
||||
initializeLogging();
|
||||
initializeJobManager();
|
||||
InChatSounds.getInstance(this);
|
||||
@@ -240,11 +229,10 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
TimeUnit.MILLISECONDS)
|
||||
.setConstraints(constraints)
|
||||
.build();
|
||||
try {
|
||||
// in Android 4 this throws exception due to R8/shrinking
|
||||
WorkManager.getInstance(this)
|
||||
.enqueueUniquePeriodicWork("FetchWorker", ExistingPeriodicWorkPolicy.KEEP, fetchWorkRequest);
|
||||
} catch (Throwable e) {}
|
||||
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
||||
"FetchWorker",
|
||||
ExistingPeriodicWorkPolicy.KEEP,
|
||||
fetchWorkRequest);
|
||||
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
|
||||
|
||||
if (Prefs.isPushEnabled(this)) {
|
||||
@@ -258,10 +246,6 @@ public class ApplicationContext extends MultiDexApplication {
|
||||
return jobManager;
|
||||
}
|
||||
|
||||
private void initializeRandomNumberFix() {
|
||||
PRNGFixes.apply();
|
||||
}
|
||||
|
||||
private void initializeLogging() {
|
||||
SignalProtocolLoggerProvider.setProvider(new AndroidSignalProtocolLogger());
|
||||
}
|
||||
|
||||
@@ -156,10 +156,6 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
||||
this.findPreference(PREFERENCE_CATEGORY_HELP)
|
||||
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_HELP));
|
||||
|
||||
if (VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
tintIcons(getActivity());
|
||||
}
|
||||
|
||||
DcHelper.getEventCenter(getActivity()).addObserver(DcContext.DC_EVENT_CONNECTIVITY_CHANGED, this);
|
||||
}
|
||||
|
||||
@@ -186,7 +182,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
||||
public void handleEvent(@NonNull DcEvent event) {
|
||||
if (event.getId() == DcContext.DC_EVENT_CONNECTIVITY_CHANGED) {
|
||||
this.findPreference(PREFERENCE_CATEGORY_CONNECTIVITY)
|
||||
.setSummary(DcHelper.getConnectivitySummary(getActivity(), R.string.connectivity_connected));
|
||||
.setSummary(DcHelper.getConnectivitySummary(getActivity(), getString(R.string.connectivity_connected)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,7 +198,7 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
|
||||
this.findPreference(PREFERENCE_CATEGORY_PRIVACY)
|
||||
.setSummary(PrivacyPreferenceFragment.getSummary(getActivity()));
|
||||
this.findPreference(PREFERENCE_CATEGORY_CONNECTIVITY)
|
||||
.setSummary(DcHelper.getConnectivitySummary(getActivity(), R.string.connectivity_connected));
|
||||
.setSummary(DcHelper.getConnectivitySummary(getActivity(), getString(R.string.connectivity_connected)));
|
||||
this.findPreference(PREFERENCE_CATEGORY_HELP)
|
||||
.setSummary(AdvancedPreferenceFragment.getVersion(getActivity()));
|
||||
}
|
||||
|
||||
@@ -33,9 +33,6 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
onPreCreate();
|
||||
if (BaseActivity.isMenuWorkaroundRequired()) {
|
||||
forceOverflowMenu();
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@@ -46,20 +43,6 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
|
||||
dynamicTheme.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return (keyCode == KeyEvent.KEYCODE_MENU && BaseActivity.isMenuWorkaroundRequired()) || super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && BaseActivity.isMenuWorkaroundRequired()) {
|
||||
openOptionsMenu();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
private void initializeScreenshotSecurity() {
|
||||
if (Prefs.isScreenSecurityEnabled(this)) {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.os.Build;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
public abstract class BaseActivity extends FragmentActivity {
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
return (keyCode == KeyEvent.KEYCODE_MENU && isMenuWorkaroundRequired()) || super.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && isMenuWorkaroundRequired()) {
|
||||
openOptionsMenu();
|
||||
return true;
|
||||
}
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
|
||||
public static boolean isMenuWorkaroundRequired() {
|
||||
return VERSION.SDK_INT < VERSION_CODES.KITKAT && ("LGE".equalsIgnoreCase(Build.MANUFACTURER) || "E6710".equalsIgnoreCase(Build.DEVICE));
|
||||
}
|
||||
}
|
||||
@@ -93,12 +93,16 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
||||
if (isForwarding(getActivity())) {
|
||||
message = String.format(Util.getLocale(), getString(R.string.ask_forward_multiple), selectedChats.size());
|
||||
} else if (!uris.isEmpty()) {
|
||||
message = String.format(Util.getLocale(), getString(R.string.share_multiple_attachments_multiple_chats), uris.size(), selectedChats.size());
|
||||
message = String.format(Util.getLocale(), getString(R.string.ask_send_files_to_selected_chats), uris.size(), selectedChats.size());
|
||||
} else {
|
||||
message = String.format(Util.getLocale(), getString(R.string.share_text_multiple_chats), selectedChats.size(), getSharedText(getActivity()));
|
||||
}
|
||||
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
if (SendRelayedMessageUtil.containsVideoType(context, uris)) {
|
||||
message += "\n\n" + getString(R.string.videos_sent_without_recoding);
|
||||
}
|
||||
new AlertDialog.Builder(context)
|
||||
.setMessage(message)
|
||||
.setCancelable(false)
|
||||
@@ -360,9 +364,7 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
||||
|
||||
mode.setTitle("1");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
requireActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
requireActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -391,11 +393,9 @@ public abstract class BaseConversationListFragment extends Fragment implements A
|
||||
actionMode = null;
|
||||
getListAdapter().initializeBatchMode(false);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
TypedArray color = requireActivity().getTheme().obtainStyledAttributes(new int[] {android.R.attr.statusBarColor});
|
||||
requireActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
|
||||
color.recycle();
|
||||
}
|
||||
TypedArray color = requireActivity().getTheme().obtainStyledAttributes(new int[]{android.R.attr.statusBarColor});
|
||||
requireActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
|
||||
color.recycle();
|
||||
|
||||
Context context = getContext();
|
||||
if (context != null) {
|
||||
|
||||
@@ -25,6 +25,7 @@ public interface BindableConversationItem extends Unbindable {
|
||||
|
||||
interface EventListener {
|
||||
void onQuoteClicked(DcMsg messageRecord);
|
||||
void onJumpToOriginalClicked(DcMsg messageRecord);
|
||||
void onShowFullClicked(DcMsg messageRecord);
|
||||
void onDownloadClicked(DcMsg messageRecord);
|
||||
void onReactionClicked(DcMsg messageRecord);
|
||||
|
||||
@@ -136,9 +136,7 @@ public class ContactSelectionListFragment extends Fragment
|
||||
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
|
||||
MenuInflater inflater = getActivity().getMenuInflater();
|
||||
inflater.inflate(R.menu.contact_list, menu);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
getActivity().getWindow().setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
setCorrectMenuVisibility(menu);
|
||||
actionMode.setTitle("1");
|
||||
return true;
|
||||
@@ -170,11 +168,9 @@ public class ContactSelectionListFragment extends Fragment
|
||||
ContactSelectionListFragment.this.actionMode = null;
|
||||
getContactSelectionListAdapter().resetActionModeSelection();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[] {android.R.attr.statusBarColor});
|
||||
getActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
|
||||
color.recycle();
|
||||
}
|
||||
TypedArray color = getActivity().getTheme().obtainStyledAttributes(new int[]{android.R.attr.statusBarColor});
|
||||
getActivity().getWindow().setStatusBarColor(color.getColor(0, Color.BLACK));
|
||||
color.recycle();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ import static org.thoughtcrime.securesms.util.RelayUtil.isSharing;
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.ClipData;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Configuration;
|
||||
@@ -36,9 +36,7 @@ import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Browser;
|
||||
import android.text.Editable;
|
||||
@@ -47,6 +45,7 @@ import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
@@ -55,6 +54,7 @@ import android.view.View.OnFocusChangeListener;
|
||||
import android.view.View.OnKeyListener;
|
||||
import android.view.WindowManager;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
@@ -91,8 +91,6 @@ import org.thoughtcrime.securesms.components.InputPanel;
|
||||
import org.thoughtcrime.securesms.components.KeyboardAwareLinearLayout.OnKeyboardShownListener;
|
||||
import org.thoughtcrime.securesms.components.ScaleStableImageView;
|
||||
import org.thoughtcrime.securesms.components.SendButton;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
@@ -121,7 +119,7 @@ import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener;
|
||||
import org.thoughtcrime.securesms.util.guava.Optional;
|
||||
import org.thoughtcrime.securesms.util.views.Stub;
|
||||
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
import org.thoughtcrime.securesms.video.recode.VideoRecoder;
|
||||
import org.thoughtcrime.securesms.videochat.VideochatUtil;
|
||||
|
||||
@@ -164,8 +162,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private static final int GROUP_EDIT = 6;
|
||||
private static final int TAKE_PHOTO = 7;
|
||||
private static final int RECORD_VIDEO = 8;
|
||||
private static final int PICK_LOCATION = 9; // TODO: i think, this can be deleted
|
||||
private static final int SMS_DEFAULT = 11; // TODO: i think, this can be deleted
|
||||
private static final int PICK_WEBXDC = 9;
|
||||
|
||||
private GlideRequests glideRequests;
|
||||
protected ComposeText composeText;
|
||||
@@ -178,11 +175,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private View composePanel;
|
||||
private ScaleStableImageView backgroundView;
|
||||
private MessageRequestsBottomView messageRequestBottomView;
|
||||
private ProgressDialog progressDialog;
|
||||
|
||||
private AttachmentTypeSelector attachmentTypeSelector;
|
||||
private AttachmentManager attachmentManager;
|
||||
private AudioRecorder audioRecorder;
|
||||
private Stub<MediaKeyboard> emojiDrawerStub;
|
||||
private FrameLayout emojiPickerContainer;
|
||||
private MediaKeyboard emojiPicker;
|
||||
protected HidingLinearLayout quickAttachmentToggle;
|
||||
private InputPanel inputPanel;
|
||||
|
||||
@@ -302,12 +301,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
DcHelper.getNotificationCenter(this).updateVisibleChat(dcContext.getAccountId(), chatId);
|
||||
|
||||
attachmentManager.onResume();
|
||||
|
||||
// action bar might be hidden by workaround in onStop()
|
||||
ActionBar supportActionBar = getSupportActionBar();
|
||||
if (supportActionBar != null && !supportActionBar.isShowing()) {
|
||||
supportActionBar.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -322,33 +315,17 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
AudioSlidePlayer.stopAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
|
||||
// hack/workaround to fix https://github.com/deltachat/deltachat-android/issues/2798
|
||||
// the real cause of the problem is still unknown but hiding the action bar here fixes it
|
||||
if ( Build.VERSION.SDK_INT >= 34) {
|
||||
ActionBar supportActionBar = getSupportActionBar();
|
||||
if (supportActionBar != null && container.isKeyboardOpen()) {
|
||||
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||||
if (!pm.isInteractive()) {
|
||||
supportActionBar.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
Log.i(TAG, "onConfigurationChanged(" + newConfig.orientation + ")");
|
||||
super.onConfigurationChanged(newConfig);
|
||||
composeText.setTransport(sendButton.getSelectedTransport());
|
||||
|
||||
if (emojiDrawerStub.resolved() && container.getCurrentInput() == emojiDrawerStub.get()) {
|
||||
if (emojiPicker != null && container.getCurrentInput() == emojiPicker) {
|
||||
container.hideAttachedInput(true);
|
||||
}
|
||||
|
||||
emojiPicker = null; // force reloading next time onEmojiToggle() is called
|
||||
initializeBackground();
|
||||
}
|
||||
|
||||
@@ -362,22 +339,38 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
public void onActivityResult(final int reqCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(reqCode, resultCode, data);
|
||||
|
||||
if ((data == null && reqCode != TAKE_PHOTO && reqCode != RECORD_VIDEO && reqCode != SMS_DEFAULT) ||
|
||||
(resultCode != RESULT_OK && reqCode != SMS_DEFAULT))
|
||||
if (resultCode != RESULT_OK || (data == null && reqCode != TAKE_PHOTO && reqCode != RECORD_VIDEO))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (reqCode) {
|
||||
case PICK_GALLERY:
|
||||
MediaType mediaType;
|
||||
String mimeType = MediaUtil.getMimeType(this, data.getData());
|
||||
|
||||
if (MediaUtil.isGif(mimeType)) mediaType = MediaType.GIF;
|
||||
else if (MediaUtil.isVideo(mimeType)) mediaType = MediaType.VIDEO;
|
||||
else mediaType = MediaType.IMAGE;
|
||||
|
||||
setMedia(data.getData(), mediaType);
|
||||
final Uri singleUri = data.getData();
|
||||
if (singleUri != null) {
|
||||
MediaType mediaType;
|
||||
String mimeType = MediaUtil.getMimeType(this, singleUri);
|
||||
if (MediaUtil.isGif(mimeType)) mediaType = MediaType.GIF;
|
||||
else if (MediaUtil.isVideo(mimeType)) mediaType = MediaType.VIDEO;
|
||||
else mediaType = MediaType.IMAGE;
|
||||
setMedia(singleUri, mediaType);
|
||||
} else {
|
||||
final ClipData multipleUris = data.getClipData();
|
||||
if (multipleUris != null) {
|
||||
final int uriCount = multipleUris.getItemCount();
|
||||
if (uriCount > 0) {
|
||||
ArrayList<Uri> uriList = new ArrayList<>(uriCount);
|
||||
for (int i = 0; i < uriCount; i++) {
|
||||
uriList.add(multipleUris.getItemAt(i).getUri());
|
||||
}
|
||||
askSendingFiles(uriList, () -> {
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
SendRelayedMessageUtil.sendMultipleMsgs(this, chatId, uriList, null);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PICK_DOCUMENT:
|
||||
@@ -386,6 +379,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
setMedia(data.getData(), docMediaType);
|
||||
break;
|
||||
|
||||
case PICK_WEBXDC:
|
||||
setMedia(data.getData(), MediaType.DOCUMENT);
|
||||
break;
|
||||
|
||||
case PICK_CONTACT:
|
||||
addAttachmentContactInfo(data.getIntExtra(AttachContactActivity.CONTACT_ID_EXTRA, 0));
|
||||
break;
|
||||
@@ -413,16 +410,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
break;
|
||||
|
||||
case PICK_LOCATION:
|
||||
break;
|
||||
|
||||
case ScribbleActivity.SCRIBBLE_REQUEST_CODE:
|
||||
setMedia(data.getData(), MediaType.IMAGE);
|
||||
break;
|
||||
|
||||
case SMS_DEFAULT:
|
||||
initializeSecurity(isSecureText, isDefaultSms);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -680,17 +670,24 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
|
||||
private void askSendingFiles(ArrayList<Uri> uriList, Runnable onConfirm) {
|
||||
String message = String.format(getString(R.string.ask_send_files_to_chat), uriList.size(), dcChat.getName());
|
||||
if (SendRelayedMessageUtil.containsVideoType(context, uriList)) {
|
||||
message += "\n\n" + getString(R.string.videos_sent_without_recoding);
|
||||
}
|
||||
new AlertDialog.Builder(this)
|
||||
.setMessage(message)
|
||||
.setCancelable(false)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(R.string.menu_send, (dialog, which) -> onConfirm.run())
|
||||
.show();
|
||||
}
|
||||
|
||||
private void handleSharing() {
|
||||
ArrayList<Uri> uriList = RelayUtil.getSharedUris(this);
|
||||
int sharedContactId = RelayUtil.getSharedContactId(this);
|
||||
if (uriList.size() > 1) {
|
||||
String message = String.format(getString(R.string.share_multiple_attachments), uriList.size());
|
||||
new AlertDialog.Builder(this)
|
||||
.setMessage(message)
|
||||
.setCancelable(false)
|
||||
.setNegativeButton(android.R.string.cancel, ((dialog, which) -> finish()))
|
||||
.setPositiveButton(R.string.menu_send, (dialog, which) -> SendRelayedMessageUtil.immediatelyRelay(this, chatId))
|
||||
.show();
|
||||
askSendingFiles(uriList, () -> SendRelayedMessageUtil.immediatelyRelay(this, chatId));
|
||||
} else {
|
||||
if (sharedContactId != 0) {
|
||||
addAttachmentContactInfo(sharedContactId);
|
||||
@@ -715,7 +712,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
DcMsg draft = dcContext.getDraft(chatId);
|
||||
final String sharedText = RelayUtil.getSharedText(this);
|
||||
|
||||
if (draft == null) {
|
||||
if (!draft.isOk()) {
|
||||
if (TextUtils.isEmpty(sharedText)) {
|
||||
composeText.setText("");
|
||||
future.set(false);
|
||||
@@ -742,8 +739,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
handleReplyMessage(quote);
|
||||
}
|
||||
|
||||
String filename = draft.getFile();
|
||||
if (filename.isEmpty() || !new File(filename).exists()) {
|
||||
String file = draft.getFile();
|
||||
if (file.isEmpty() || !new File(file).exists()) {
|
||||
future.set(!text.isEmpty());
|
||||
updateToggleButtonState();
|
||||
return future;
|
||||
@@ -763,26 +760,21 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
};
|
||||
|
||||
File file = new File(filename);
|
||||
Uri uri = Uri.fromFile(file);
|
||||
switch (draft.getType()) {
|
||||
case DcMsg.DC_MSG_IMAGE:
|
||||
setMedia(uri, MediaType.IMAGE).addListener(listener);
|
||||
setMedia(draft, MediaType.IMAGE).addListener(listener);
|
||||
break;
|
||||
case DcMsg.DC_MSG_GIF:
|
||||
setMedia(uri, MediaType.GIF).addListener(listener);
|
||||
setMedia(draft, MediaType.GIF).addListener(listener);
|
||||
break;
|
||||
case DcMsg.DC_MSG_AUDIO:
|
||||
setMedia(uri, MediaType.AUDIO).addListener(listener);
|
||||
setMedia(draft, MediaType.AUDIO).addListener(listener);
|
||||
break;
|
||||
case DcMsg.DC_MSG_VIDEO:
|
||||
setMedia(uri, MediaType.VIDEO).addListener(listener);
|
||||
break;
|
||||
case DcMsg.DC_MSG_WEBXDC:
|
||||
setMedia(draft, MediaType.DOCUMENT).addListener(listener);
|
||||
setMedia(draft, MediaType.VIDEO).addListener(listener);
|
||||
break;
|
||||
default:
|
||||
setMedia(uri, MediaType.DOCUMENT).addListener(listener);
|
||||
setMedia(draft, MediaType.DOCUMENT).addListener(listener);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -816,7 +808,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
sendButton = ViewUtil.findById(this, R.id.send_button);
|
||||
attachButton = ViewUtil.findById(this, R.id.attach_button);
|
||||
composeText = ViewUtil.findById(this, R.id.embedded_text_editor);
|
||||
emojiDrawerStub = ViewUtil.findStubById(this, R.id.emoji_drawer_stub);
|
||||
emojiPickerContainer = ViewUtil.findById(this, R.id.emoji_picker_container);
|
||||
composePanel = ViewUtil.findById(this, R.id.bottom_panel);
|
||||
container = ViewUtil.findById(this, R.id.layout_container);
|
||||
quickAttachmentToggle = ViewUtil.findById(this, R.id.quick_attachment_toggle);
|
||||
@@ -936,13 +928,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
case AttachmentTypeSelector.TAKE_PHOTO:
|
||||
attachmentManager.capturePhoto(this, TAKE_PHOTO); break;
|
||||
case AttachmentTypeSelector.RECORD_VIDEO:
|
||||
if(VideoRecoder.canRecode()) {
|
||||
attachmentManager.captureVideo(this, RECORD_VIDEO);
|
||||
}
|
||||
else {
|
||||
Toast.makeText(this, "This device does not support video-compression (requires Android 4.4 KitKat)", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
attachmentManager.captureVideo(this, RECORD_VIDEO);
|
||||
break;
|
||||
case AttachmentTypeSelector.ADD_WEBXDC:
|
||||
AttachmentManager.selectWebxdc(this, PICK_WEBXDC); break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -991,14 +980,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
protected static final int ACTION_SEND_OUT = 1;
|
||||
protected static final int ACTION_SAVE_DRAFT = 2;
|
||||
|
||||
private String getSelfReaction(int msgId) {
|
||||
try {
|
||||
final String [] selfReactions = rpc.getMsgReactions(dcContext.getAccountId(), msgId).getReactionsByContact().get(DcContact.DC_CONTACT_ID_SELF);
|
||||
if (selfReactions != null && selfReactions.length > 0) return selfReactions[0];
|
||||
} catch(Exception e) { e.printStackTrace(); }
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ListenableFuture<Integer> processComposeControls(int action) {
|
||||
return processComposeControls(action, composeText.getTextTrimmed(),
|
||||
attachmentManager.isAttachmentPresent() ?
|
||||
@@ -1047,7 +1028,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
msg = new DcMsg(dcContext, DcMsg.DC_MSG_FILE);
|
||||
}
|
||||
String path = attachment.getRealPath(this);
|
||||
msg.setFile(path, null);
|
||||
msg.setFileAndDeduplicate(path, attachment.getFileName(), null);
|
||||
}
|
||||
}
|
||||
msg.setText(body);
|
||||
@@ -1056,18 +1037,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else if (action == ACTION_SEND_OUT && quote.isPresent() && EmojiProvider.getInstance(this).maybeEmoji(body)){
|
||||
int quotedMsg = quote.get().getQuotedMsg().getId();
|
||||
try {
|
||||
rpc.sendReaction(dcContext.getAccountId(), quotedMsg, body.equals(getSelfReaction(quotedMsg))? "" : body);
|
||||
future.set(chatId);
|
||||
return future;
|
||||
} catch (RpcException e) {
|
||||
e.printStackTrace();
|
||||
msg = new DcMsg(dcContext, DcMsg.DC_MSG_TEXT);
|
||||
msg.setText(body);
|
||||
}
|
||||
}
|
||||
else if (!body.isEmpty()){
|
||||
msg = new DcMsg(dcContext, DcMsg.DC_MSG_TEXT);
|
||||
msg.setText(body);
|
||||
@@ -1096,7 +1065,23 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
{
|
||||
boolean doSend = true;
|
||||
if (recompress==DcMsg.DC_MSG_VIDEO) {
|
||||
Util.runOnMain(() -> {
|
||||
progressDialog = ProgressDialog.show(
|
||||
ConversationActivity.this,
|
||||
"",
|
||||
getString(R.string.one_moment),
|
||||
true,
|
||||
false
|
||||
);
|
||||
});
|
||||
doSend = VideoRecoder.prepareVideo(ConversationActivity.this, dcChat.getId(), msg);
|
||||
Util.runOnMain(() -> {
|
||||
try {
|
||||
progressDialog.dismiss();
|
||||
} catch (final IllegalArgumentException e) {
|
||||
// The activity is finishing/destroyed, do nothing.
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (doSend) {
|
||||
@@ -1252,17 +1237,23 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
});
|
||||
}
|
||||
|
||||
private void reloadEmojiPicker() {
|
||||
emojiPickerContainer.removeAllViews();
|
||||
emojiPicker = (MediaKeyboard) LayoutInflater.from(this).inflate(R.layout.conversation_activity_emojidrawer_stub, emojiPickerContainer, false);
|
||||
emojiPickerContainer.addView(emojiPicker);
|
||||
inputPanel.setMediaKeyboard(emojiPicker);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEmojiToggle() {
|
||||
if (!emojiDrawerStub.resolved()) {
|
||||
initializeMediaKeyboardProviders(emojiDrawerStub.get(), false);
|
||||
inputPanel.setMediaKeyboard(emojiDrawerStub.get());
|
||||
if (emojiPicker == null) {
|
||||
reloadEmojiPicker();
|
||||
}
|
||||
|
||||
if (container.getCurrentInput() == emojiDrawerStub.get()) {
|
||||
if (container.getCurrentInput() == emojiPicker) {
|
||||
container.showSoftkey(composeText);
|
||||
} else {
|
||||
container.show(composeText, emojiDrawerStub.get());
|
||||
container.show(composeText, emojiPicker);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1290,17 +1281,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
if (quote.isPresent()) {
|
||||
msg.setQuote(quote.get().getQuotedMsg());
|
||||
}
|
||||
msg.setFile(path, null);
|
||||
msg.setFileAndDeduplicate(path, null, null);
|
||||
msg.forceSticker();
|
||||
dcContext.sendMsg(chatId, msg);
|
||||
}
|
||||
|
||||
private void initializeMediaKeyboardProviders(@NonNull MediaKeyboard mediaKeyboard, boolean stickersAvailable) {
|
||||
boolean isSystemEmojiPreferred = Prefs.isSystemEmojiPreferred(this);
|
||||
if (!isSystemEmojiPreferred) {
|
||||
mediaKeyboard.setProviders(0, new EmojiKeyboardProvider(this, inputPanel));
|
||||
}
|
||||
}
|
||||
|
||||
// Listeners
|
||||
|
||||
private class AttachmentTypeListener implements AttachmentTypeSelector.AttachmentClickedListener {
|
||||
|
||||
@@ -24,9 +24,9 @@ import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -211,7 +211,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
dcContext.marknoticedChat((int) chatId);
|
||||
Util.runOnBackground(() -> dcContext.marknoticedChat((int) chatId));
|
||||
if (list.getAdapter() != null) {
|
||||
list.getAdapter().notifyDataSetChanged();
|
||||
}
|
||||
@@ -442,7 +442,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
|
||||
if (msg.getFromId() != prevMsg.getFromId() && !singleMsg) {
|
||||
DcContact contact = dcContext.getContact(msg.getFromId());
|
||||
result.append(msg.getSenderName(contact, false)).append(":\n");
|
||||
result.append(msg.getSenderName(contact)).append(":\n");
|
||||
}
|
||||
if (msg.getType() == DcMsg.DC_MSG_TEXT || (singleMsg && !msg.getText().isEmpty())) {
|
||||
result.append(msg.getText());
|
||||
@@ -704,7 +704,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
index++;
|
||||
}
|
||||
}
|
||||
dcContext.markseenMsgs(ids);
|
||||
Util.runOnAnyBackgroundThread(() -> dcContext.markseenMsgs(ids));
|
||||
}
|
||||
|
||||
|
||||
@@ -810,7 +810,10 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
DozeReminder.dozeReminderTapped(getContext());
|
||||
}
|
||||
else if(messageRecord.getInfoType() == DcMsg.DC_INFO_WEBXDC_INFO_MESSAGE) {
|
||||
scrollMaybeSmoothToMsgId(messageRecord.getParent().getId());
|
||||
WebxdcActivity.openWebxdcActivity(getContext(), messageRecord.getParent(), messageRecord.getWebxdcHref());
|
||||
}
|
||||
else if (!TextUtils.isEmpty(messageRecord.getPOILocation()) && messageRecord.getType() == DcMsg.DC_MSG_TEXT && !messageRecord.hasHtml()) {
|
||||
WebxdcActivity.openMaps(getContext(), getListAdapter().getChat().getId(), "index.html#"+messageRecord.getPOILocation());
|
||||
}
|
||||
else {
|
||||
String self_mail = dcContext.getConfig("configured_mail_user");
|
||||
@@ -841,20 +844,18 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuoteClicked(DcMsg messageRecord) {
|
||||
DcMsg quoted = messageRecord.getQuotedMsg();
|
||||
if (quoted == null) {
|
||||
Log.i(TAG, "Clicked on a quote whose original message we never had.");
|
||||
private void jumpToOriginal(DcMsg original) {
|
||||
if (original == null) {
|
||||
Log.i(TAG, "Clicked on a quote or jump-to-original whose original message was deleted/non-existing.");
|
||||
Toast.makeText(getContext(), R.string.ConversationFragment_quoted_message_not_found, Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
int foreignChatId = quoted.getChatId();
|
||||
int foreignChatId = original.getChatId();
|
||||
if (foreignChatId != 0 && foreignChatId != chatId) {
|
||||
Intent intent = new Intent(getActivity(), ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.CHAT_ID_EXTRA, foreignChatId);
|
||||
int start = DcMsg.getMessagePosition(quoted, dcContext);
|
||||
int start = DcMsg.getMessagePosition(original, dcContext);
|
||||
intent.putExtra(ConversationActivity.STARTING_POSITION_EXTRA, start);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
((ConversationActivity) getActivity()).hideSoftKeyboard();
|
||||
@@ -864,10 +865,20 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
Log.e(TAG, "Activity was null");
|
||||
}
|
||||
} else {
|
||||
scrollMaybeSmoothToMsgId(quoted.getId());
|
||||
scrollMaybeSmoothToMsgId(original.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onJumpToOriginalClicked(DcMsg messageRecord) {
|
||||
jumpToOriginal(dcContext.getMsg(messageRecord.getOriginalMsgId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onQuoteClicked(DcMsg messageRecord) {
|
||||
jumpToOriginal(messageRecord.getQuotedMsg());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShowFullClicked(DcMsg messageRecord) {
|
||||
Intent intent = new Intent(getActivity(), FullMsgActivity.class);
|
||||
@@ -911,11 +922,9 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
|
||||
mode.setTitle("1");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getActivity().getWindow();
|
||||
statusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
Window window = getActivity().getWindow();
|
||||
statusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
|
||||
setCorrectMenuVisibility(menu);
|
||||
ConversationAdaptiveActionsToolbar.adjustMenuActions(menu, 10, requireActivity().getWindow().getDecorView().getMeasuredWidth());
|
||||
@@ -932,9 +941,7 @@ public class ConversationFragment extends MessageSelectorFragment
|
||||
((ConversationAdapter)list.getAdapter()).clearSelection();
|
||||
list.getAdapter().notifyDataSetChanged();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getActivity().getWindow().setStatusBarColor(statusBarColor);
|
||||
}
|
||||
getActivity().getWindow().setStatusBarColor(statusBarColor);
|
||||
|
||||
actionMode = null;
|
||||
hideAddReactionView();
|
||||
|
||||
@@ -22,12 +22,10 @@ import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
@@ -56,7 +54,6 @@ import org.thoughtcrime.securesms.components.DocumentView;
|
||||
import org.thoughtcrime.securesms.components.QuoteView;
|
||||
import org.thoughtcrime.securesms.components.VcardView;
|
||||
import org.thoughtcrime.securesms.components.WebxdcView;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||
import org.thoughtcrime.securesms.mms.DocumentSlide;
|
||||
@@ -69,10 +66,10 @@ import org.thoughtcrime.securesms.mms.StickerSlide;
|
||||
import org.thoughtcrime.securesms.mms.VcardSlide;
|
||||
import org.thoughtcrime.securesms.reactions.ReactionsConversationView;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Linkifier;
|
||||
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
|
||||
import org.thoughtcrime.securesms.util.MarkdownUtil;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.views.Stub;
|
||||
@@ -104,6 +101,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
protected ViewGroup bodyBubble;
|
||||
protected ReactionsConversationView reactionsView;
|
||||
protected View replyView;
|
||||
protected View jumptoView;
|
||||
@Nullable private QuoteView quoteView;
|
||||
private ConversationItemFooter footer;
|
||||
private TextView groupSender;
|
||||
@@ -112,6 +110,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
protected ViewGroup contactPhotoHolder;
|
||||
private ViewGroup container;
|
||||
private Button msgActionButton;
|
||||
private Button showFullButton;
|
||||
|
||||
private @NonNull Stub<ConversationItemThumbnail> mediaThumbnailStub;
|
||||
private @NonNull Stub<AudioView> audioViewStub;
|
||||
@@ -157,7 +156,9 @@ public class ConversationItem extends BaseConversationItem
|
||||
this.quoteView = findViewById(R.id.quote_view);
|
||||
this.container = findViewById(R.id.container);
|
||||
this.replyView = findViewById(R.id.reply_icon);
|
||||
this.jumptoView = findViewById(R.id.jumpto_icon);
|
||||
this.msgActionButton = findViewById(R.id.msg_action_button);
|
||||
this.showFullButton = findViewById(R.id.show_full_button);
|
||||
|
||||
setOnClickListener(new ClickListener(null));
|
||||
|
||||
@@ -177,12 +178,23 @@ public class ConversationItem extends BaseConversationItem
|
||||
{
|
||||
bind(messageRecord, dcChat, batchSelected, pulseHighlight, recipients);
|
||||
this.glideRequests = glideRequests;
|
||||
this.showSender = dcContext.isCommunity() || (dcChat.isMultiUser() && !messageRecord.isOutgoing()) || messageRecord.getOverrideSenderName() != null;
|
||||
this.showSender = dcContext.isCommunity() || ((dcChat.isMultiUser() || dcChat.isSelfTalk()) && !messageRecord.isOutgoing()) || messageRecord.getOverrideSenderName() != null;
|
||||
|
||||
if (showSender) {
|
||||
this.dcContact = dcContext.getContact(messageRecord.getFromId());
|
||||
}
|
||||
|
||||
if (dcChat.isSelfTalk() && messageRecord.getOriginalMsgId() != 0) {
|
||||
jumptoView.setVisibility(View.VISIBLE);
|
||||
jumptoView.setOnClickListener(view -> {
|
||||
if (eventListener != null) {
|
||||
eventListener.onJumpToOriginalClicked(messageRecord);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
jumptoView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
setGutterSizes(messageRecord, showSender);
|
||||
setMessageShape(messageRecord);
|
||||
setMediaAttributes(messageRecord, showSender);
|
||||
@@ -385,7 +397,6 @@ public class ConversationItem extends BaseConversationItem
|
||||
private void setBodyText(DcMsg messageRecord) {
|
||||
bodyText.setClickable(false);
|
||||
bodyText.setFocusable(false);
|
||||
bodyText.setTextSize(TypedValue.COMPLEX_UNIT_SP, Prefs.getMessageBodyTextSize(context));
|
||||
|
||||
String text = messageRecord.getText();
|
||||
|
||||
@@ -399,7 +410,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
else {
|
||||
Spannable spannable = (Spannable) MarkdownUtil.toMarkdown(context, text);
|
||||
if (batchSelected.isEmpty()) {
|
||||
spannable = EmojiTextView.linkify(spannable);
|
||||
spannable = Linkifier.linkify(spannable);
|
||||
}
|
||||
bodyText.setText(spannable);
|
||||
bodyText.setVisibility(View.VISIBLE);
|
||||
@@ -407,6 +418,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
|
||||
int downloadState = messageRecord.getDownloadState();
|
||||
if (downloadState == DcMsg.DC_DOWNLOAD_AVAILABLE || downloadState == DcMsg.DC_DOWNLOAD_FAILURE || downloadState == DcMsg.DC_DOWNLOAD_IN_PROGRESS) {
|
||||
showFullButton.setVisibility(View.GONE);
|
||||
msgActionButton.setVisibility(View.VISIBLE);
|
||||
if (downloadState==DcMsg.DC_DOWNLOAD_IN_PROGRESS) {
|
||||
msgActionButton.setEnabled(false);
|
||||
@@ -427,6 +439,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
}
|
||||
});
|
||||
} else if (messageRecord.getType() == DcMsg.DC_MSG_WEBXDC) {
|
||||
showFullButton.setVisibility(View.GONE);
|
||||
msgActionButton.setVisibility(View.VISIBLE);
|
||||
msgActionButton.setEnabled(true);
|
||||
msgActionButton.setText(webxdcViewStub.get().isCommunity()? R.string.join: R.string.start_app);
|
||||
@@ -439,10 +452,11 @@ public class ConversationItem extends BaseConversationItem
|
||||
});
|
||||
}
|
||||
else if (messageRecord.hasHtml()) {
|
||||
msgActionButton.setVisibility(View.VISIBLE);
|
||||
msgActionButton.setEnabled(true);
|
||||
msgActionButton.setText(R.string.show_full_message);
|
||||
msgActionButton.setOnClickListener(view -> {
|
||||
msgActionButton.setVisibility(View.GONE);
|
||||
showFullButton.setVisibility(View.VISIBLE);
|
||||
showFullButton.setEnabled(true);
|
||||
showFullButton.setText(R.string.show_full_message);
|
||||
showFullButton.setOnClickListener(view -> {
|
||||
if (eventListener != null && batchSelected.isEmpty()) {
|
||||
eventListener.onShowFullClicked(messageRecord);
|
||||
} else {
|
||||
@@ -451,6 +465,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
});
|
||||
} else {
|
||||
msgActionButton.setVisibility(View.GONE);
|
||||
showFullButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,9 +507,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
audioViewStub.get().setAudio(new AudioSlide(context, messageRecord), duration);
|
||||
audioViewStub.get().setOnClickListener(passthroughClickListener);
|
||||
audioViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
audioViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
audioViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -512,9 +525,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
documentViewStub.get().setDocument(new DocumentSlide(context, messageRecord));
|
||||
documentViewStub.get().setDocumentClickListener(new ThumbnailClickListener());
|
||||
documentViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
documentViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
documentViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -531,9 +542,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
webxdcViewStub.get().setWebxdc(messageRecord, context.getString(R.string.webxdc_app));
|
||||
webxdcViewStub.get().setWebxdcClickListener(new ThumbnailClickListener());
|
||||
webxdcViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
webxdcViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
webxdcViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -551,9 +560,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
vcardViewStub.get().setVcardClickListener(new ThumbnailClickListener());
|
||||
vcardViewStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
vcardViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
vcardViewStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -589,9 +596,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
mediaThumbnailStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
mediaThumbnailStub.get().setOnClickListener(passthroughClickListener);
|
||||
mediaThumbnailStub.get().showShade(TextUtils.isEmpty(messageRecord.getText()));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
mediaThumbnailStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
mediaThumbnailStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
setThumbnailOutlineCorners(messageRecord, showSender);
|
||||
|
||||
@@ -614,9 +619,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
stickerStub.get().setThumbnailClickListener(new StickerClickListener());
|
||||
stickerStub.get().setOnLongClickListener(passthroughClickListener);
|
||||
stickerStub.get().setOnClickListener(passthroughClickListener);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
stickerStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
}
|
||||
stickerStub.get().setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
|
||||
|
||||
ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
ViewUtil.updateLayoutParams(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
@@ -677,7 +680,7 @@ public class ConversationItem extends BaseConversationItem
|
||||
contactPhoto.setVisibility(View.GONE);
|
||||
} else {
|
||||
int color = messageRecord.getSenderColor();
|
||||
Recipient recipient = new Recipient(context, dcContact, messageRecord.getSenderName(dcContact, !dcContext.isCommunity()), color);
|
||||
Recipient recipient = new Recipient(context, dcContact, messageRecord.getSenderName(dcContact), color);
|
||||
contactPhoto.setAvatar(glideRequests, recipient, true);
|
||||
contactPhoto.setVisibility(View.VISIBLE);
|
||||
}
|
||||
@@ -802,14 +805,14 @@ public class ConversationItem extends BaseConversationItem
|
||||
|
||||
if (messageRecord.isForwarded()) {
|
||||
if (showSender && dcContact !=null) {
|
||||
this.groupSender.setText(context.getString(R.string.forwarded_by, messageRecord.getSenderName(dcContact, false)));
|
||||
this.groupSender.setText(context.getString(R.string.forwarded_by, messageRecord.getSenderName(dcContact)));
|
||||
} else {
|
||||
this.groupSender.setText(context.getString(R.string.forwarded_message));
|
||||
}
|
||||
this.groupSender.setTextColor(context.getResources().getColor(R.color.unknown_sender));
|
||||
}
|
||||
else if (showSender && dcContact !=null) {
|
||||
this.groupSender.setText(messageRecord.getSenderName(dcContact, true));
|
||||
this.groupSender.setText(messageRecord.getSenderName(dcContact));
|
||||
int color = messageRecord.getSenderColor();
|
||||
this.groupSender.setTextColor(Util.rgbToArgbColor(color!=0? color : dcContact.getColor()));
|
||||
}
|
||||
|
||||
@@ -174,9 +174,7 @@ class ConversationItemSwipeCallback extends ItemTouchHelper.SimpleCallback {
|
||||
vibrate(viewHolder.itemView.getContext());
|
||||
}
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
recyclerView.cancelPendingInputEvents();
|
||||
}
|
||||
recyclerView.cancelPendingInputEvents();
|
||||
}
|
||||
|
||||
private static void resetProgress(RecyclerView.ViewHolder viewHolder) {
|
||||
@@ -199,11 +197,7 @@ class ConversationItemSwipeCallback extends ItemTouchHelper.SimpleCallback {
|
||||
}
|
||||
|
||||
private static float getSignFromDirection(@NonNull View view) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -1f : 1f;
|
||||
} else {
|
||||
return 1f;
|
||||
}
|
||||
return view.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -1f : 1f;
|
||||
}
|
||||
|
||||
private static boolean sameSign(float dX, float sign) {
|
||||
|
||||
@@ -19,7 +19,9 @@ package org.thoughtcrime.securesms;
|
||||
import static org.thoughtcrime.securesms.ConversationActivity.CHAT_ID_EXTRA;
|
||||
import static org.thoughtcrime.securesms.ConversationActivity.STARTING_POSITION_EXTRA;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_ADDRESS;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_ENABLED;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SERVER_FLAGS;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_URL;
|
||||
import static org.thoughtcrime.securesms.util.RelayUtil.acquireRelayMessageContent;
|
||||
import static org.thoughtcrime.securesms.util.RelayUtil.getDirectSharingChatId;
|
||||
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedTitle;
|
||||
@@ -66,6 +68,7 @@ import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.connect.DirectShareUtil;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
|
||||
import org.thoughtcrime.securesms.qr.QrActivity;
|
||||
import org.thoughtcrime.securesms.qr.QrCodeHandler;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
@@ -86,7 +89,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
public static final String CLEAR_NOTIFICATIONS = "clear_notifications";
|
||||
public static final String ACCOUNT_ID_EXTRA = "account_id";
|
||||
public static final String FROM_WELCOME = "from_welcome";
|
||||
public static final String WARN_CANNOT_ENCRYPT = "warn_cannot_encrypt";
|
||||
|
||||
private ConversationListFragment conversationListFragment;
|
||||
public TextView title;
|
||||
@@ -110,7 +112,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
// it is not needed to keep all past update messages, however, when deleted, also the strings should be deleted.
|
||||
try {
|
||||
DcContext dcContext = DcHelper.getContext(this);
|
||||
final String deviceMsgLabel = "update_1_46_0l_android";
|
||||
final String deviceMsgLabel = "update_1_50_0_android";
|
||||
if (!dcContext.wasDeviceMsgEverAdded(deviceMsgLabel)) {
|
||||
DcMsg msg = null;
|
||||
if (!getIntent().getBooleanExtra(FROM_WELCOME, false)) {
|
||||
@@ -121,7 +123,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
// Util.copy(inputStream, new FileOutputStream(outputFile));
|
||||
// msg.setFile(outputFile, "image/jpeg");
|
||||
|
||||
msg.setText(getString(R.string.update_1_46_android, "https://get.delta.chat/#changelogs"));
|
||||
msg.setText(getString(R.string.update_1_50_android, "https://raw.githubusercontent.com/ArcaneChat/android/refs/heads/main/CHANGELOG.md"));
|
||||
}
|
||||
dcContext.addDeviceMsg(deviceMsgLabel, msg);
|
||||
|
||||
@@ -186,7 +188,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
|
||||
TooltipCompat.setTooltipText(selfAvatar, getText(R.string.switch_account));
|
||||
selfAvatar.setOnClickListener(v -> AccountManager.getInstance().showSwitchAccountMenu(this));
|
||||
title.setOnClickListener(v -> {
|
||||
findViewById(R.id.avatar_and_title).setOnClickListener(v -> {
|
||||
if (!isRelayingMessageContent(this)) {
|
||||
AccountManager.getInstance().showSwitchAccountMenu(this);
|
||||
}
|
||||
@@ -254,6 +256,10 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
if (isFinishing()) {
|
||||
Log.w(TAG, "Activity is finishing, aborting onNewIntent()");
|
||||
return;
|
||||
}
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
refresh();
|
||||
@@ -265,17 +271,12 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
DcContext dcContext = DcHelper.getContext(this);
|
||||
int accountId = getIntent().getIntExtra(ACCOUNT_ID_EXTRA, dcContext.getAccountId());
|
||||
if (getIntent().getBooleanExtra(CLEAR_NOTIFICATIONS, false)) {
|
||||
DcHelper.getNotificationCenter(this).removeAllNotifiations(accountId);
|
||||
DcHelper.getNotificationCenter(this).removeAllNotifications(accountId);
|
||||
}
|
||||
if (accountId != dcContext.getAccountId()) {
|
||||
AccountManager.getInstance().switchAccountAndStartActivity(this, accountId);
|
||||
}
|
||||
|
||||
String warnAddr = getIntent().getStringExtra(WARN_CANNOT_ENCRYPT);
|
||||
if (!TextUtils.isEmpty(warnAddr)) {
|
||||
DcHelper.showEncryptionRequiredDialog(this, warnAddr);
|
||||
}
|
||||
|
||||
refreshAvatar();
|
||||
refreshUnreadIndicator();
|
||||
refreshTitle();
|
||||
@@ -299,19 +300,15 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
}
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
} else {
|
||||
DcContext dcContext = DcHelper.getContext(this);
|
||||
DcContact self = dcContext.getContact(DcContact.DC_CONTACT_ID_SELF);
|
||||
String name = dcContext.getConfig("displayname");
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
name = self.getAddr();
|
||||
}
|
||||
title.setText(name);
|
||||
title.setText(DcHelper.getContext(this).getName());
|
||||
selfAvatar.setConnectivity(DcHelper.getContext(this).getConnectivity());
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshAvatar() {
|
||||
if (selfAvatarContainer == null) return;
|
||||
|
||||
if (isRelayingMessageContent(this)) {
|
||||
selfAvatarContainer.setVisibility(View.GONE);
|
||||
} else {
|
||||
@@ -367,6 +364,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
refreshTitle();
|
||||
invalidateOptionsMenu();
|
||||
DirectShareUtil.triggerRefreshDirectShare(this);
|
||||
}
|
||||
|
||||
@@ -377,20 +375,16 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
|
||||
if (!isRelayingMessageContent(this)) {
|
||||
inflater.inflate(R.menu.text_secure_normal, menu);
|
||||
MenuItem item = menu.findItem(R.id.menu_global_map);
|
||||
if (Prefs.isLocationStreamingEnabled(this)) {
|
||||
item.setVisible(true);
|
||||
}
|
||||
|
||||
if (!Prefs.isLocationStreamingEnabled(this)) {
|
||||
menu.findItem(R.id.menu_global_map).setVisible(false);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
MenuCompat.setGroupDividerEnabled(menu, true);
|
||||
} else{
|
||||
menu.setGroupVisible(R.id.extra_services, false);
|
||||
menu.findItem(R.id.menu_global_map).setVisible(Prefs.isLocationStreamingEnabled(this));
|
||||
MenuItem proxyItem = menu.findItem(R.id.menu_proxy_settings);
|
||||
if (TextUtils.isEmpty(DcHelper.get(this, CONFIG_PROXY_URL))) {
|
||||
proxyItem.setVisible(false);
|
||||
} else {
|
||||
boolean proxyEnabled = DcHelper.getInt(this, CONFIG_PROXY_ENABLED) == 1;
|
||||
proxyItem.setIcon(proxyEnabled? R.drawable.ic_proxy_enabled_24 : R.drawable.ic_proxy_disabled_24);
|
||||
proxyItem.setVisible(true);
|
||||
}
|
||||
MenuCompat.setGroupDividerEnabled(menu, true);
|
||||
}
|
||||
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
@@ -453,17 +447,17 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
case R.id.menu_global_map:
|
||||
WebxdcActivity.openMaps(this, 0);
|
||||
return true;
|
||||
case R.id.menu_proxy_settings:
|
||||
startActivity(new Intent(this, ProxySettingsActivity.class));
|
||||
return true;
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
case R.id.menu_all_media:
|
||||
startActivity(new Intent(this, ProfileActivity.class));
|
||||
return true;
|
||||
case R.id.menu_webxdc_apps_store:
|
||||
handleShowBot("xstore@testrun.org", "OPENPGP4FPR:37DC2B704A2AE2F6A96235CE0C3A0EBCA4F5801D#a=xstore%40testrun.org&n=&i=-1IGtynaivZ&s=JqHsvvcDmnW");
|
||||
return true;
|
||||
case R.id.menu_public_bots:
|
||||
handleShowBot("publicbots@testrun.org", "OPENPGP4FPR:4DB8117591B27184A903FF7E9F469E00D40E13E7#a=publicbots%40testrun.org&n=Public%20Bots&i=zSuQpFtBa_Q&s=weLMu1-o1o1");
|
||||
handleShowBot("botsindex@arcanechat.me", "https://i.delta.chat/#67889B0362BEDBFEE05ACD92C1D737FA632A9582&a=botsindex%40arcanechat.me&n=Public%20Bots&i=336MTEz38EH-RJxM9OKWygYK&s=TpVVGK6C4KrJmRG0bwHLalXt");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -565,7 +559,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
private void shareInvite() {
|
||||
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("text/plain");
|
||||
String inviteURL = Util.QrDataToInviteURL(DcHelper.getContext(this).getSecurejoinQr(0));
|
||||
String inviteURL = DcHelper.getContext(this).getSecurejoinQr(0);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, getString(R.string.invite_friends_text, inviteURL));
|
||||
startActivity(Intent.createChooser(intent, getString(R.string.chat_share_with_title)));
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ import com.b44t.messenger.DcMsg;
|
||||
import org.thoughtcrime.securesms.ConversationListAdapter.ItemClickListener;
|
||||
import org.thoughtcrime.securesms.components.recyclerview.DeleteItemAnimator;
|
||||
import org.thoughtcrime.securesms.components.reminder.DozeReminder;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
|
||||
@@ -29,7 +29,6 @@ public class ConversationListItemInboxZero extends LinearLayout implements Binda
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public ConversationListItemInboxZero(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
@@ -31,12 +30,9 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.soundcloud.android.crop.Crop;
|
||||
|
||||
import org.thoughtcrime.securesms.components.AvatarSelector;
|
||||
import org.thoughtcrime.securesms.components.InputAwareLayout;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||
@@ -54,7 +50,7 @@ import java.security.SecureRandom;
|
||||
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public class CreateProfileActivity extends BaseActionBarActivity implements EmojiKeyboardProvider.EmojiEventListener {
|
||||
public class CreateProfileActivity extends BaseActionBarActivity {
|
||||
|
||||
private static final String TAG = CreateProfileActivity.class.getSimpleName();
|
||||
|
||||
@@ -66,7 +62,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
private ImageView avatar;
|
||||
private EditText name;
|
||||
private EditText overridenName;
|
||||
private MediaKeyboard emojiDrawer;
|
||||
private EditText statusView;
|
||||
|
||||
private boolean fromWelcome;
|
||||
@@ -91,7 +86,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
attachmentManager = new AttachmentManager(this, () -> {});
|
||||
avatarChanged = false;
|
||||
initializeResources();
|
||||
initializeEmojiInput();
|
||||
initializeProfileName();
|
||||
initializeProfileAvatar();
|
||||
initializeStatusText();
|
||||
@@ -130,15 +124,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
||||
if (container.getCurrentInput() == emojiDrawer) {
|
||||
container.hideAttachedInput(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
|
||||
Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults);
|
||||
@@ -161,10 +146,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
case ScribbleActivity.SCRIBBLE_REQUEST_CODE:
|
||||
setAvatarView(data.getData());
|
||||
break;
|
||||
|
||||
case Crop.REQUEST_CROP:
|
||||
setAvatarView(Crop.getOutput(data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +187,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
this.avatar = ViewUtil.findById(this, R.id.avatar);
|
||||
this.name = ViewUtil.findById(this, R.id.name_text);
|
||||
this.overridenName = ViewUtil.findById(this, R.id.overriden_name);
|
||||
this.emojiDrawer = ViewUtil.findById(this, R.id.emoji_drawer);
|
||||
this.container = ViewUtil.findById(this, R.id.container);
|
||||
this.statusView = ViewUtil.findById(this, R.id.status_text);
|
||||
|
||||
@@ -261,33 +241,6 @@ public class CreateProfileActivity extends BaseActionBarActivity implements Emoj
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEmojiSelected(String emoji) {
|
||||
final int start = name.getSelectionStart();
|
||||
final int end = name.getSelectionEnd();
|
||||
|
||||
name.getText().replace(Math.min(start, end), Math.max(start, end), emoji);
|
||||
name.setSelection(start + emoji.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyEvent(KeyEvent keyEvent) {
|
||||
name.dispatchKeyEvent(keyEvent);
|
||||
}
|
||||
|
||||
private void initializeMediaKeyboardProviders(@NonNull MediaKeyboard mediaKeyboard) {
|
||||
boolean isSystemEmojiPreferred = Prefs.isSystemEmojiPreferred(this);
|
||||
if (!isSystemEmojiPreferred) {
|
||||
mediaKeyboard.setProviders(0, new EmojiKeyboardProvider(this, this));
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeEmojiInput() {
|
||||
initializeMediaKeyboardProviders(emojiDrawer);
|
||||
this.name.setOnClickListener(v -> container.showSoftkey(name));
|
||||
}
|
||||
|
||||
private void initializeStatusText() {
|
||||
String status = DcHelper.get(this, DcHelper.CONFIG_SELF_STATUS);
|
||||
statusView.setText(status);
|
||||
|
||||
@@ -17,7 +17,6 @@ import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.loader.app.LoaderManager;
|
||||
|
||||
import com.b44t.messenger.DcChat;
|
||||
@@ -26,7 +25,6 @@ import com.b44t.messenger.DcContext;
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.soundcloud.android.crop.Crop;
|
||||
|
||||
import org.thoughtcrime.securesms.components.AvatarSelector;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
@@ -221,22 +219,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
updateGroup(groupName);
|
||||
} else {
|
||||
verified = !broadcast && allMembersVerified();
|
||||
if (verified && getAdapter().getContacts().size() == 1) {
|
||||
new AlertDialog.Builder(this)
|
||||
.setMessage(R.string.create_verified_group_ask)
|
||||
.setNeutralButton(R.string.learn_more, (d, w) -> DcHelper.openHelp(this, "#e2eeguarantee"))
|
||||
.setPositiveButton(R.string.yes, (d, w) -> {
|
||||
createGroup(groupName);
|
||||
})
|
||||
.setNegativeButton(R.string.no, (d, w) -> {
|
||||
verified = false;
|
||||
createGroup(groupName);
|
||||
})
|
||||
.setCancelable(true)
|
||||
.show();
|
||||
} else {
|
||||
createGroup(groupName);
|
||||
}
|
||||
createGroup(groupName);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -360,10 +343,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
case ScribbleActivity.SCRIBBLE_REQUEST_CODE:
|
||||
setAvatarView(data.getData());
|
||||
break;
|
||||
|
||||
case Crop.REQUEST_CROP:
|
||||
setAvatarView(Crop.getOutput(data));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_ENABLED;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_URL;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
@@ -13,6 +18,7 @@ import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.text.util.Linkify;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
@@ -35,7 +41,6 @@ import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.google.zxing.integration.android.IntentIntegrator;
|
||||
import com.google.zxing.integration.android.IntentResult;
|
||||
import com.soundcloud.android.crop.Crop;
|
||||
|
||||
import org.thoughtcrime.securesms.components.AvatarSelector;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
@@ -47,8 +52,10 @@ import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints;
|
||||
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
|
||||
import org.thoughtcrime.securesms.qr.RegistrationQrActivity;
|
||||
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
@@ -64,7 +71,7 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
private static final String DCACCOUNT = "dcaccount";
|
||||
private static final String DCLOGIN = "dclogin";
|
||||
private static final String INSTANCES_URL = "https://delta.chat/chatmail";
|
||||
private static final String DEFAULT_CHATMAIL_HOST = "nine.testrun.org";
|
||||
private static final String DEFAULT_CHATMAIL_HOST = "arcanechat.me";
|
||||
|
||||
public static final String QR_ACCOUNT_EXTRA = "qr_account_extra";
|
||||
public static final String FROM_WELCOME = "from_welcome";
|
||||
@@ -132,13 +139,37 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
handleIntent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
menu.clear();
|
||||
getMenuInflater().inflate(R.menu.instant_onboarding_menu, menu);
|
||||
MenuItem proxyItem = menu.findItem(R.id.menu_proxy_settings);
|
||||
if (TextUtils.isEmpty(DcHelper.get(this, CONFIG_PROXY_URL))) {
|
||||
proxyItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
|
||||
} else {
|
||||
boolean proxyEnabled = DcHelper.getInt(this, CONFIG_PROXY_ENABLED) == 1;
|
||||
proxyItem.setIcon(proxyEnabled? R.drawable.ic_proxy_enabled_24 : R.drawable.ic_proxy_disabled_24);
|
||||
proxyItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
}
|
||||
return super.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
getOnBackPressedDispatcher().onBackPressed();
|
||||
return true;
|
||||
case R.id.menu_proxy_settings:
|
||||
startActivity(new Intent(this, ProxySettingsActivity.class));
|
||||
return true;
|
||||
case R.id.menu_view_log:
|
||||
startActivity(new Intent(this, LogViewActivity.class));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -160,14 +191,16 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
setAvatarView(data.getData());
|
||||
break;
|
||||
|
||||
case Crop.REQUEST_CROP:
|
||||
setAvatarView(Crop.getOutput(data));
|
||||
break;
|
||||
|
||||
case IntentIntegrator.REQUEST_CODE:
|
||||
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
|
||||
if (scanResult != null && scanResult.getFormatName() != null) {
|
||||
setProviderFromQr(scanResult.getContents());
|
||||
String qrRaw = data.getStringExtra(RegistrationQrActivity.QRDATA_EXTRA);
|
||||
if (qrRaw == null) {
|
||||
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
|
||||
if (scanResult != null && scanResult.getFormatName() != null) {
|
||||
qrRaw = scanResult.getContents();
|
||||
}
|
||||
}
|
||||
if (qrRaw != null) {
|
||||
setProviderFromQr(qrRaw);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -209,20 +242,32 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
final String displayName = name.getText().toString();
|
||||
DcHelper.set(this, DcHelper.CONFIG_DISPLAY_NAME, TextUtils.isEmpty(displayName)? null : displayName);
|
||||
// Save display name and avatar in the unconfigured profile.
|
||||
// If the currently selected profile is configured, then this means that rollbackAccountCreation()
|
||||
// was called (see handleOnBackPressed() above), i.e. the newly created profile was removed already
|
||||
// and we can't save the display name & avatar.
|
||||
if (DcHelper.getContext(this).isConfigured() == 0) {
|
||||
final String displayName = name.getText().toString();
|
||||
DcHelper.set(this, DcHelper.CONFIG_DISPLAY_NAME, TextUtils.isEmpty(displayName) ? null : displayName);
|
||||
|
||||
if (avatarChanged) {
|
||||
try {
|
||||
AvatarHelper.setSelfAvatar(InstantOnboardingActivity.this, avatarBmp);
|
||||
Prefs.setProfileAvatarId(InstantOnboardingActivity.this, new SecureRandom().nextInt());
|
||||
avatarChanged = false;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to save avatar", e);
|
||||
if (avatarChanged) {
|
||||
try {
|
||||
AvatarHelper.setSelfAvatar(InstantOnboardingActivity.this, avatarBmp);
|
||||
Prefs.setProfileAvatarId(InstantOnboardingActivity.this, new SecureRandom().nextInt());
|
||||
avatarChanged = false;
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to save avatar", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
@@ -284,38 +329,21 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
|
||||
privacyPolicyBtn.setOnClickListener(view -> {
|
||||
if (!isDcLogin) {
|
||||
WebViewActivity.openUrlInBrowser(this, "https://" + providerHost + "/privacy.html");
|
||||
IntentUtils.showInBrowser(this, "https://" + providerHost + "/privacy.html");
|
||||
}
|
||||
});
|
||||
|
||||
signUpBtn.setOnClickListener(view -> createProfile());
|
||||
|
||||
Button otherOptionsBtn = findViewById(R.id.other_options_button);
|
||||
otherOptionsBtn.setOnClickListener(view -> showOtherOptionsDialog());
|
||||
}
|
||||
|
||||
private void showOtherOptionsDialog() {
|
||||
View view = View.inflate(this, R.layout.signup_options_view, null);
|
||||
AlertDialog signUpDialog = new AlertDialog.Builder(this)
|
||||
.setView(view)
|
||||
.setTitle(R.string.instant_onboarding_show_more_instances)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create();
|
||||
|
||||
view.findViewById(R.id.use_other_server).setOnClickListener((v) -> {
|
||||
WebViewActivity.openUrlInBrowser(this, INSTANCES_URL);
|
||||
signUpDialog.dismiss();
|
||||
findViewById(R.id.use_other_server).setOnClickListener((v) -> {
|
||||
IntentUtils.showInBrowser(this, INSTANCES_URL);
|
||||
});
|
||||
view.findViewById(R.id.login_button).setOnClickListener((v) -> {
|
||||
findViewById(R.id.login_button).setOnClickListener((v) -> {
|
||||
startRegistrationActivity();
|
||||
signUpDialog.dismiss();
|
||||
});
|
||||
view.findViewById(R.id.scan_qr_button).setOnClickListener((v) -> {
|
||||
findViewById(R.id.scan_qr_button).setOnClickListener((v) -> {
|
||||
new IntentIntegrator(this).setCaptureActivity(RegistrationQrActivity.class).initiateScan();
|
||||
signUpDialog.dismiss();
|
||||
});
|
||||
|
||||
signUpDialog.show();
|
||||
}
|
||||
|
||||
private void startRegistrationActivity() {
|
||||
@@ -330,7 +358,11 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
privacyPolicyBtn.setText(getString(R.string.qrlogin_ask_login, providerHost));
|
||||
} else {
|
||||
signUpBtn.setText(R.string.instant_onboarding_create);
|
||||
privacyPolicyBtn.setTextColor(getResources().getColor(R.color.def_accent));
|
||||
|
||||
try (TypedArray typedArray = obtainStyledAttributes(new int[]{R.attr.colorAccent})) {
|
||||
privacyPolicyBtn.setTextColor(typedArray.getColor(0, Color.BLACK));
|
||||
}
|
||||
|
||||
if (DEFAULT_CHATMAIL_HOST.equals(providerHost)) {
|
||||
privacyPolicyBtn.setText(getString(R.string.instant_onboarding_agree_default2, providerHost));
|
||||
} else {
|
||||
@@ -373,7 +405,6 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
progressUpdate((int)progress);
|
||||
} else if (progress==1000/*done*/) {
|
||||
DcHelper.getAccounts(this).startIo();
|
||||
dcContext.assumeSingleDevice();
|
||||
progressSuccess();
|
||||
}
|
||||
}
|
||||
@@ -386,7 +417,7 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
|
||||
private void progressError(String data2) {
|
||||
progressDialog.dismiss();
|
||||
maybeShowConfigurationError(this, data2);
|
||||
WelcomeActivity.maybeShowConfigurationError(this, data2);
|
||||
}
|
||||
|
||||
private void progressSuccess() {
|
||||
@@ -399,22 +430,6 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
|
||||
finishAffinity();
|
||||
}
|
||||
|
||||
public static void maybeShowConfigurationError(Activity activity, String data2) {
|
||||
if (data2 != null && !data2.isEmpty()) {
|
||||
AlertDialog d = new AlertDialog.Builder(activity)
|
||||
.setMessage(data2)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.create();
|
||||
d.show();
|
||||
try {
|
||||
//noinspection ConstantConditions
|
||||
Linkify.addLinks((TextView) d.findViewById(android.R.id.message), Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES);
|
||||
} catch(NullPointerException e) {
|
||||
Log.e(TAG, "Linkify failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
private void createProfile() {
|
||||
if (TextUtils.isEmpty(this.name.getText())) {
|
||||
|
||||
@@ -62,16 +62,16 @@ public class LocalHelpActivity extends WebViewActivity
|
||||
webView.scrollTo(0, 0);
|
||||
return true;
|
||||
case R.id.learn_more:
|
||||
openOnlineUrl("https://delta.chat");
|
||||
openOnlineUrl("https://arcanechat.me");
|
||||
return true;
|
||||
case R.id.privacy_policy:
|
||||
openOnlineUrl("https://delta.chat/gdpr");
|
||||
openOnlineUrl("https://arcanechat.me/privacy.html");
|
||||
return true;
|
||||
case R.id.contribute:
|
||||
openOnlineUrl("https://github.com/deltachat/deltachat-android");
|
||||
openOnlineUrl("https://arcanechat.me/#contribute");
|
||||
return true;
|
||||
case R.id.report_issue:
|
||||
openOnlineUrl("https://github.com/deltachat/deltachat-android/issues");
|
||||
openOnlineUrl("https://github.com/ArcaneChat/android/issues");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
@@ -35,6 +36,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.PermissionChecker;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.b44t.messenger.DcContext;
|
||||
@@ -195,12 +197,11 @@ public class LogViewFragment extends Fragment {
|
||||
asMegs(info.maxMemory()));
|
||||
}
|
||||
|
||||
@TargetApi(VERSION_CODES.KITKAT)
|
||||
public static String getMemoryClass(Context context) {
|
||||
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
String lowMem = "";
|
||||
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.KITKAT && activityManager.isLowRamDevice()) {
|
||||
if (activityManager.isLowRamDevice()) {
|
||||
lowMem = ", low-mem device";
|
||||
}
|
||||
return activityManager.getMemoryClass() + lowMem;
|
||||
@@ -250,9 +251,14 @@ public class LogViewFragment extends Fragment {
|
||||
|
||||
Locale locale = Util.getLocale();
|
||||
builder.append("lang=").append(locale.toString()).append("\n");
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
boolean isRtl = Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL;
|
||||
builder.append("rtl=").append(isRtl).append("\n");
|
||||
boolean isRtl = Util.getLayoutDirection(context) == View.LAYOUT_DIRECTION_RTL;
|
||||
builder.append("rtl=").append(isRtl).append("\n");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
boolean notifPermGranted = PermissionChecker.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) == PermissionChecker.PERMISSION_GRANTED;
|
||||
builder.append("post-notifications-granted=").append(notifPermGranted).append("\n");
|
||||
} else {
|
||||
builder.append("post-notifications-granted=<not needed>").append("\n");
|
||||
}
|
||||
|
||||
final String token = FcmReceiveService.getToken();
|
||||
|
||||
@@ -207,7 +207,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
messageRecord = null;
|
||||
long date = getIntent().getLongExtra(DATE_EXTRA, 0);
|
||||
long size = getIntent().getLongExtra(SIZE_EXTRA, 0);
|
||||
initialMedia = new MediaItem(null, getIntent().getData(), getIntent().getType(),
|
||||
initialMedia = new MediaItem(null, getIntent().getData(), null, getIntent().getType(),
|
||||
DcMsg.DC_MSG_NO_ID, date, size, false);
|
||||
|
||||
if (address != null) {
|
||||
@@ -218,7 +218,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
} else {
|
||||
messageRecord = dcContext.getMsg(msgId);
|
||||
initialMedia = new MediaItem(Recipient.fromChat(context, msgId), Uri.fromFile(messageRecord.getFileAsFile()),
|
||||
messageRecord.getFilemime(), messageRecord.getId(), messageRecord.getDateReceived(),
|
||||
messageRecord.getFilename(), messageRecord.getFilemime(), messageRecord.getId(), messageRecord.getDateReceived(),
|
||||
messageRecord.getFilebytes(), messageRecord.isOutgoing());
|
||||
conversationRecipient = Recipient.fromChat(context, msgId);
|
||||
}
|
||||
@@ -232,12 +232,11 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
// if you search for the place where the media are loaded, go to 'onCreateLoader'.
|
||||
|
||||
Log.w(TAG, "Loading Part URI: " + initialMedia);
|
||||
|
||||
if (messageRecord != null) {
|
||||
getSupportLoaderManager().restartLoader(0, null, this);
|
||||
} else {
|
||||
mediaPager.setAdapter(new SingleItemPagerAdapter(this, GlideApp.with(this),
|
||||
getWindow(), initialMedia.uri, initialMedia.type, initialMedia.size));
|
||||
getWindow(), initialMedia.uri, initialMedia.name, initialMedia.type, initialMedia.size));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,7 +312,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
private void performSavetoDisk(@NonNull MediaItem mediaItem) {
|
||||
SaveAttachmentTask saveTask = new SaveAttachmentTask(MediaPreviewActivity.this);
|
||||
long saveDate = (mediaItem.date > 0) ? mediaItem.date : System.currentTimeMillis();
|
||||
saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Attachment(mediaItem.uri, mediaItem.type, saveDate, null));
|
||||
saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Attachment(mediaItem.uri, mediaItem.type, saveDate, mediaItem.name));
|
||||
}
|
||||
|
||||
private void showInChat() {
|
||||
@@ -473,9 +472,12 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
MediaItemAdapter adapter = (MediaItemAdapter)mediaPager.getAdapter();
|
||||
|
||||
if (adapter != null) {
|
||||
MediaItem item = adapter.getMediaItemFor(position);
|
||||
if (item.recipient != null) item.recipient.removeListener(MediaPreviewActivity.this);
|
||||
|
||||
try {
|
||||
MediaItem item = adapter.getMediaItemFor(position);
|
||||
if (item.recipient != null) item.recipient.removeListener(MediaPreviewActivity.this);
|
||||
} catch (IllegalArgumentException e) {
|
||||
Log.w(TAG, "Ignoring invalid position index");
|
||||
}
|
||||
adapter.pause(position);
|
||||
}
|
||||
}
|
||||
@@ -486,18 +488,20 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
private final GlideRequests glideRequests;
|
||||
private final Window window;
|
||||
private final Uri uri;
|
||||
private final String name;
|
||||
private final String mediaType;
|
||||
private final long size;
|
||||
|
||||
private final LayoutInflater inflater;
|
||||
|
||||
SingleItemPagerAdapter(@NonNull Context context, @NonNull GlideRequests glideRequests,
|
||||
@NonNull Window window, @NonNull Uri uri, @NonNull String mediaType,
|
||||
@NonNull Window window, @NonNull Uri uri, @Nullable String name, @NonNull String mediaType,
|
||||
long size)
|
||||
{
|
||||
this.glideRequests = glideRequests;
|
||||
this.window = window;
|
||||
this.uri = uri;
|
||||
this.name = name;
|
||||
this.mediaType = mediaType;
|
||||
this.size = size;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
@@ -519,7 +523,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
MediaView mediaView = itemView.findViewById(R.id.media_view);
|
||||
|
||||
try {
|
||||
mediaView.set(glideRequests, window, uri, mediaType, size, true);
|
||||
mediaView.set(glideRequests, window, uri, name, mediaType, size, true);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
@@ -539,7 +543,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public MediaItem getMediaItemFor(int position) {
|
||||
return new MediaItem(null, uri, mediaType, DcMsg.DC_MSG_NO_ID, -1, -1, true);
|
||||
return new MediaItem(null, uri, name, mediaType, DcMsg.DC_MSG_NO_ID, -1, -1, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -604,7 +608,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
try {
|
||||
//noinspection ConstantConditions
|
||||
mediaView.set(glideRequests, window, Uri.fromFile(msg.getFileAsFile()),
|
||||
mediaView.set(glideRequests, window, Uri.fromFile(msg.getFileAsFile()), msg.getFilename(),
|
||||
msg.getFilemime(), msg.getFilebytes(), autoplay);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
@@ -633,6 +637,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
return new MediaItem(Recipient.fromChat(context, msg.getId()),
|
||||
Uri.fromFile(msg.getFileAsFile()),
|
||||
msg.getFilename(),
|
||||
msg.getFilemime(),
|
||||
msg.getId(),
|
||||
msg.getDateReceived(),
|
||||
@@ -655,6 +660,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
private static class MediaItem {
|
||||
private final @Nullable Recipient recipient;
|
||||
private final @NonNull Uri uri;
|
||||
private final @Nullable String name;
|
||||
private final @NonNull String type;
|
||||
private final int msgId;
|
||||
private final long date;
|
||||
@@ -663,6 +669,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
private MediaItem(@Nullable Recipient recipient,
|
||||
@NonNull Uri uri,
|
||||
@Nullable String name,
|
||||
@NonNull String type,
|
||||
int msgId,
|
||||
long date,
|
||||
@@ -671,6 +678,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
|
||||
{
|
||||
this.recipient = recipient;
|
||||
this.uri = uri;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.msgId = msgId;
|
||||
this.date = date;
|
||||
|
||||
@@ -111,8 +111,6 @@ public class NewConversationActivity extends ContactSelectionActivity {
|
||||
int contactId = dcContext.lookupContactIdByAddr(addr);
|
||||
if (contactId!=0 && dcContext.getChatIdByContactId(contactId)!=0) {
|
||||
openConversation(dcContext.getChatIdByContactId(contactId));
|
||||
} else if (contactId == 0 && dcContext.isChatmail()) {
|
||||
DcHelper.showEncryptionRequiredDialog(this, addr);
|
||||
} else {
|
||||
String nameNAddr = contactId == 0 ? addr : dcContext.getContact(contactId).getNameNAddr();
|
||||
new AlertDialog.Builder(this)
|
||||
|
||||
@@ -153,6 +153,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
|
||||
menu.findItem(R.id.share).setVisible(false);
|
||||
}
|
||||
} else {
|
||||
menu.findItem(R.id.menu_clone).setVisible(false);
|
||||
canReceive = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,13 @@ public class ProfileDocumentsFragment
|
||||
|
||||
noMedia.setVisibility(recyclerView.getAdapter().getItemCount() > 0 ? View.GONE : View.VISIBLE);
|
||||
if (chatId == DC_CHAT_NO_CHAT) {
|
||||
noMedia.setText(R.string.tab_all_media_empty_hint);
|
||||
if (showWebxdc) {
|
||||
noMedia.setText(R.string.all_apps_empty_hint);
|
||||
} else if (!showAudio){
|
||||
noMedia.setText(R.string.all_files_empty_hint);
|
||||
} else {
|
||||
noMedia.setText(R.string.tab_all_media_empty_hint);
|
||||
}
|
||||
} else if (showAudio) {
|
||||
noMedia.setText(R.string.tab_audio_empty_hint);
|
||||
} else if (showWebxdc) {
|
||||
@@ -229,11 +235,9 @@ public class ProfileDocumentsFragment
|
||||
mode.getMenuInflater().inflate(R.menu.profile_context, menu);
|
||||
mode.setTitle("1");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
setCorrectMenuVisibility(menu);
|
||||
return true;
|
||||
}
|
||||
@@ -283,9 +287,7 @@ public class ProfileDocumentsFragment
|
||||
actionMode = null;
|
||||
getListAdapter().clearSelection();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,11 +219,9 @@ public class ProfileGalleryFragment
|
||||
mode.getMenuInflater().inflate(R.menu.profile_context, menu);
|
||||
mode.setTitle("1");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
setCorrectMenuVisibility(menu);
|
||||
return true;
|
||||
}
|
||||
@@ -269,9 +267,7 @@ public class ProfileGalleryFragment
|
||||
actionMode = null;
|
||||
getListAdapter().clearSelection();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,11 +268,9 @@ public class ProfileSettingsFragment extends Fragment
|
||||
menu.findItem(R.id.menu_select_all).setVisible(false);
|
||||
mode.setTitle("1");
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
}
|
||||
Window window = getActivity().getWindow();
|
||||
originalStatusBarColor = window.getStatusBarColor();
|
||||
window.setStatusBarColor(getResources().getColor(R.color.action_mode_status_bar));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -314,9 +312,7 @@ public class ProfileSettingsFragment extends Fragment
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
actionMode = null;
|
||||
adapter.clearSelection();
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
getActivity().getWindow().setStatusBarColor(originalStatusBarColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,14 @@ import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
|
||||
import org.thoughtcrime.securesms.util.Linkifier;
|
||||
import org.thoughtcrime.securesms.util.LongClickMovementMethod;
|
||||
|
||||
public class ProfileStatusItem extends LinearLayout {
|
||||
|
||||
private EmojiTextView statusTextView;
|
||||
private AppCompatTextView statusTextView;
|
||||
private final PassthroughClickListener passthroughClickListener = new PassthroughClickListener();
|
||||
|
||||
public ProfileStatusItem(Context context) {
|
||||
@@ -32,7 +34,7 @@ public class ProfileStatusItem extends LinearLayout {
|
||||
}
|
||||
|
||||
public void set(String status) {
|
||||
statusTextView.setText(EmojiTextView.linkify(new SpannableString(status)));
|
||||
statusTextView.setText(Linkifier.linkify(new SpannableString(status)));
|
||||
}
|
||||
|
||||
private class PassthroughClickListener implements View.OnLongClickListener, View.OnClickListener {
|
||||
|
||||
@@ -12,15 +12,10 @@ import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SEND_SECURITY;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SEND_SERVER;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SEND_USER;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SERVER_FLAGS;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_ENABLED;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_HOST;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_PASSWORD;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_PORT;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SOCKS5_USER;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_ENABLED;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.getContext;
|
||||
import static org.thoughtcrime.securesms.service.IPCAddAccountsService.ACCOUNT_DATA;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
@@ -35,7 +30,6 @@ import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
@@ -59,9 +53,11 @@ import com.google.android.material.textfield.TextInputEditText;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.permissions.Permissions;
|
||||
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.views.ProgressDialog;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -96,7 +92,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
Spinner certCheck;
|
||||
|
||||
private SwitchCompat proxySwitch;
|
||||
private Group proxyGroup;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
@@ -127,15 +122,11 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
authMethod = findViewById(R.id.auth_method);
|
||||
certCheck = findViewById(R.id.cert_check);
|
||||
|
||||
proxyGroup = findViewById(R.id.socks5_group);
|
||||
proxySwitch = findViewById(R.id.socks5_switch);
|
||||
proxySwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
proxyGroup.setVisibility(isChecked? advancedGroup.getVisibility() : View.GONE);
|
||||
proxySwitch = findViewById(R.id.proxy_settings);
|
||||
proxySwitch.setOnClickListener(l -> {
|
||||
proxySwitch.setChecked(!proxySwitch.isChecked()); // revert toggle
|
||||
startActivity(new Intent(this, ProxySettingsActivity.class));
|
||||
});
|
||||
TextInputEditText proxyHostInput = findViewById(R.id.socks5_host_text);
|
||||
TextInputEditText proxyPortInput = findViewById(R.id.socks5_port_text);
|
||||
proxyHostInput.setOnFocusChangeListener((view, focused) -> focusListener(view, focused, VerificationType.SERVER));
|
||||
proxyPortInput.setOnFocusChangeListener((view, focused) -> focusListener(view, focused, VerificationType.PORT));
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
@@ -161,7 +152,16 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
advancedIcon.setOnClickListener(l -> onAdvancedSettings());
|
||||
advancedIcon.setRotation(45);
|
||||
viewLogText.setOnClickListener((view) -> showLog());
|
||||
|
||||
boolean isConfigured = DcHelper.isConfigured(getApplicationContext());
|
||||
boolean expandAdvanced = false;
|
||||
String strVal;
|
||||
int intVal;
|
||||
|
||||
intVal = DcHelper.getInt(this, CONFIG_PROXY_ENABLED);
|
||||
proxySwitch.setChecked(intVal == 1);
|
||||
expandAdvanced = expandAdvanced || intVal == 1;
|
||||
|
||||
if (isConfigured) {
|
||||
String email = DcHelper.get(this, CONFIG_ADDRESS);
|
||||
emailInput.setText(email);
|
||||
@@ -170,10 +170,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
}
|
||||
passwordInput.setText(DcHelper.get(this, CONFIG_MAIL_PASSWORD));
|
||||
|
||||
boolean expandAdvanced = false;
|
||||
String strVal;
|
||||
int intVal;
|
||||
|
||||
TextInputEditText imapLoginInput = findViewById(R.id.imap_login_text);
|
||||
strVal = DcHelper.get(this, CONFIG_MAIL_USER);
|
||||
imapLoginInput.setText(strVal);
|
||||
@@ -188,7 +184,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
expandAdvanced = expandAdvanced || !TextUtils.isEmpty(strVal);
|
||||
|
||||
intVal = DcHelper.getInt(this, CONFIG_MAIL_SECURITY);
|
||||
imapSecurity.setSelection(intVal);
|
||||
imapSecurity.setSelection(ViewUtil.checkBounds(intVal, imapSecurity));
|
||||
expandAdvanced = expandAdvanced || intVal != 0;
|
||||
|
||||
TextInputEditText smtpLoginInput = findViewById(R.id.smtp_login_text);
|
||||
@@ -210,20 +206,9 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
expandAdvanced = expandAdvanced || !TextUtils.isEmpty(strVal);
|
||||
|
||||
intVal = DcHelper.getInt(this, CONFIG_SEND_SECURITY);
|
||||
smtpSecurity.setSelection(intVal);
|
||||
smtpSecurity.setSelection(ViewUtil.checkBounds(intVal, smtpSecurity));
|
||||
expandAdvanced = expandAdvanced || intVal != 0;
|
||||
|
||||
intVal = DcHelper.getInt(this, CONFIG_SOCKS5_ENABLED);
|
||||
proxySwitch.setChecked(intVal == 1);
|
||||
expandAdvanced = expandAdvanced || intVal == 1;
|
||||
|
||||
proxyHostInput.setText(DcHelper.get(this, CONFIG_SOCKS5_HOST));
|
||||
proxyPortInput.setText(DcHelper.get(this, CONFIG_SOCKS5_PORT));
|
||||
TextInputEditText proxyUserInput = findViewById(R.id.socks5_user_text);
|
||||
TextInputEditText proxyPasswordInput = findViewById(R.id.socks5_password_text);
|
||||
proxyUserInput.setText(DcHelper.get(this, CONFIG_SOCKS5_USER));
|
||||
proxyPasswordInput.setText(DcHelper.get(this, CONFIG_SOCKS5_PASSWORD));
|
||||
|
||||
int serverFlags = DcHelper.getInt(this, CONFIG_SERVER_FLAGS);
|
||||
int sel = 0;
|
||||
if((serverFlags&DcContext.DC_LP_AUTH_OAUTH2)!=0) {
|
||||
@@ -236,14 +221,15 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
}
|
||||
// /remove gmail oauth2
|
||||
}
|
||||
authMethod.setSelection(sel);
|
||||
authMethod.setSelection(ViewUtil.checkBounds(sel, authMethod));
|
||||
expandAdvanced = expandAdvanced || sel != 0;
|
||||
|
||||
int certCheckFlags = DcHelper.getInt(this, "imap_certificate_checks");
|
||||
certCheck.setSelection(certCheckFlags);
|
||||
expandAdvanced = expandAdvanced || certCheckFlags != 0;
|
||||
|
||||
if (expandAdvanced) { onAdvancedSettings(); }
|
||||
int imapCertificateChecks = DcHelper.getInt(this, "imap_certificate_checks");
|
||||
if (imapCertificateChecks == 3) {
|
||||
imapCertificateChecks = 2; // 3 is a deprecated alias for 2
|
||||
}
|
||||
certCheck.setSelection(ViewUtil.checkBounds(imapCertificateChecks, certCheck));
|
||||
expandAdvanced = expandAdvanced || imapCertificateChecks != 0;
|
||||
} else if (getIntent() != null && getIntent().getBundleExtra(ACCOUNT_DATA) != null) {
|
||||
// Companion app might have sent account data
|
||||
Bundle b = getIntent().getBundleExtra(ACCOUNT_DATA);
|
||||
@@ -261,6 +247,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
}
|
||||
}
|
||||
|
||||
if (expandAdvanced) { onAdvancedSettings(); }
|
||||
registerForEvents();
|
||||
}
|
||||
|
||||
@@ -272,6 +259,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
dynamicTheme.onResume(this);
|
||||
proxySwitch.setChecked(DcHelper.getInt(this, CONFIG_PROXY_ENABLED) == 1);
|
||||
}
|
||||
|
||||
private void showLog() {
|
||||
@@ -449,7 +437,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
.setPositiveButton(R.string.perm_continue, (dialog, which)-> {
|
||||
// pass control to browser, we'll be back in business at (**)
|
||||
activity.oauth2Requested = System.currentTimeMillis();
|
||||
IntentUtils.showBrowserIntent(activity, oauth2url);
|
||||
IntentUtils.showInBrowser(activity, oauth2url);
|
||||
oauth2started.set(true);
|
||||
})
|
||||
.setCancelable(false)
|
||||
@@ -504,11 +492,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
if (provider!=null) {
|
||||
String url = provider.getOverviewPage();
|
||||
if(!url.isEmpty()) {
|
||||
try {
|
||||
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(this, R.string.no_browser_installed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
IntentUtils.showInBrowser(this, url);
|
||||
} else {
|
||||
// this should normally not happen
|
||||
Toast.makeText(this, "ErrProviderWithoutUrl", Toast.LENGTH_LONG).show();
|
||||
@@ -574,12 +558,10 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
private void onAdvancedSettings() {
|
||||
boolean advancedViewVisible = advancedGroup.getVisibility() == View.VISIBLE;
|
||||
if (advancedViewVisible) {
|
||||
proxyGroup.setVisibility(View.GONE);
|
||||
advancedGroup.setVisibility(View.GONE);
|
||||
advancedIcon.setRotation(45);
|
||||
} else {
|
||||
advancedGroup.setVisibility(View.VISIBLE);
|
||||
if (proxySwitch.isChecked()) proxyGroup.setVisibility(View.VISIBLE);
|
||||
advancedIcon.setRotation(0);
|
||||
}
|
||||
}
|
||||
@@ -621,15 +603,6 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
|
||||
setConfig(R.id.smtp_port_text, CONFIG_SEND_PORT, true);
|
||||
setConfig(R.id.smtp_login_text, CONFIG_SEND_USER, false);
|
||||
setConfig(R.id.smtp_password_text, CONFIG_SEND_PASSWORD, false);
|
||||
if (proxySwitch.isChecked()) {
|
||||
DcHelper.getContext(this).setConfigInt(CONFIG_SOCKS5_ENABLED, 1);
|
||||
setConfig(R.id.socks5_host_text, CONFIG_SOCKS5_HOST, true);
|
||||
setConfig(R.id.socks5_port_text, CONFIG_SOCKS5_PORT, true);
|
||||
setConfig(R.id.socks5_user_text, CONFIG_SOCKS5_USER, true);
|
||||
setConfig(R.id.socks5_password_text, CONFIG_SOCKS5_PASSWORD, false);
|
||||
} else {
|
||||
DcHelper.getContext(this).setConfigInt(CONFIG_SOCKS5_ENABLED, 0);
|
||||
}
|
||||
|
||||
DcHelper.getContext(this).setConfigInt(CONFIG_MAIL_SECURITY, imapSecurity.getSelectedItemPosition());
|
||||
DcHelper.getContext(this).setConfigInt(CONFIG_SEND_SECURITY, smtpSecurity.getSelectedItemPosition());
|
||||
|
||||
@@ -58,6 +58,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
|
||||
{
|
||||
private static final String TAG = ShareActivity.class.getSimpleName();
|
||||
|
||||
public static final String EXTRA_ACC_ID = "acc_id";
|
||||
public static final String EXTRA_CHAT_ID = "chat_id";
|
||||
public static final String EXTRA_MSG_TYPE = "msg_type";
|
||||
public static final String EXTRA_MSG_SUBJECT = "msg_subject";
|
||||
@@ -213,14 +214,10 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
|
||||
}
|
||||
|
||||
private void handleResolvedMedia(Intent intent) {
|
||||
int accId = intent.getIntExtra(EXTRA_ACC_ID, -1);
|
||||
int chatId = intent.getIntExtra(EXTRA_CHAT_ID, -1);
|
||||
String msgType = intent.getStringExtra(EXTRA_MSG_TYPE);
|
||||
|
||||
String shortcutId = intent.getStringExtra(ShortcutManagerCompat.EXTRA_SHORTCUT_ID);
|
||||
if (chatId == -1 && shortcutId != null) {
|
||||
chatId = Integer.parseInt(shortcutId);
|
||||
}
|
||||
|
||||
String[] extraEmail = getIntent().getStringArrayExtra(Intent.EXTRA_EMAIL);
|
||||
/*
|
||||
usually, external app will try to start "e-mail sharing" intent, providing it:
|
||||
@@ -259,28 +256,21 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
|
||||
}
|
||||
*/
|
||||
|
||||
String addr = null;
|
||||
if(chatId == -1 && extraEmail != null && extraEmail.length > 0) {
|
||||
addr = extraEmail[0];
|
||||
final String addr = extraEmail[0];
|
||||
int contactId = dcContext.lookupContactIdByAddr(addr);
|
||||
|
||||
if(contactId != 0 || !dcContext.isChatmail()) {
|
||||
if(contactId == 0) {
|
||||
contactId = dcContext.createContact(null, addr);
|
||||
}
|
||||
|
||||
chatId = dcContext.createChatByContactId(contactId);
|
||||
addr = null;
|
||||
if(contactId == 0) {
|
||||
contactId = dcContext.createContact(null, addr);
|
||||
}
|
||||
|
||||
chatId = dcContext.createChatByContactId(contactId);
|
||||
}
|
||||
Intent composeIntent;
|
||||
if (addr != null) {
|
||||
composeIntent = new Intent(this, ConversationListActivity.class);
|
||||
composeIntent.putExtra(ConversationListActivity.WARN_CANNOT_ENCRYPT, addr);
|
||||
startActivity(composeIntent);
|
||||
} else if (chatId != -1) {
|
||||
if (accId != -1 && chatId != -1) {
|
||||
composeIntent = getBaseShareIntent(ConversationActivity.class);
|
||||
composeIntent.putExtra(ConversationActivity.CHAT_ID_EXTRA, chatId);
|
||||
composeIntent.putExtra(ConversationActivity.ACCOUNT_ID_EXTRA, accId);
|
||||
RelayUtil.setSharedType(composeIntent, msgType);
|
||||
RelayUtil.setSharedUris(composeIntent, resolvedExtras);
|
||||
startActivity(composeIntent);
|
||||
|
||||
@@ -26,6 +26,7 @@ import androidx.webkit.ProxyController;
|
||||
import androidx.webkit.ProxyConfig;
|
||||
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
|
||||
public class WebViewActivity extends PassphraseRequiredActionBarActivity
|
||||
implements SearchView.OnQueryTextListener,
|
||||
@@ -278,16 +279,8 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity
|
||||
// onBackPressed() can be overwritten by derived classes as needed.
|
||||
// the default behavior (close the activity) is just fine eg. for Webxdc, Connectivity, HTML-mails
|
||||
|
||||
public static void openUrlInBrowser(Context context, String url) {
|
||||
try {
|
||||
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Toast.makeText(context, R.string.no_browser_installed, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean openOnlineUrl(String url) {
|
||||
openUrlInBrowser(this, url);
|
||||
IntentUtils.showInBrowser(this, url);
|
||||
// returning `true` causes the WebView to abort loading
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
@@ -40,11 +39,13 @@ import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.DcMsg;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
import org.thoughtcrime.securesms.util.JsonUtils;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
@@ -54,6 +55,8 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -63,7 +66,9 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
private static final String EXTRA_ACCOUNT_ID = "accountId";
|
||||
private static final String EXTRA_APP_MSG_ID = "appMessageId";
|
||||
private static final String EXTRA_HIDE_ACTION_BAR = "hideActionBar";
|
||||
private static final String EXTRA_HREF = "href";
|
||||
private static final int REQUEST_CODE_FILE_PICKER = 51426;
|
||||
private static long lastOpenTime = 0;
|
||||
|
||||
private ValueCallback<Uri[]> filePathCallback;
|
||||
private DcContext dcContext;
|
||||
@@ -71,12 +76,23 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
private DcMsg dcAppMsg;
|
||||
private String baseURL;
|
||||
private String sourceCodeUrl = "";
|
||||
private String selfAddr;
|
||||
private int sendUpdateMaxSize;
|
||||
private int sendUpdateInterval;
|
||||
private boolean internetAccess = false;
|
||||
private boolean hideActionBar = false;
|
||||
|
||||
public static void openMaps(Context context, int chatId) {
|
||||
openMaps(context, chatId, "");
|
||||
}
|
||||
|
||||
public static void openMaps(Context context, int chatId, String href) {
|
||||
DcContext dcContext = DcHelper.getContext(context);
|
||||
int msgId = dcContext.initWebxdcIntegration(chatId);
|
||||
int msgId = 0;
|
||||
final int mapsVersion = 2;
|
||||
if (dcContext.getConfigInt("ui.maps_version") >= mapsVersion) {
|
||||
msgId = dcContext.initWebxdcIntegration(chatId);
|
||||
}
|
||||
if (msgId == 0) {
|
||||
try {
|
||||
InputStream inputStream = context.getResources().getAssets().open("webxdc/maps.xdc");
|
||||
@@ -91,34 +107,36 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
Toast.makeText(context, "Cannot get maps.xdc, see log for details.", Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
dcContext.setConfigInt("ui.maps_version", mapsVersion);
|
||||
}
|
||||
openWebxdcActivity(context, msgId, true);
|
||||
openWebxdcActivity(context, msgId, true, href);
|
||||
}
|
||||
|
||||
public static void openWebxdcActivity(Context context, DcMsg instance) {
|
||||
openWebxdcActivity(context, instance.getId(), false);
|
||||
openWebxdcActivity(context, instance, "");
|
||||
}
|
||||
|
||||
public static void openWebxdcActivity(Context context, int msgId, boolean hideActionBar) {
|
||||
public static void openWebxdcActivity(Context context, DcMsg instance, String href) {
|
||||
openWebxdcActivity(context, instance.getId(), false, href);
|
||||
}
|
||||
|
||||
public static void openWebxdcActivity(Context context, int msgId, boolean hideActionBar, String href) {
|
||||
if (!Util.isClickedRecently()) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (Prefs.isDeveloperModeEnabled(context)) {
|
||||
WebView.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
context.startActivity(getWebxdcIntent(context, msgId, hideActionBar));
|
||||
} else {
|
||||
Toast.makeText(context, "At least Android 5.0 (Lollipop) required for Webxdc.", Toast.LENGTH_LONG).show();
|
||||
if (Prefs.isDeveloperModeEnabled(context)) {
|
||||
WebView.setWebContentsDebuggingEnabled(true);
|
||||
}
|
||||
context.startActivity(getWebxdcIntent(context, msgId, hideActionBar, href));
|
||||
}
|
||||
}
|
||||
|
||||
private static Intent getWebxdcIntent(Context context, int msgId, boolean hideActionBar) {
|
||||
private static Intent getWebxdcIntent(Context context, int msgId, boolean hideActionBar, String href) {
|
||||
DcContext dcContext = DcHelper.getContext(context);
|
||||
Intent intent = new Intent(context, WebxdcActivity.class);
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.putExtra(EXTRA_ACCOUNT_ID, dcContext.getAccountId());
|
||||
intent.putExtra(EXTRA_APP_MSG_ID, msgId);
|
||||
intent.putExtra(EXTRA_HIDE_ACTION_BAR, hideActionBar);
|
||||
intent.putExtra(EXTRA_HREF, href);
|
||||
return intent;
|
||||
}
|
||||
|
||||
@@ -129,7 +147,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
.putExtra(ConversationActivity.CHAT_ID_EXTRA, dcContext.getMsg(msgId).getChatId())
|
||||
.setAction(Intent.ACTION_VIEW);
|
||||
|
||||
final Intent webxdcIntent = getWebxdcIntent(context, msgId, false);
|
||||
final Intent webxdcIntent = getWebxdcIntent(context, msgId, false, "");
|
||||
|
||||
return TaskStackBuilder.create(context)
|
||||
.addNextIntentWithParentStack(chatIntent)
|
||||
@@ -197,6 +215,9 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
// this is needed here because if the app is opened while already in landscape mode, onConfigurationChanged() is not triggered
|
||||
setScreenMode(getResources().getConfiguration());
|
||||
}
|
||||
selfAddr = info.optString("self_addr");
|
||||
sendUpdateMaxSize = info.optInt("send_update_max_size");
|
||||
sendUpdateInterval = info.optInt("send_update_interval");
|
||||
|
||||
toggleFakeProxy(!internetAccess);
|
||||
|
||||
@@ -213,7 +234,20 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
webView.setNetworkAvailable(internetAccess); // this does not block network but sets `window.navigator.isOnline` in js land
|
||||
webView.addJavascriptInterface(new InternalJSApi(), "InternalJSApi");
|
||||
|
||||
webView.loadUrl(this.baseURL + "/index.html");
|
||||
String extraHref = b.getString(EXTRA_HREF, "");
|
||||
if (TextUtils.isEmpty(extraHref)) {
|
||||
extraHref = "index.html";
|
||||
}
|
||||
|
||||
String href = baseURL + "/" + extraHref;
|
||||
String encodedHref = "";
|
||||
try {
|
||||
encodedHref = URLEncoder.encode(href, Charsets.UTF_8.name());
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
webView.loadUrl(this.baseURL + "/webxdc_bootstrap324567869.html?i=1&href=" + encodedHref);
|
||||
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
final DcChat chat = dcContext.getChat(dcAppMsg.getChatId());
|
||||
@@ -223,8 +257,21 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
DcHelper.getNotificationCenter(this).updateVisibleWebxdc(dcContext.getAccountId(), dcAppMsg.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
DcHelper.getNotificationCenter(this).clearVisibleWebxdc();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
lastOpenTime = System.currentTimeMillis();
|
||||
DcHelper.getEventCenter(this.getApplicationContext()).removeObservers(this);
|
||||
leaveRealtimeChannel();
|
||||
super.onDestroy();
|
||||
@@ -247,7 +294,10 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
addToHomeScreen(this, dcAppMsg.getId());
|
||||
return true;
|
||||
case R.id.source_code:
|
||||
openUrlInBrowser(this, sourceCodeUrl);
|
||||
IntentUtils.showInBrowser(this, sourceCodeUrl);
|
||||
return true;
|
||||
case R.id.show_in_chat:
|
||||
showInChat();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -334,7 +384,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
res = new WebResourceResponse("text/plain", "UTF-8", targetStream);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !internetAccess) {
|
||||
if (!internetAccess) {
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Content-Security-Policy",
|
||||
"default-src 'self'; "
|
||||
@@ -353,9 +403,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
}
|
||||
|
||||
private void callJavaScriptFunction(String func) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
webView.evaluateJavascript("window." + func + ";", null);
|
||||
}
|
||||
webView.evaluateJavascript("document.getElementById('frame').contentWindow." + func + ";", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -394,6 +442,13 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
}
|
||||
}
|
||||
|
||||
private void showInChat() {
|
||||
Intent intent = new Intent(this, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.CHAT_ID_EXTRA, dcAppMsg.getChatId());
|
||||
intent.putExtra(ConversationActivity.STARTING_POSITION_EXTRA, DcMsg.getMessagePosition(dcAppMsg, dcContext));
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
public static void addToHomeScreen(Activity activity, int msgId) {
|
||||
Context context = activity.getApplicationContext();
|
||||
try {
|
||||
@@ -469,13 +524,23 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
return dcContext.isCommunity();
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public int sendUpdateMaxSize() {
|
||||
return WebxdcActivity.this.sendUpdateMaxSize;
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public int sendUpdateInterval() {
|
||||
return WebxdcActivity.this.sendUpdateInterval;
|
||||
}
|
||||
|
||||
@JavascriptInterface
|
||||
public String selfAddr() {
|
||||
if (dcContext.isCommunity() && !TextUtils.isEmpty(dcContext.getCommunityUser())) {
|
||||
int flags = Base64.NO_WRAP | Base64.NO_PADDING | Base64.URL_SAFE;
|
||||
return Base64.encodeToString(dcContext.getCommunityUser().getBytes(), flags);
|
||||
}
|
||||
return dcContext.getConfig("configured_addr");
|
||||
return WebxdcActivity.this.selfAddr;
|
||||
}
|
||||
|
||||
/** @noinspection unused*/
|
||||
@@ -493,9 +558,9 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
|
||||
|
||||
/** @noinspection unused*/
|
||||
@JavascriptInterface
|
||||
public boolean sendStatusUpdate(String payload, String descr) {
|
||||
public boolean sendStatusUpdate(String payload) {
|
||||
Log.i(TAG, "sendStatusUpdate");
|
||||
if (!WebxdcActivity.this.dcContext.sendWebxdcStatusUpdate(WebxdcActivity.this.dcAppMsg.getId(), payload, descr)) {
|
||||
if (!WebxdcActivity.this.dcContext.sendWebxdcStatusUpdate(WebxdcActivity.this.dcAppMsg.getId(), payload)) {
|
||||
DcChat dcChat = WebxdcActivity.this.dcContext.getChat(WebxdcActivity.this.dcAppMsg.getChatId());
|
||||
Toast.makeText(WebxdcActivity.this,
|
||||
dcChat.isContactRequest() ?
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.MenuItem;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.rpc.HttpResponse;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
|
||||
import org.thoughtcrime.securesms.util.IntentUtils;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class WebxdcStoreActivity extends PassphraseRequiredActionBarActivity {
|
||||
private static final String TAG = WebxdcStoreActivity.class.getSimpleName();
|
||||
|
||||
private DcContext dcContext;
|
||||
private Rpc rpc;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle state, boolean ready) {
|
||||
setContentView(R.layout.web_view_activity);
|
||||
rpc = DcHelper.getRpc(this);
|
||||
dcContext = DcHelper.getContext(this);
|
||||
WebView webView = findViewById(R.id.webview);
|
||||
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
actionBar.setTitle(R.string.webxdc_apps);
|
||||
}
|
||||
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
String ext = MediaUtil.getFileExtensionFromUrl(Uri.parse(url).getPath());
|
||||
if ("xdc".equals(ext)) {
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
try {
|
||||
HttpResponse httpResponse = rpc.getHttpResponse(dcContext.getAccountId(), url);
|
||||
Uri uri = PersistentBlobProvider.getInstance().create(WebxdcStoreActivity.this, httpResponse.getBlob(), "application/octet-stream", "app.xdc");
|
||||
Intent intent = new Intent();
|
||||
intent.setData(uri);
|
||||
setResult(Activity.RESULT_OK, intent);
|
||||
finish();
|
||||
} catch (RpcException e) {
|
||||
e.printStackTrace();
|
||||
Util.runOnMain(() -> Toast.makeText(WebxdcStoreActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
IntentUtils.showInBrowser(WebxdcStoreActivity.this, url);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
return shouldOverrideUrlLoading(view, request.getUrl().toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
|
||||
return interceptRequest(request.getUrl().toString());
|
||||
}
|
||||
});
|
||||
|
||||
WebSettings webSettings = webView.getSettings();
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
webSettings.setAllowFileAccess(false);
|
||||
webSettings.setAllowContentAccess(false);
|
||||
webSettings.setGeolocationEnabled(false);
|
||||
webSettings.setAllowFileAccessFromFileURLs(false);
|
||||
webSettings.setAllowUniversalAccessFromFileURLs(false);
|
||||
webSettings.setDatabaseEnabled(true);
|
||||
webSettings.setDomStorageEnabled(true);
|
||||
webView.setNetworkAvailable(true); // this does not block network but sets `window.navigator.isOnline` in js land
|
||||
|
||||
webView.loadUrl(Prefs.getWebxdcStoreUrl(this));
|
||||
}
|
||||
|
||||
private WebResourceResponse interceptRequest(String url) {
|
||||
WebResourceResponse res = null;
|
||||
try {
|
||||
if (url == null) {
|
||||
throw new Exception("no url specified");
|
||||
}
|
||||
HttpResponse httpResponse = rpc.getHttpResponse(dcContext.getAccountId(), url);
|
||||
String mimeType = httpResponse.getMimetype();
|
||||
if (mimeType == null) {
|
||||
mimeType = "application/octet-stream";
|
||||
}
|
||||
|
||||
ByteArrayInputStream data = new ByteArrayInputStream(httpResponse.getBlob());
|
||||
res = new WebResourceResponse(mimeType, httpResponse.getEncoding(), data);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ByteArrayInputStream data = new ByteArrayInputStream(("Could not load apps. Are you online?\n\n" + e.getMessage()).getBytes());
|
||||
res = new WebResourceResponse("text/plain", "UTF-8", data);
|
||||
}
|
||||
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
headers.put("access-control-allow-origin", "*");
|
||||
res.setResponseHeaders(headers);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -69,26 +69,9 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
super.onCreate(bundle);
|
||||
setContentView(R.layout.welcome_activity);
|
||||
|
||||
Button signUpButton = findViewById(R.id.signup_button);
|
||||
Button signInButton = findViewById(R.id.signin_button);
|
||||
|
||||
View view = View.inflate(this, R.layout.login_options_view, null);
|
||||
AlertDialog signInDialog = new AlertDialog.Builder(this)
|
||||
.setView(view)
|
||||
.setTitle(R.string.onboarding_alternative_logins)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create();
|
||||
view.findViewById(R.id.add_as_second_device_button).setOnClickListener((v) -> {
|
||||
startAddAsSecondDeviceActivity();
|
||||
signInDialog.dismiss();
|
||||
});
|
||||
view.findViewById(R.id.backup_button).setOnClickListener((v) -> {
|
||||
startImportBackup();
|
||||
signInDialog.dismiss();
|
||||
});
|
||||
|
||||
signUpButton.setOnClickListener((v) -> startInstantOnboardingActivity());
|
||||
signInButton.setOnClickListener((v) -> signInDialog.show());
|
||||
findViewById(R.id.signup_button).setOnClickListener((v) -> startInstantOnboardingActivity());
|
||||
findViewById(R.id.add_as_second_device_button).setOnClickListener((v) -> startAddAsSecondDeviceActivity());
|
||||
findViewById(R.id.backup_button).setOnClickListener((v) -> startImportBackup());
|
||||
|
||||
registerForEvents();
|
||||
initializeActionBar();
|
||||
@@ -110,7 +93,7 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
|
||||
boolean canGoBack = AccountManager.getInstance().canRollbackAccountCreation(this);
|
||||
supportActionBar.setDisplayHomeAsUpEnabled(canGoBack);
|
||||
getSupportActionBar().setTitle(canGoBack? R.string.add_account : R.string.welcome_desktop);
|
||||
getSupportActionBar().setTitle(canGoBack? R.string.add_account : R.string.app_name);
|
||||
}
|
||||
|
||||
private void registerForEvents() {
|
||||
@@ -183,7 +166,7 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
.withPermanentDenialDialog(getString(R.string.perm_explain_access_to_storage_denied))
|
||||
.onAllGranted(() -> {
|
||||
File imexDir = DcHelper.getImexDir();
|
||||
if (Build.VERSION.SDK_INT >= 30) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
AttachmentManager.selectMediaType(this, "application/x-tar", null, PICK_BACKUP, StorageUtil.getDownloadUri());
|
||||
} else {
|
||||
final String backupFile = dcContext.imexHasBackup(imexDir.getAbsolutePath());
|
||||
@@ -296,6 +279,8 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
}
|
||||
|
||||
public static void maybeShowConfigurationError(Activity activity, String data2) {
|
||||
if (activity.isFinishing()) return; // avoid android.view.WindowManager$BadTokenException
|
||||
|
||||
if (data2 != null && !data2.isEmpty()) {
|
||||
AlertDialog d = new AlertDialog.Builder(activity)
|
||||
.setMessage(data2)
|
||||
@@ -342,7 +327,6 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
}
|
||||
DcHelper.getAccounts(this).startIo();
|
||||
progressSuccess();
|
||||
dcContext.assumeMultiDevice();
|
||||
notificationController.close();
|
||||
cleanupTempBackupFile();
|
||||
}
|
||||
@@ -352,20 +336,29 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (resultCode != RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestCode==IntentIntegrator.REQUEST_CODE) {
|
||||
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
|
||||
if (scanResult == null || scanResult.getFormatName() == null) {
|
||||
return; // aborted
|
||||
String qrRaw = data.getStringExtra(RegistrationQrActivity.QRDATA_EXTRA);
|
||||
if (qrRaw == null) {
|
||||
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
|
||||
if (scanResult == null || scanResult.getFormatName() == null) {
|
||||
return; // aborted
|
||||
}
|
||||
qrRaw = scanResult.getContents();
|
||||
}
|
||||
String qrRaw = scanResult.getContents();
|
||||
DcLot qrParsed = dcContext.checkQr(qrRaw);
|
||||
switch (qrParsed.getState()) {
|
||||
case DcContext.DC_QR_BACKUP:
|
||||
case DcContext.DC_QR_BACKUP2:
|
||||
new AlertDialog.Builder(this)
|
||||
final String finalQrRaw = qrRaw;
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.multidevice_receiver_title)
|
||||
.setMessage(R.string.multidevice_receiver_scanning_ask)
|
||||
.setPositiveButton(R.string.perm_continue, (dialog, which) -> startBackupTransfer(qrRaw))
|
||||
.setPositiveButton(R.string.perm_continue, (dialog, which) -> startBackupTransfer(finalQrRaw))
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.setCancelable(false)
|
||||
.show();
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package org.thoughtcrime.securesms.accounts;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@@ -11,7 +10,6 @@ import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.b44t.messenger.DcAccounts;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
@@ -92,7 +90,7 @@ public class AccountSelectionListAdapter extends RecyclerView.Adapter
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
|
||||
int id = accountList[i];
|
||||
DcContext dcContext = (id == DcContact.DC_CONTACT_ID_ADD_ACCOUNT)? null : accounts.getAccount(id);
|
||||
DcContext dcContext = accounts.getAccount(id);
|
||||
|
||||
ViewHolder holder = (ViewHolder) viewHolder;
|
||||
holder.unbind(glideRequests);
|
||||
|
||||
+86
-12
@@ -4,10 +4,13 @@ import android.app.Activity;
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
@@ -16,19 +19,26 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.b44t.messenger.DcAccounts;
|
||||
import com.b44t.messenger.DcContact;
|
||||
import com.b44t.messenger.DcContext;
|
||||
import com.b44t.messenger.DcEvent;
|
||||
import com.b44t.messenger.rpc.Rpc;
|
||||
import com.b44t.messenger.rpc.RpcException;
|
||||
|
||||
import org.thoughtcrime.securesms.ConnectivityActivity;
|
||||
import org.thoughtcrime.securesms.ConversationListActivity;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.AvatarView;
|
||||
import org.thoughtcrime.securesms.connect.AccountManager;
|
||||
import org.thoughtcrime.securesms.connect.DcEventCenter;
|
||||
import org.thoughtcrime.securesms.connect.DcHelper;
|
||||
import org.thoughtcrime.securesms.mms.GlideApp;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
import static com.b44t.messenger.DcContact.DC_CONTACT_ID_ADD_ACCOUNT;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PRIVATE_TAG;
|
||||
|
||||
public class AccountSelectionListFragment extends DialogFragment implements DcEventCenter.DcEventDelegate
|
||||
{
|
||||
@@ -79,15 +89,15 @@ public class AccountSelectionListFragment extends DialogFragment implements DcEv
|
||||
private void refreshData() {
|
||||
if (adapter == null) return;
|
||||
|
||||
DcAccounts accounts = DcHelper.getAccounts(requireActivity());
|
||||
DcAccounts accounts = DcHelper.getAccounts(getActivity());
|
||||
int[] accountIds = accounts.getAll();
|
||||
|
||||
int[] ids = new int[accountIds.length + 1];
|
||||
ids[0] = DC_CONTACT_ID_ADD_ACCOUNT;
|
||||
int j = 0;
|
||||
for (int accountId : accountIds) {
|
||||
ids[++j] = accountId;
|
||||
ids[j++] = accountId;
|
||||
}
|
||||
ids[j] = DC_CONTACT_ID_ADD_ACCOUNT;
|
||||
adapter.changeData(ids, accounts.getSelectedAccount().getAccountId());
|
||||
}
|
||||
|
||||
@@ -100,11 +110,7 @@ public class AccountSelectionListFragment extends DialogFragment implements DcEv
|
||||
int accountId = listItem.getAccountId();
|
||||
DcAccounts dcAccounts = DcHelper.getAccounts(getActivity());
|
||||
|
||||
if (accountId == dcAccounts.getSelectedAccount().getAccountId()) {
|
||||
menu.findItem(R.id.delete).setVisible(false);
|
||||
} else {
|
||||
Util.redMenuItem(menu, R.id.delete);
|
||||
}
|
||||
Util.redMenuItem(menu, R.id.delete);
|
||||
|
||||
if (dcAccounts.getAccount(accountId).isMuted()) {
|
||||
menu.findItem(R.id.menu_mute_notifications).setTitle(R.string.menu_unmute);
|
||||
@@ -130,22 +136,90 @@ public class AccountSelectionListFragment extends DialogFragment implements DcEv
|
||||
case R.id.menu_mute_notifications:
|
||||
onToggleMute(accountId);
|
||||
break;
|
||||
case R.id.menu_set_tag:
|
||||
onSetTag(accountId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void onSetTag(int accountId) {
|
||||
Activity activity = getActivity();
|
||||
if (activity == null) return;
|
||||
AccountSelectionListFragment.this.dismiss();
|
||||
|
||||
DcContext dcContext = DcHelper.getAccounts(activity).getAccount(accountId);
|
||||
View view = View.inflate(activity, R.layout.single_line_input, null);
|
||||
EditText inputField = view.findViewById(R.id.input_field);
|
||||
inputField.setHint(R.string.profile_tag_hint);
|
||||
inputField.setText(dcContext.getConfig(CONFIG_PRIVATE_TAG));
|
||||
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.profile_tag)
|
||||
.setMessage(R.string.profile_tag_explain)
|
||||
.setView(view)
|
||||
.setPositiveButton(android.R.string.ok, (d, b) -> {
|
||||
String newTag = inputField.getText().toString().trim();
|
||||
dcContext.setConfig(CONFIG_PRIVATE_TAG, newTag);
|
||||
AccountManager.getInstance().showSwitchAccountMenu(activity);
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, (d, b) -> AccountManager.getInstance().showSwitchAccountMenu(activity))
|
||||
.show();
|
||||
}
|
||||
|
||||
private void onDeleteAccount(int accountId) {
|
||||
Activity activity = getActivity();
|
||||
AccountSelectionListFragment.this.dismiss();
|
||||
if (activity == null) return;
|
||||
DcAccounts accounts = DcHelper.getAccounts(activity);
|
||||
Rpc rpc = DcHelper.getRpc(activity);
|
||||
|
||||
View dialogView = View.inflate(activity, R.layout.dialog_delete_profile, null);
|
||||
AvatarView avatar = dialogView.findViewById(R.id.avatar);
|
||||
TextView nameView = dialogView.findViewById(R.id.name);
|
||||
TextView addrView = dialogView.findViewById(R.id.address);
|
||||
TextView sizeView = dialogView.findViewById(R.id.size_label);
|
||||
TextView description = dialogView.findViewById(R.id.description);
|
||||
DcContext dcContext = accounts.getAccount(accountId);
|
||||
String name = dcContext.getConfig("displayname");
|
||||
DcContact contact = dcContext.getContact(DcContact.DC_CONTACT_ID_SELF);
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
name = contact.getAddr();
|
||||
}
|
||||
Recipient recipient = new Recipient(getContext(), contact, name);
|
||||
avatar.setAvatar(GlideApp.with(activity), recipient, false);
|
||||
nameView.setText(name);
|
||||
addrView.setText(contact.getAddr());
|
||||
Util.runOnAnyBackgroundThread(() -> {
|
||||
try {
|
||||
final int sizeBytes = rpc.getAccountFileSize(accountId);
|
||||
Util.runOnMain(() -> {
|
||||
sizeView.setText(Util.getPrettyFileSize(sizeBytes));
|
||||
});
|
||||
} catch (RpcException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
description.setText(activity.getString(R.string.delete_account_explain_with_name, name));
|
||||
|
||||
AlertDialog dialog = new AlertDialog.Builder(activity)
|
||||
.setTitle(accounts.getAccount(accountId).getNameNAddr())
|
||||
.setMessage(R.string.forget_login_confirmation_desktop)
|
||||
.setTitle(R.string.delete_account)
|
||||
.setView(dialogView)
|
||||
.setNegativeButton(R.string.cancel, (d, which) -> AccountManager.getInstance().showSwitchAccountMenu(activity))
|
||||
.setPositiveButton(R.string.delete, (d2, which2) -> {
|
||||
DcHelper.getNotificationCenter(activity).removeAllNotifiations(accountId);
|
||||
boolean selected = accountId == accounts.getSelectedAccount().getAccountId();
|
||||
DcHelper.getNotificationCenter(activity).removeAllNotifications(accountId);
|
||||
accounts.removeAccount(accountId);
|
||||
AccountManager.getInstance().showSwitchAccountMenu(activity);
|
||||
if (selected) {
|
||||
DcContext selAcc = accounts.getSelectedAccount();
|
||||
AccountManager.getInstance().switchAccountAndStartActivity(activity, selAcc.isOk()? selAcc.getAccountId() : 0);
|
||||
} else {
|
||||
AccountManager.getInstance().showSwitchAccountMenu(activity);
|
||||
}
|
||||
|
||||
// title update needed to show "Delta Chat" in case there is only one profile left
|
||||
if (activity instanceof ConversationListActivity) {
|
||||
((ConversationListActivity)activity).refreshTitle();
|
||||
}
|
||||
})
|
||||
.show();
|
||||
Util.redPositiveButton(dialog);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package org.thoughtcrime.securesms.accounts;
|
||||
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_DISPLAY_NAME;
|
||||
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PRIVATE_TAG;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
@@ -29,7 +32,7 @@ public class AccountSelectionListItem extends LinearLayout {
|
||||
|
||||
private AvatarView contactPhotoImage;
|
||||
private View addrContainer;
|
||||
private TextView addrView;
|
||||
private TextView addrOrTagView;
|
||||
private TextView nameView;
|
||||
private ImageView unreadIndicator;
|
||||
private SwitchCompat enableSwitch;
|
||||
@@ -50,7 +53,7 @@ public class AccountSelectionListItem extends LinearLayout {
|
||||
super.onFinishInflate();
|
||||
this.contactPhotoImage = findViewById(R.id.contact_photo_image);
|
||||
this.addrContainer = findViewById(R.id.addr_container);
|
||||
this.addrView = findViewById(R.id.addr);
|
||||
this.addrOrTagView = findViewById(R.id.addr_or_tag);
|
||||
this.nameView = findViewById(R.id.name);
|
||||
this.unreadIndicator = findViewById(R.id.unread_indicator);
|
||||
this.enableSwitch = findViewById(R.id.enable_switch);
|
||||
@@ -66,45 +69,54 @@ public class AccountSelectionListItem extends LinearLayout {
|
||||
this.dcContext = dcContext;
|
||||
DcContact self = null;
|
||||
String name;
|
||||
String addr = null;
|
||||
String addrOrTag = null;
|
||||
int unreadCount = 0;
|
||||
boolean isMuted = dcContext != null && dcContext.isMuted();
|
||||
boolean isMuted = dcContext.isMuted();
|
||||
|
||||
Recipient recipient;
|
||||
if (accountId != DcContact.DC_CONTACT_ID_ADD_ACCOUNT) {
|
||||
if (accountId == DcContact.DC_CONTACT_ID_ADD_ACCOUNT) {
|
||||
name = getContext().getString(R.string.add_account);
|
||||
enableSwitch.setVisibility(View.INVISIBLE);
|
||||
recipient = null;
|
||||
this.contactPhotoImage.setSeenRecently(false); // hide connectivity dot
|
||||
} else {
|
||||
self = dcContext.getContact(DcContact.DC_CONTACT_ID_SELF);
|
||||
addr = dcContext.isCommunity()? getContext().getString(R.string.community) : self.getAddr();
|
||||
name = dcContext.getConfig("displayname");
|
||||
name = dcContext.getConfig(CONFIG_DISPLAY_NAME);
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
name = addr;
|
||||
name = self.getAddr();
|
||||
}
|
||||
|
||||
addrOrTag = dcContext.getConfig(CONFIG_PRIVATE_TAG);
|
||||
if ("".equals(addrOrTag)) {
|
||||
if (dcContext.isCommunity()) {
|
||||
addrOrTag = getContext().getString(R.string.community);
|
||||
} else if (!dcContext.isChatmail()) {
|
||||
addrOrTag = self.getAddr();
|
||||
}
|
||||
}
|
||||
|
||||
unreadCount = dcContext.getFreshMsgs().length;
|
||||
|
||||
enableSwitch.setChecked(dcContext.isEnabled());
|
||||
enableSwitch.setVisibility(View.VISIBLE);
|
||||
recipient = new Recipient(getContext(), self, name);
|
||||
this.contactPhotoImage.setConnectivity(dcContext.getConnectivity());
|
||||
} else {
|
||||
name = getContext().getString(R.string.add_account);
|
||||
enableSwitch.setVisibility(View.INVISIBLE);
|
||||
recipient = null;
|
||||
this.contactPhotoImage.setSeenRecently(false); // hide connectivity dot
|
||||
}
|
||||
this.contactPhotoImage.setAvatar(glideRequests, recipient, false);
|
||||
|
||||
setSelected(selected);
|
||||
nameView.setCompoundDrawablesWithIntrinsicBounds(isMuted? R.drawable.ic_volume_off_grey600_18dp : 0, 0, 0, 0);
|
||||
|
||||
setSelected(selected);
|
||||
if (selected) {
|
||||
addrView.setTypeface(null, Typeface.BOLD);
|
||||
addrOrTagView.setTypeface(null, Typeface.BOLD);
|
||||
nameView.setTypeface(null, Typeface.BOLD);
|
||||
} else {
|
||||
addrView.setTypeface(null, Typeface.NORMAL);
|
||||
nameView.setTypeface(null, accountId == DcContact.DC_CONTACT_ID_ADD_ACCOUNT? Typeface.BOLD : Typeface.NORMAL);
|
||||
addrOrTagView.setTypeface(null, Typeface.NORMAL);
|
||||
nameView.setTypeface(null, Typeface.NORMAL);
|
||||
}
|
||||
|
||||
updateUnreadIndicator(unreadCount, isMuted);
|
||||
setText(name, addr);
|
||||
setText(name, addrOrTag);
|
||||
|
||||
if (accountId != DcContact.DC_CONTACT_ID_ADD_ACCOUNT) {
|
||||
fragment.registerForContextMenu(this);
|
||||
@@ -142,11 +154,11 @@ public class AccountSelectionListItem extends LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private void setText(String name, String addr) {
|
||||
private void setText(String name, String addrOrTag) {
|
||||
this.nameView.setText(name==null? "#" : name);
|
||||
|
||||
if(addr != null) {
|
||||
this.addrView.setText(addr);
|
||||
if(!TextUtils.isEmpty(addrOrTag)) {
|
||||
this.addrOrTagView.setText(addrOrTag);
|
||||
this.addrContainer.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
this.addrContainer.setVisibility(View.GONE);
|
||||
|
||||
@@ -48,7 +48,7 @@ public class AudioRecorder {
|
||||
ParcelFileDescriptor fds[] = ParcelFileDescriptor.createPipe();
|
||||
|
||||
captureUri = blobProvider.create(context, new ParcelFileDescriptor.AutoCloseInputStream(fds[0]),
|
||||
MediaUtil.AUDIO_AAC, null, null);
|
||||
MediaUtil.AUDIO_AAC, "voice.aac", null);
|
||||
audioCodec = new AudioCodec(context);
|
||||
|
||||
audioCodec.start(new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]));
|
||||
|
||||
@@ -87,11 +87,14 @@ public class AudioSlidePlayer {
|
||||
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
|
||||
if (playbackState == Player.STATE_READY) {
|
||||
Util.runOnMain(() -> {
|
||||
Log.d(TAG, "request duration " + durationCalculator.getDuration());
|
||||
getListener().onReceivedDuration(Long.valueOf(durationCalculator.getDuration()).intValue());
|
||||
durationCalculator.release();
|
||||
durationCalculator.removeListener(this);
|
||||
durationCalculator = null;
|
||||
synchronized (AudioSlidePlayer.this) {
|
||||
if (durationCalculator == null) return;
|
||||
Log.d(TAG, "request duration " + durationCalculator.getDuration());
|
||||
getListener().onReceivedDuration(Long.valueOf(durationCalculator.getDuration()).intValue());
|
||||
durationCalculator.release();
|
||||
durationCalculator.removeListener(this);
|
||||
durationCalculator = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
public static final int TAKE_PHOTO = 5;
|
||||
public static final int ADD_LOCATION = 6;
|
||||
public static final int RECORD_VIDEO = 7;
|
||||
public static final int ADD_WEBXDC = 8;
|
||||
|
||||
private static final int ANIMATION_DURATION = 300;
|
||||
|
||||
@@ -53,7 +54,7 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
//private final @NonNull ImageView cameraButton;
|
||||
private final @NonNull ImageView videoButton;
|
||||
private final @NonNull ImageView locationButton;
|
||||
private final @NonNull ImageView closeButton;
|
||||
private final @NonNull ImageView webxdcButton;
|
||||
|
||||
private @Nullable View currentAnchor;
|
||||
private @Nullable AttachmentClickedListener listener;
|
||||
@@ -76,7 +77,7 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
//this.cameraButton = ViewUtil.findById(layout, R.id.camera_button);
|
||||
this.videoButton = ViewUtil.findById(layout, R.id.record_video_button);
|
||||
this.locationButton = ViewUtil.findById(layout, R.id.location_button);
|
||||
this.closeButton = ViewUtil.findById(layout, R.id.close_button);
|
||||
this.webxdcButton = ViewUtil.findById(layout, R.id.webxdc_button);
|
||||
|
||||
this.imageButton.setOnClickListener(new PropagatingClickListener(ADD_GALLERY));
|
||||
this.videoChatButton.setOnClickListener(new PropagatingClickListener(INVITE_VIDEO_CHAT));
|
||||
@@ -85,7 +86,7 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
//this.cameraButton.setOnClickListener(new PropagatingClickListener(TAKE_PHOTO));
|
||||
this.videoButton.setOnClickListener(new PropagatingClickListener(RECORD_VIDEO));
|
||||
this.locationButton.setOnClickListener(new PropagatingClickListener(ADD_LOCATION));
|
||||
this.closeButton.setOnClickListener(new CloseClickListener());
|
||||
this.webxdcButton.setOnClickListener(new PropagatingClickListener(ADD_WEBXDC));
|
||||
this.recentRail.setListener(new RecentPhotoSelectedListener());
|
||||
|
||||
if (!Prefs.isLocationStreamingEnabled(context)) {
|
||||
@@ -130,33 +131,23 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
public void onGlobalLayout() {
|
||||
getContentView().getViewTreeObserver().removeGlobalOnLayoutListener(this);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
animateWindowInCircular(anchor, getContentView());
|
||||
} else {
|
||||
animateWindowInTranslate(getContentView());
|
||||
}
|
||||
animateWindowInCircular(anchor, getContentView());
|
||||
}
|
||||
});
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
//animateButtonIn(cameraButton, ANIMATION_DURATION / 2);
|
||||
animateButtonIn(videoButton, ANIMATION_DURATION / 2);
|
||||
animateButtonIn(imageButton, ANIMATION_DURATION / 3);
|
||||
animateButtonIn(contactButton, ANIMATION_DURATION / 3);
|
||||
animateButtonIn(locationButton, ANIMATION_DURATION / 4);
|
||||
animateButtonIn(documentButton, ANIMATION_DURATION / 4);
|
||||
animateButtonIn(videoChatButton, 0);
|
||||
animateButtonIn(closeButton, 0);
|
||||
}
|
||||
//animateButtonIn(cameraButton, ANIMATION_DURATION / 2);
|
||||
animateButtonIn(videoButton, ANIMATION_DURATION / 2);
|
||||
animateButtonIn(imageButton, ANIMATION_DURATION / 3);
|
||||
animateButtonIn(contactButton, ANIMATION_DURATION / 3);
|
||||
animateButtonIn(locationButton, ANIMATION_DURATION / 4);
|
||||
animateButtonIn(documentButton, ANIMATION_DURATION / 4);
|
||||
animateButtonIn(webxdcButton, 0);
|
||||
animateButtonIn(videoChatButton, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
animateWindowOutCircular(currentAnchor, getContentView());
|
||||
} else {
|
||||
animateWindowOutTranslate(getContentView());
|
||||
}
|
||||
animateWindowOutCircular(currentAnchor, getContentView());
|
||||
}
|
||||
|
||||
public void setListener(@Nullable AttachmentClickedListener listener) {
|
||||
@@ -186,7 +177,6 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
button.startAnimation(animation);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void animateWindowInCircular(@Nullable View anchor, @NonNull View contentView) {
|
||||
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(contentView,
|
||||
@@ -205,7 +195,6 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
getContentView().startAnimation(animation);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void animateWindowOutCircular(@Nullable View anchor, @NonNull View contentView) {
|
||||
Pair<Integer, Integer> coordinates = getClickOrigin(anchor, contentView);
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(getContentView(),
|
||||
@@ -301,13 +290,6 @@ public class AttachmentTypeSelector extends PopupWindow {
|
||||
|
||||
}
|
||||
|
||||
private class CloseClickListener implements View.OnClickListener {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public interface AttachmentClickedListener {
|
||||
public void onClick(int type);
|
||||
public void onQuickAttachment(Uri uri);
|
||||
|
||||
@@ -71,12 +71,10 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
this.pauseButton.setOnClickListener(new PauseClickedListener());
|
||||
this.seekBar.setOnSeekBarChangeListener(new SeekBarModifiedListener());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
this.playButton.setImageDrawable(context.getDrawable(R.drawable.play_icon));
|
||||
this.pauseButton.setImageDrawable(context.getDrawable(R.drawable.pause_icon));
|
||||
this.playButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
|
||||
this.pauseButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
|
||||
}
|
||||
this.playButton.setImageDrawable(context.getDrawable(R.drawable.play_icon));
|
||||
this.pauseButton.setImageDrawable(context.getDrawable(R.drawable.pause_icon));
|
||||
this.playButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
|
||||
this.pauseButton.setBackground(context.getDrawable(R.drawable.ic_circle_fill_white_48dp));
|
||||
|
||||
setTint(getContext().getResources().getColor(R.color.audio_icon));
|
||||
}
|
||||
@@ -192,13 +190,8 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
}
|
||||
|
||||
public void setTint(int foregroundTint) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
this.playButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
|
||||
this.pauseButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
|
||||
} else {
|
||||
this.playButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
|
||||
this.pauseButton.setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
|
||||
}
|
||||
this.playButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
|
||||
this.pauseButton.setBackgroundTintList(ColorStateList.valueOf(foregroundTint));
|
||||
|
||||
this.seekBar.getProgressDrawable().setColorFilter(foregroundTint, PorterDuff.Mode.SRC_IN);
|
||||
|
||||
@@ -220,25 +213,20 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
private void togglePlayToPause() {
|
||||
controlToggle.displayQuick(pauseButton);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
AnimatedVectorDrawable playToPauseDrawable = (AnimatedVectorDrawable)getContext().getDrawable(R.drawable.play_to_pause_animation);
|
||||
pauseButton.setImageDrawable(playToPauseDrawable);
|
||||
playToPauseDrawable.start();
|
||||
}
|
||||
AnimatedVectorDrawable playToPauseDrawable = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.play_to_pause_animation);
|
||||
pauseButton.setImageDrawable(playToPauseDrawable);
|
||||
playToPauseDrawable.start();
|
||||
}
|
||||
|
||||
private void togglePauseToPlay() {
|
||||
controlToggle.displayQuick(playButton);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
AnimatedVectorDrawable pauseToPlayDrawable = (AnimatedVectorDrawable)getContext().getDrawable(R.drawable.pause_to_play_animation);
|
||||
playButton.setImageDrawable(pauseToPlayDrawable);
|
||||
pauseToPlayDrawable.start();
|
||||
}
|
||||
AnimatedVectorDrawable pauseToPlayDrawable = (AnimatedVectorDrawable) getContext().getDrawable(R.drawable.pause_to_play_animation);
|
||||
playButton.setImageDrawable(pauseToPlayDrawable);
|
||||
pauseToPlayDrawable.start();
|
||||
}
|
||||
|
||||
private class PlayClickedListener implements View.OnClickListener {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
@@ -279,7 +267,6 @@ public class AudioView extends FrameLayout implements AudioSlidePlayer.Listener
|
||||
}
|
||||
|
||||
private class PauseClickedListener implements View.OnClickListener {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Log.w(TAG, "pausebutton onClick");
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import androidx.appcompat.widget.AppCompatEditText;
|
||||
import androidx.core.view.inputmethod.EditorInfoCompat;
|
||||
import androidx.core.view.inputmethod.InputConnectionCompat;
|
||||
import androidx.core.view.inputmethod.InputContentInfoCompat;
|
||||
@@ -25,10 +26,9 @@ import android.view.inputmethod.InputConnection;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.TransportOption;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
|
||||
public class ComposeText extends EmojiEditText {
|
||||
public class ComposeText extends AppCompatEditText {
|
||||
|
||||
private CharSequence hint;
|
||||
private SpannableString subHint;
|
||||
@@ -122,7 +122,6 @@ public class ComposeText extends EmojiEditText {
|
||||
editorInfo.imeOptions &= ~EditorInfo.IME_FLAG_NO_ENTER_ACTION;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < 21) return inputConnection;
|
||||
if (mediaListener == null) return inputConnection;
|
||||
if (inputConnection == null) return null;
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.util.DateUtils;
|
||||
public class ConversationItemFooter extends LinearLayout {
|
||||
|
||||
private TextView dateView;
|
||||
private ImageView bookmarkIndicatorView;
|
||||
private ImageView secureIndicatorView;
|
||||
private ImageView locationIndicatorView;
|
||||
private DeliveryStatusView deliveryStatusView;
|
||||
@@ -44,6 +45,7 @@ public class ConversationItemFooter extends LinearLayout {
|
||||
inflate(getContext(), R.layout.conversation_item_footer, this);
|
||||
|
||||
dateView = findViewById(R.id.footer_date);
|
||||
bookmarkIndicatorView = findViewById(R.id.footer_bookmark_indicator);
|
||||
secureIndicatorView = findViewById(R.id.footer_secure_indicator);
|
||||
locationIndicatorView = findViewById(R.id.footer_location_indicator);
|
||||
deliveryStatusView = new DeliveryStatusView(findViewById(R.id.delivery_indicator));
|
||||
@@ -58,6 +60,8 @@ public class ConversationItemFooter extends LinearLayout {
|
||||
|
||||
public void setMessageRecord(@NonNull DcMsg messageRecord) {
|
||||
presentDate(messageRecord);
|
||||
boolean bookmark = messageRecord.getOriginalMsgId() != 0 || messageRecord.getSavedMsgId() != 0;
|
||||
bookmarkIndicatorView.setVisibility(bookmark ? View.VISIBLE : View.GONE);
|
||||
secureIndicatorView.setVisibility(messageRecord.isSecure() ? View.VISIBLE : View.GONE);
|
||||
locationIndicatorView.setVisibility(messageRecord.hasLocation() ? View.VISIBLE : View.GONE);
|
||||
presentDeliveryStatus(messageRecord);
|
||||
@@ -65,6 +69,7 @@ public class ConversationItemFooter extends LinearLayout {
|
||||
|
||||
private void setTextColor(int color) {
|
||||
dateView.setTextColor(color);
|
||||
bookmarkIndicatorView.setColorFilter(color);
|
||||
secureIndicatorView.setColorFilter(color);
|
||||
locationIndicatorView.setColorFilter(color);
|
||||
deliveryStatusView.setTint(color);
|
||||
|
||||
@@ -120,15 +120,10 @@ public class ConversationItemThumbnail extends FrameLayout {
|
||||
@SuppressWarnings("SuspiciousNameCombination")
|
||||
@Override
|
||||
protected void dispatchDraw(Canvas canvas) {
|
||||
if (cornerMask.isLegacy()) {
|
||||
cornerMask.mask(canvas);
|
||||
}
|
||||
|
||||
super.dispatchDraw(canvas);
|
||||
|
||||
if (!cornerMask.isLegacy()) {
|
||||
cornerMask.mask(canvas);
|
||||
}
|
||||
cornerMask.mask(canvas);
|
||||
|
||||
final float halfStrokeWidth = outlinePaint.getStrokeWidth() / 2;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import android.graphics.Path;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.PorterDuffXfermode;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import android.view.View;
|
||||
|
||||
@@ -20,11 +20,7 @@ public class CornerMask {
|
||||
private final RectF bounds = new RectF();
|
||||
|
||||
public CornerMask(@NonNull View view) {
|
||||
if (isLegacy()) {
|
||||
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||
} else {
|
||||
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
}
|
||||
view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
|
||||
|
||||
clearPaint.setColor(Color.BLACK);
|
||||
clearPaint.setStyle(Paint.Style.FILL);
|
||||
@@ -44,19 +40,10 @@ public class CornerMask {
|
||||
// Note: There's a bug in the P beta where most PorterDuff modes aren't working. But CLEAR does.
|
||||
// So we find and inverse path and use Mode.CLEAR for versions that support Path.op().
|
||||
// See issue https://issuetracker.google.com/issues/111394085.
|
||||
if (!isLegacy()) {
|
||||
outline.reset();
|
||||
outline.addRect(bounds, Path.Direction.CW);
|
||||
outline.op(corners, Path.Op.DIFFERENCE);
|
||||
canvas.drawPath(outline, clearPaint);
|
||||
} else {
|
||||
corners.addRoundRect(bounds, radii, Path.Direction.CW);
|
||||
canvas.clipPath(corners);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLegacy() {
|
||||
return Build.VERSION.SDK_INT < 19;
|
||||
outline.reset();
|
||||
outline.addRect(bounds, Path.Direction.CW);
|
||||
outline.op(corners, Path.Op.DIFFERENCE);
|
||||
canvas.drawPath(outline, clearPaint);
|
||||
}
|
||||
|
||||
public void setRadius(int radius) {
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.thoughtcrime.securesms.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
|
||||
import androidx.appcompat.widget.AppCompatTextView;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
@@ -14,12 +16,11 @@ import android.text.style.TypefaceSpan;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.spans.CenterAlignedRelativeSizeSpan;
|
||||
|
||||
public class FromTextView extends EmojiTextView {
|
||||
public class FromTextView extends AppCompatTextView {
|
||||
|
||||
private static final String TAG = FromTextView.class.getSimpleName();
|
||||
|
||||
|
||||
@@ -9,7 +9,6 @@ import android.os.Build;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
@@ -29,14 +28,12 @@ import com.b44t.messenger.util.concurrent.SettableFuture;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiKeyboardProvider;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiToggle;
|
||||
import org.thoughtcrime.securesms.components.emoji.MediaKeyboard;
|
||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||
import org.thoughtcrime.securesms.mms.QuoteModel;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Prefs;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener;
|
||||
@@ -46,9 +43,9 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class InputPanel extends ConstraintLayout
|
||||
implements MicrophoneRecorderView.Listener,
|
||||
KeyboardAwareLinearLayout.OnKeyboardShownListener,
|
||||
EmojiKeyboardProvider.EmojiEventListener
|
||||
implements MicrophoneRecorderView.Listener,
|
||||
KeyboardAwareLinearLayout.OnKeyboardShownListener,
|
||||
MediaKeyboard.MediaKeyboardListener
|
||||
{
|
||||
|
||||
private static final String TAG = InputPanel.class.getSimpleName();
|
||||
@@ -56,7 +53,7 @@ public class InputPanel extends ConstraintLayout
|
||||
private static final int FADE_TIME = 150;
|
||||
|
||||
private QuoteView quoteView;
|
||||
private EmojiToggle mediaKeyboard;
|
||||
private EmojiToggle emojiToggle;
|
||||
private ComposeText composeText;
|
||||
private View quickCameraToggle;
|
||||
private View quickAudioToggle;
|
||||
@@ -70,7 +67,6 @@ public class InputPanel extends ConstraintLayout
|
||||
private ValueAnimator quoteAnimator;
|
||||
|
||||
private @Nullable Listener listener;
|
||||
private boolean emojiVisible;
|
||||
|
||||
public InputPanel(Context context) {
|
||||
super(context);
|
||||
@@ -92,7 +88,7 @@ public class InputPanel extends ConstraintLayout
|
||||
View quoteDismiss = findViewById(R.id.quote_dismiss);
|
||||
|
||||
this.quoteView = findViewById(R.id.quote_view);
|
||||
this.mediaKeyboard = findViewById(R.id.emoji_toggle);
|
||||
this.emojiToggle = findViewById(R.id.emoji_toggle);
|
||||
this.composeText = findViewById(R.id.embedded_text_editor);
|
||||
this.quickCameraToggle = findViewById(R.id.quick_camera_toggle);
|
||||
this.quickAudioToggle = findViewById(R.id.quick_audio_toggle);
|
||||
@@ -106,21 +102,13 @@ public class InputPanel extends ConstraintLayout
|
||||
|
||||
this.recordLockCancel.setOnClickListener(v -> microphoneRecorderView.cancelAction());
|
||||
|
||||
if (Prefs.isSystemEmojiPreferred(getContext())) {
|
||||
mediaKeyboard.setVisibility(View.GONE);
|
||||
emojiVisible = false;
|
||||
} else {
|
||||
mediaKeyboard.setVisibility(View.VISIBLE);
|
||||
emojiVisible = true;
|
||||
}
|
||||
|
||||
quoteDismiss.setOnClickListener(v -> clearQuote());
|
||||
}
|
||||
|
||||
public void setListener(final @NonNull Listener listener) {
|
||||
this.listener = listener;
|
||||
|
||||
mediaKeyboard.setOnClickListener(v -> listener.onEmojiToggle());
|
||||
emojiToggle.setOnClickListener(v -> listener.onEmojiToggle());
|
||||
}
|
||||
|
||||
public void setMediaListener(@NonNull MediaListener listener) {
|
||||
@@ -207,7 +195,7 @@ public class InputPanel extends ConstraintLayout
|
||||
}
|
||||
|
||||
public void setMediaKeyboard(@NonNull MediaKeyboard mediaKeyboard) {
|
||||
this.mediaKeyboard.attach(mediaKeyboard);
|
||||
mediaKeyboard.setKeyboardListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -221,7 +209,7 @@ public class InputPanel extends ConstraintLayout
|
||||
recordTime.display();
|
||||
slideToCancel.display();
|
||||
|
||||
if (emojiVisible) ViewUtil.fadeOut(mediaKeyboard, FADE_TIME, View.INVISIBLE);
|
||||
ViewUtil.fadeOut(emojiToggle, FADE_TIME, View.INVISIBLE);
|
||||
ViewUtil.fadeOut(composeText, FADE_TIME, View.INVISIBLE);
|
||||
ViewUtil.fadeOut(quickCameraToggle, FADE_TIME, View.INVISIBLE);
|
||||
ViewUtil.fadeOut(quickAudioToggle, FADE_TIME, View.INVISIBLE);
|
||||
@@ -276,7 +264,7 @@ public class InputPanel extends ConstraintLayout
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
composeText.setEnabled(enabled);
|
||||
mediaKeyboard.setEnabled(enabled);
|
||||
emojiToggle.setEnabled(enabled);
|
||||
quickAudioToggle.setEnabled(enabled);
|
||||
quickCameraToggle.setEnabled(enabled);
|
||||
}
|
||||
@@ -290,7 +278,7 @@ public class InputPanel extends ConstraintLayout
|
||||
future.addListener(new AssertedSuccessListener<Void>() {
|
||||
@Override
|
||||
public void onSuccess(Void result) {
|
||||
if (emojiVisible) ViewUtil.fadeIn(mediaKeyboard, FADE_TIME);
|
||||
ViewUtil.fadeIn(emojiToggle, FADE_TIME);
|
||||
ViewUtil.fadeIn(composeText, FADE_TIME);
|
||||
ViewUtil.fadeIn(quickCameraToggle, FADE_TIME);
|
||||
ViewUtil.fadeIn(quickAudioToggle, FADE_TIME);
|
||||
@@ -304,17 +292,7 @@ public class InputPanel extends ConstraintLayout
|
||||
|
||||
@Override
|
||||
public void onKeyboardShown() {
|
||||
mediaKeyboard.setToMedia();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onKeyEvent(KeyEvent keyEvent) {
|
||||
composeText.dispatchKeyEvent(keyEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEmojiSelected(String emoji) {
|
||||
composeText.insertEmoji(emoji);
|
||||
emojiToggle.setToMedia();
|
||||
}
|
||||
|
||||
public boolean isRecordingInLockedMode() {
|
||||
@@ -325,6 +303,25 @@ public class InputPanel extends ConstraintLayout
|
||||
microphoneRecorderView.unlockAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShown() {
|
||||
emojiToggle.setToIme();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHidden() {
|
||||
emojiToggle.setToMedia();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEmojiPicked(String emoji) {
|
||||
final int start = composeText.getSelectionStart();
|
||||
final int end = composeText.getSelectionEnd();
|
||||
|
||||
composeText.getText().replace(Math.min(start, end), Math.max(start, end), emoji);
|
||||
composeText.setSelection(start + emoji.length());
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onRecorderStarted();
|
||||
void onRecorderLocked();
|
||||
|
||||
@@ -104,7 +104,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
|
||||
}
|
||||
|
||||
private void updateKeyboardState() {
|
||||
if (viewInset == 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) viewInset = getViewInset();
|
||||
if (viewInset == 0) viewInset = getViewInset();
|
||||
|
||||
getWindowVisibleDisplayFrame(rect);
|
||||
|
||||
@@ -148,7 +148,6 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
|
||||
private int getViewInset() {
|
||||
try {
|
||||
Field attachInfoField = View.class.getDeclaredField("mAttachInfo");
|
||||
@@ -219,11 +218,7 @@ public class KeyboardAwareLinearLayout extends LinearLayoutCompat {
|
||||
return Surface.ROTATION_0;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
return ServiceUtil.getWindowManager(getContext()).getDefaultDisplay().getRotation();
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 30) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
getContext().getDisplay().getRealMetrics(displayMetrics);
|
||||
} else {
|
||||
ServiceUtil.getWindowManager(getContext()).getDefaultDisplay().getRealMetrics(displayMetrics);
|
||||
|
||||
@@ -3,10 +3,8 @@ package org.thoughtcrime.securesms.components;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
@@ -40,7 +38,6 @@ public class MediaView extends FrameLayout {
|
||||
initialize();
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public MediaView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
initialize();
|
||||
@@ -56,6 +53,7 @@ public class MediaView extends FrameLayout {
|
||||
public void set(@NonNull GlideRequests glideRequests,
|
||||
@NonNull Window window,
|
||||
@NonNull Uri source,
|
||||
@Nullable String fileName,
|
||||
@NonNull String mediaType,
|
||||
long size,
|
||||
boolean autoplay)
|
||||
@@ -69,7 +67,7 @@ public class MediaView extends FrameLayout {
|
||||
imageView.setVisibility(View.GONE);
|
||||
videoView.get().setVisibility(View.VISIBLE);
|
||||
videoView.get().setWindow(window);
|
||||
videoView.get().setVideoSource(new VideoSlide(getContext(), source, size), autoplay);
|
||||
videoView.get().setVideoSource(new VideoSlide(getContext(), source, fileName, size), autoplay);
|
||||
} else {
|
||||
throw new IOException("Unsupported media type: " + mediaType);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ package org.thoughtcrime.securesms.components;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
@@ -17,7 +16,6 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
import com.b44t.messenger.DcContact;
|
||||
@@ -80,7 +78,6 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
initialize(attrs);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public QuoteView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
initialize(attrs);
|
||||
@@ -158,7 +155,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
if (contact == null) {
|
||||
authorView.setText(getContext().getString(R.string.forwarded_message));
|
||||
} else {
|
||||
authorView.setText(getContext().getString(R.string.forwarded_by, quotedMsg.getSenderName(contact, false)));
|
||||
authorView.setText(getContext().getString(R.string.forwarded_by, quotedMsg.getSenderName(contact)));
|
||||
}
|
||||
authorView.setTextColor(getForwardedColor());
|
||||
quoteBarView.setBackgroundColor(getForwardedColor());
|
||||
@@ -169,7 +166,7 @@ public class QuoteView extends FrameLayout implements RecipientForeverObserver {
|
||||
quoteBarView.setBackgroundColor(getForwardedColor());
|
||||
} else {
|
||||
authorView.setVisibility(VISIBLE);
|
||||
authorView.setText(quotedMsg.getSenderName(contact, true));
|
||||
authorView.setText(quotedMsg.getSenderName(contact));
|
||||
if (hasSticker) {
|
||||
authorView.setTextColor(getResources().getColor(R.color.core_dark_05));
|
||||
quoteBarView.setBackgroundColor(getResources().getColor(R.color.core_dark_05));
|
||||
|
||||
@@ -29,7 +29,6 @@ public class RepeatableImageKey extends ImageButton {
|
||||
init();
|
||||
}
|
||||
|
||||
@TargetApi(VERSION_CODES.LOLLIPOP)
|
||||
public RepeatableImageKey(Context context, AttributeSet attrs, int defStyleAttr,
|
||||
int defStyleRes)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@ public class SearchToolbar extends LinearLayout {
|
||||
private static final String TAG = SearchToolbar.class.getSimpleName();
|
||||
private float x, y;
|
||||
private MenuItem searchItem;
|
||||
private EditText searchText;
|
||||
private SearchListener listener;
|
||||
|
||||
public SearchToolbar(Context context) {
|
||||
@@ -63,7 +64,7 @@ public class SearchToolbar extends LinearLayout {
|
||||
|
||||
this.searchItem = toolbar.getMenu().findItem(R.id.action_filter_search);
|
||||
SearchView searchView = (SearchView) searchItem.getActionView();
|
||||
EditText searchText = searchView.findViewById(androidx.appcompat.R.id.search_src_text);
|
||||
searchText = searchView.findViewById(androidx.appcompat.R.id.search_src_text);
|
||||
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
|
||||
|
||||
searchView.setSubmitButtonEnabled(false);
|
||||
@@ -107,6 +108,17 @@ public class SearchToolbar extends LinearLayout {
|
||||
}
|
||||
});
|
||||
|
||||
MenuItem searchUnread = toolbar.getMenu().findItem(R.id.search_unread);
|
||||
searchUnread.setOnMenuItemClickListener(item -> {
|
||||
String t = searchText.getText().toString();
|
||||
if (!t.contains("is:unread")) {
|
||||
t += (t.isEmpty() ? "" : " ") + "is:unread ";
|
||||
}
|
||||
searchText.setText(t);
|
||||
searchText.setSelection(t.length(), t.length());
|
||||
return true;
|
||||
});
|
||||
|
||||
toolbar.setNavigationOnClickListener(v -> hide());
|
||||
}
|
||||
|
||||
@@ -118,15 +130,11 @@ public class SearchToolbar extends LinearLayout {
|
||||
|
||||
searchItem.expandActionView();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, 0, getWidth());
|
||||
animator.setDuration(400);
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int) x, (int) y, 0, getWidth());
|
||||
animator.setDuration(400);
|
||||
|
||||
setVisibility(View.VISIBLE);
|
||||
animator.start();
|
||||
} else {
|
||||
setVisibility(View.VISIBLE);
|
||||
}
|
||||
setVisibility(View.VISIBLE);
|
||||
animator.start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,19 +149,15 @@ public class SearchToolbar extends LinearLayout {
|
||||
|
||||
if (listener != null) listener.onSearchClosed();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int)x, (int)y, getWidth(), 0);
|
||||
animator.setDuration(400);
|
||||
animator.addListener(new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
animator.start();
|
||||
} else {
|
||||
setVisibility(View.INVISIBLE);
|
||||
}
|
||||
Animator animator = ViewAnimationUtils.createCircularReveal(this, (int) x, (int) y, getWidth(), 0);
|
||||
animator.setDuration(400);
|
||||
animator.addListener(new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
animator.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ public class SwitchPreferenceCompat extends CheckBoxPreference {
|
||||
setLayoutRes();
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
setLayoutRes();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user