Compare commits
857 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c2d7f3ebc6 | ||
|
8f1ff56d34 | ||
|
11ae0ea7d3 | ||
|
afa78857f9 | ||
|
ae2423b2e9 | ||
|
01d3e746d8 | ||
|
13cd03a762 | ||
|
ac7b3c4eb9 | ||
|
7effbc8de0 | ||
|
8c5f0c78e7 | ||
|
45e00ac93d | ||
|
80454afc0d | ||
|
428e898a7a | ||
|
13762eb67f | ||
|
04c43ebf7b | ||
|
f9b5a5212d | ||
|
0351f94761 | ||
|
a89543b555 | ||
|
ce30b1a6ff | ||
|
1b382004cb | ||
|
ab7ff25929 | ||
|
eedf19ad9d | ||
|
941ace99c6 | ||
|
95e0b870f6 | ||
|
2bdb2dc34f | ||
|
22a44d0c8d | ||
|
a9cdbdc03e | ||
|
3fd5470eae | ||
39f96cbd28 | |||
4501f10429 | |||
bd0cde7e87 | |||
|
dd36e08d7d | ||
|
4634def93e | ||
|
1974a8bb8d | ||
|
e9a6609593 | ||
|
b20577026e | ||
|
dae9e137f7 | ||
|
1509d0c5bb | ||
430ebbd1c5 | |||
|
b561eaee6d | ||
|
1aa21c3762 | ||
|
c8a67177d8 | ||
|
59597e962d | ||
|
c85a951a9e | ||
|
7f47a17633 | ||
|
690c961a55 | ||
|
21efd1e4a7 | ||
|
ad27228429 | ||
|
dd4a1667ca | ||
|
399d2b7951 | ||
|
d51dfd6636 | ||
|
ca85c1fa9f | ||
|
5e7f06070e | ||
|
dc0c20cd0c | ||
|
98aa33341a | ||
|
1f7c0afc1e | ||
|
1ccce3f942 | ||
|
90d5bc8de7 | ||
|
c6a685d7c0 | ||
|
e6cfd899e5 | ||
|
bd23f14792 | ||
|
46f6b9e537 | ||
|
d5832c48e1 | ||
|
64ec0f63ca | ||
|
0b7c42e814 | ||
|
d8dc63fc98 | ||
|
81a7f154c2 | ||
|
af3263d471 | ||
|
bbe5f19997 | ||
|
f33650c099 | ||
|
58f81ec851 | ||
|
c9262eb204 | ||
|
3637b832e5 | ||
|
ee56cfe2b4 | ||
|
721410c7d0 | ||
|
f0310e3933 | ||
|
302d7cccc4 | ||
|
f9977d5ce6 | ||
|
0a927fd320 | ||
|
523501a592 | ||
|
ff8155be6a | ||
|
6c5d697051 | ||
|
b19145160e | ||
|
c7ada71ef5 | ||
|
4951229576 | ||
|
d98c1bddec | ||
|
b0d0e93364 | ||
|
f20a562439 | ||
|
4ae8475f5e | ||
|
fd4c627c61 | ||
|
a867d48232 | ||
|
f6bf61fce9 | ||
|
c60c9a8f74 | ||
|
dc021ab71e | ||
|
18b5551f6c | ||
|
6fcd8771a5 | ||
|
1fef4c3d2e | ||
|
ee6ed2bf0b | ||
|
57b67fee09 | ||
|
a6cbacae72 | ||
|
1e0f8e2484 | ||
|
bcb4c6d7b0 | ||
|
ea1d5907c1 | ||
|
05bac38fc3 | ||
|
69746cd369 | ||
|
ff3db531e5 | ||
|
558de7ba3f | ||
|
af15116bf9 | ||
|
36e5a9747b | ||
|
1d66b47f5f | ||
|
1346dd3616 | ||
|
b6ec5e108b | ||
|
5b2833350c | ||
|
66acb380ab | ||
|
00c62f2ad4 | ||
|
7205863d95 | ||
|
2a4274d583 | ||
|
087184b598 | ||
|
e5600e0be7 | ||
|
964f3128d2 | ||
|
69905cdc55 | ||
|
bf4e277db7 | ||
|
eaa7cca278 | ||
|
0e115bb808 | ||
|
1897f5567b | ||
|
d647528b3c | ||
|
07d42cdb9c | ||
|
dabb960c94 | ||
|
c71e794051 | ||
|
1584c0cbb2 | ||
|
22f0f1abf4 | ||
|
205f92d093 | ||
|
7488ac15a7 | ||
|
44f5db993a | ||
|
f76eae23ca | ||
|
5e2a18f819 | ||
|
2f6e5d53c2 | ||
|
50e6c4d965 | ||
|
3ad0554a7d | ||
|
113ec78c67 | ||
|
f814927eca | ||
|
a9719feeec | ||
|
6dc4f1b448 | ||
|
e1fa17691d | ||
|
42e61d6e1f | ||
|
2bf3e6bd3c | ||
|
608b2f868d | ||
|
46638bab5b | ||
|
4607362e46 | ||
|
041b2dfcc1 | ||
|
7ad0dd43e2 | ||
|
35339f7328 | ||
|
e474e7cd75 | ||
|
612fab2aef | ||
|
3f67bd471b | ||
|
cb29dcd6cc | ||
|
d428e89c30 | ||
|
9b2aeb7480 | ||
|
d9ad69c7ff | ||
|
16fc058264 | ||
|
520b143165 | ||
|
95c37a03f8 | ||
|
0d058b9c9c | ||
|
7c72b5e69b | ||
|
3ec254e908 | ||
|
fda13c004e | ||
|
3af85eeea6 | ||
|
c08616e6df | ||
|
7faa0f8a54 | ||
|
26c5fe2e69 | ||
|
6bdaa8352b | ||
|
6367a1fd15 | ||
|
2c5ff64d42 | ||
|
e614cb41d8 | ||
|
82737e2280 | ||
|
3b5c27096b | ||
|
8a85830bd3 | ||
|
19ac90688e | ||
|
5f4a6bc462 | ||
|
4c7f3166d4 | ||
|
4233f4dd88 | ||
|
bd09312418 | ||
|
11ab07b238 | ||
|
d2e2f089fb | ||
|
d619f98de7 | ||
|
89228a52dc | ||
|
90a49efa4a | ||
|
a7423caeb1 | ||
|
6f31a2c228 | ||
|
fc98b0882f | ||
|
dff05967ea | ||
|
ec836a2f9d | ||
|
737c85cf00 | ||
|
ff7b07f464 | ||
|
19422b5afa | ||
|
6b93e413b6 | ||
|
ab72736bcc | ||
|
38939e5d05 | ||
|
1a90a0e0ad | ||
|
7aa9fa4646 | ||
|
82d788c8d3 | ||
|
ab8176efcb | ||
|
b4c3e7a928 | ||
|
2db263fb68 | ||
|
5fd4d37972 | ||
|
9b1dbf351a | ||
|
4c7c058e0d | ||
|
f8dc08b02b | ||
|
0e6bc3ce54 | ||
|
fcb018406d | ||
|
40756a5e4b | ||
|
61b12bdebd | ||
|
8b1c41ae1e | ||
|
d654564f6b | ||
|
8bd22ebafa | ||
|
647e66d57b | ||
|
67c8ac1aa3 | ||
|
f336c7ae53 | ||
|
9ea1dad62d | ||
|
58bc374e64 | ||
|
cea0d4887d | ||
|
d5e73ecd8b | ||
|
2235a0498b | ||
|
3f9b92831c | ||
|
5680750c82 | ||
|
298e3efe49 | ||
|
7b2bd6f9eb | ||
|
d935e07990 | ||
|
868a74c184 | ||
|
a86af9736b | ||
|
8bd4d27d2f | ||
|
94951c59f3 | ||
|
e39c83a5a6 | ||
|
516a5f03e3 | ||
|
992150804a | ||
|
e905aa76a0 | ||
|
940b365447 | ||
|
d4d1c35264 | ||
|
5b818c8258 | ||
|
dedfae7b33 | ||
|
aa91a7fe24 | ||
|
822a4ae776 | ||
|
c6eb1c813c | ||
|
0d50676586 | ||
|
a2a3297986 | ||
|
8bdab73ae9 | ||
|
4469bb7bee | ||
|
b2dc460b4b | ||
|
3b281a8c3f | ||
|
fe40a0a677 | ||
|
b8c2bd3564 | ||
|
be236313e9 | ||
|
7a285d11a5 | ||
|
6e56a0f568 | ||
|
10d5c4334b | ||
|
8a5e90e562 | ||
|
c7c7badaf0 | ||
|
183e86aad6 | ||
|
5fbbcfc888 | ||
|
5169deb005 | ||
|
98fa89bd80 | ||
|
db4f5f9011 | ||
|
33aaf8afd2 | ||
|
3902d6361e | ||
|
d8d5249a23 | ||
|
42828efa19 | ||
|
a75b40bbfb | ||
|
4ebf621e11 | ||
|
cee82f39c2 | ||
|
eb9e0e0543 | ||
|
35c3ee023b | ||
|
2134f116da | ||
|
feb3d15968 | ||
|
4910dfd527 | ||
|
94252de73f | ||
|
dc5a157dad | ||
|
bf8411cc24 | ||
|
a9648f803c | ||
|
b2b4eed4fa | ||
|
7665eb6bf2 | ||
|
40c1ff0e1a | ||
|
6ceb1f6c02 | ||
|
8c37af6207 | ||
|
7baf5e44fd | ||
|
8fff672d2f | ||
|
d4fe719a2c | ||
|
108d5ae830 | ||
|
867c3207c5 | ||
|
0c257b763d | ||
|
58af2b00cb | ||
|
1d78ce4b72 | ||
|
26d9d826a3 | ||
|
bb9957be24 | ||
|
0dce279fd0 | ||
|
884239bc26 | ||
|
dfdd5f8d20 | ||
|
b5f0612e78 | ||
|
dc044e684d | ||
|
8f1dddb8a3 | ||
|
763f91fd4c | ||
|
dd1c06013b | ||
|
748659e78e | ||
|
b265b8b1e0 | ||
|
7b3c0915d8 | ||
|
d0335b6b16 | ||
|
6d35020840 | ||
|
cedd4b47b3 | ||
|
45a672ab0d | ||
|
6798e01f49 | ||
|
c0678e9a90 | ||
|
156e67bc52 | ||
|
9b1456e1a7 | ||
|
f9b61546ab | ||
|
1b3a33104a | ||
|
d819c05669 | ||
|
68729e3b54 | ||
|
90a3d7aa68 | ||
|
b3349176d9 | ||
|
e72dab2a6e | ||
|
b54debe2e5 | ||
|
95ce4f0dc0 | ||
|
c9ba182a2e | ||
|
716954aa9a | ||
|
5c5a3f614f | ||
|
229d845a42 | ||
|
d1a8fa38b0 | ||
|
899f13cb35 | ||
|
0409c2ef79 | ||
|
83b065180f | ||
|
34a003d0e5 | ||
|
7b89bb449d | ||
|
4aca4ad495 | ||
|
99d44f2a92 | ||
|
c9606f98d3 | ||
|
af217b4831 | ||
|
f45f2d5df9 | ||
|
c8c4208bb4 | ||
|
dc8b8ae6c4 | ||
|
7aa4a1bf82 | ||
|
e2548ef6b1 | ||
|
abde9b7897 | ||
|
be1c2a7b90 | ||
|
55a4bb7621 | ||
|
37ca5ff84e | ||
|
d2256eabfa | ||
|
cbb8d4e1b6 | ||
|
785ad7f3a1 | ||
|
5d9b87dace | ||
|
feb5484cf6 | ||
|
3821a15f9d | ||
|
e5f85c931c | ||
|
6c99de1e89 | ||
|
3613f6f8de | ||
|
945e619d55 | ||
|
5220b13e7d | ||
|
7ea8d0c0f7 | ||
|
996585d7ac | ||
|
ce115eadbb | ||
|
aebdc9e208 | ||
|
b0bceefc0e | ||
|
bf37c5cb51 | ||
|
16215dde3b | ||
|
2ac10e8127 | ||
|
dcb924abac | ||
|
94e18146fd | ||
|
2a619849f4 | ||
|
1e57ee5fb3 | ||
|
db721a9d10 | ||
|
40951e8da0 | ||
|
f44b4bb0e0 | ||
|
b330d54ca2 | ||
|
2678ff4477 | ||
|
995e45d28f | ||
|
9ca27d7c12 | ||
|
4183dae458 | ||
|
5426be9fa0 | ||
|
9d8034e010 | ||
|
647ad841df | ||
|
a66a1e6f8e | ||
|
ebfd860458 | ||
|
740476460f | ||
|
2b6a14a348 | ||
|
77311f42cd | ||
|
a0e89103af | ||
|
5cdbe9338b | ||
|
f7b84238df | ||
|
8b039c61ed | ||
|
f227335e14 | ||
|
ce7a8590db | ||
|
d497fa8ed7 | ||
|
6b940c4366 | ||
|
f167e8ea0a | ||
|
de703531f6 | ||
|
c72f9fbdb1 | ||
|
09eaf18632 | ||
|
5cee20163d | ||
|
63c7e9710b | ||
|
6f27b9c13f | ||
|
76e68c09d8 | ||
|
aea389cd3d | ||
|
9ce18b128e | ||
|
a7c954c6bc | ||
|
a0880c4a16 | ||
|
2c90df2c2d | ||
|
71f15e1736 | ||
|
0b14ab5032 | ||
|
2771e56357 | ||
|
1479b818ea | ||
|
4f6de892b5 | ||
|
e540260377 | ||
|
f3f21bbf73 | ||
|
44a1389dd7 | ||
|
1b05261a97 | ||
|
d55334739c | ||
|
c511ed380e | ||
|
b59ecf0370 | ||
|
65b038afcd | ||
|
5fbde0dca0 | ||
|
ab69e502da | ||
|
52065dda6b | ||
|
7cd8e48145 | ||
|
2a7f143bbf | ||
|
4a676b01e1 | ||
|
18c9833104 | ||
|
7e2787704b | ||
|
b13c2ccd32 | ||
|
4795d8f48c | ||
|
808a06b0af | ||
|
70a42afab8 | ||
|
ea210d6aac | ||
|
f70cded634 | ||
|
cc6e1b4052 | ||
|
1ce5ba4f06 | ||
|
2b23a1d048 | ||
|
37f262177d | ||
|
7ded510625 | ||
|
797a987e2b | ||
|
062dee987f | ||
|
1054931e63 | ||
|
3720a881a4 | ||
|
f379b4e5ab | ||
|
9a9e86829e | ||
|
66cd4abd8b | ||
|
ba4470f155 | ||
|
b95ec019de | ||
|
d3a40ebca8 | ||
|
5d335049a2 | ||
|
bd51e2ab55 | ||
|
f8278bd44e | ||
|
4797cd1eca | ||
|
706d244ff8 | ||
|
5b8cd18128 | ||
|
8a854bb37d | ||
|
6e6f892cb0 | ||
|
2b4ddfa072 | ||
|
c9adff5a25 | ||
|
503cfff82e | ||
|
5e713f0c2a | ||
|
e035007070 | ||
|
17a94395f3 | ||
|
0ab6c8e4b0 | ||
|
8284169923 | ||
|
5f9094c540 | ||
|
332ac9c109 | ||
|
9ba49f35ff | ||
|
d0646f12e6 | ||
|
a8817c75b0 | ||
|
7fc50f2629 | ||
|
b2d9684738 | ||
|
8ab284ff98 | ||
|
a099d29524 | ||
|
cf44af0065 | ||
|
b5bf8b6545 | ||
|
4cc3fa4d89 | ||
|
ed50e202d7 | ||
|
6d865af15a | ||
|
66d331ddb8 | ||
|
0903c03a29 | ||
|
5f546b6c6d | ||
|
9bb73bb35b | ||
|
2ca5b04de2 | ||
|
e883c1e678 | ||
|
4fc434a222 | ||
|
ecfa747a2c | ||
|
dc28ebfa50 | ||
|
6596eba6ca | ||
|
7194f9aac0 | ||
|
e4fe1cfa90 | ||
|
5bc73548b3 | ||
|
2156848e4a | ||
|
3f807b3e51 | ||
|
d786862a60 | ||
|
fb75bafe96 | ||
|
66f781b716 | ||
|
b3dc409926 | ||
|
287ed06b6a | ||
|
df1d013b1c | ||
|
fdb95484c1 | ||
|
4cf1f29e0a | ||
|
332fd9d1f6 | ||
|
039d881a07 | ||
|
b8176a9fe9 | ||
|
65937d6f4c | ||
|
590bf74e98 | ||
|
642a3e10ce | ||
|
52a8cf92c8 | ||
|
fc68ee56d5 | ||
|
644f4803df | ||
|
eda6106de8 | ||
|
3a1691066e | ||
|
b02039bad4 | ||
|
6527a9e9bb | ||
|
c59ad4d446 | ||
|
f475cbc5d8 | ||
|
00452cc505 | ||
|
23660961bd | ||
|
742ff183bf | ||
|
dca8c28b84 | ||
|
46079393d5 | ||
|
517e4a4507 | ||
|
6f3ae6da9d | ||
|
273136ab23 | ||
|
e74f86e118 | ||
|
84d4d3b165 | ||
|
c355cb8bd5 | ||
|
2957034286 | ||
|
36b4fbd303 | ||
|
f57cf46313 | ||
|
244ddc7ce2 | ||
|
4d161aea07 | ||
|
cf9101d157 | ||
|
614c8a1d13 | ||
|
879ab7951d | ||
|
311b42ad25 | ||
|
0ebbbac9a6 | ||
|
d2f9fcdda0 | ||
|
cfe5690a73 | ||
|
a055b3ff5c | ||
|
18f37ec2a8 | ||
|
14b4e5aeec | ||
|
a980930e69 | ||
|
1b4eb70d8d | ||
|
1856ccc3aa | ||
|
3217c67ff6 | ||
|
54d5f1cb1b | ||
|
e49d002941 | ||
|
4822b8bf23 | ||
|
198a6d5665 | ||
|
c7b9ec3a4c | ||
|
f46e10e11c | ||
|
b9acc4ecf8 | ||
|
403d094a3d | ||
|
3b1f11e5a8 | ||
|
ddba06cca3 | ||
|
bf89af0da9 | ||
|
5a30164848 | ||
|
0c4e200900 | ||
|
fe8e8f041c | ||
|
43084d9d86 | ||
|
e1e1b4e278 | ||
|
14f8239ba3 | ||
|
e660a70d00 | ||
|
119d30bb16 | ||
|
5686de56e2 | ||
|
e0214a6a9f | ||
|
330de495db | ||
|
dcc7fe55f4 | ||
|
3274b4c79a | ||
|
cbfa4b1c41 | ||
|
5f7d2f2a68 | ||
|
e38bdbe508 | ||
|
c352b94b38 | ||
|
6b0106e385 | ||
|
60021e5123 | ||
|
76d3157247 | ||
|
7c24778460 | ||
|
d43072663e | ||
|
8231db4a5a | ||
|
eb3562567d | ||
|
fe5dd5e8dc | ||
|
5872928812 | ||
|
8a8f4bb388 | ||
|
0e8d5fd5ec | ||
|
b9344149b0 | ||
|
5053a6852f | ||
|
bb3faca533 | ||
|
4f7fcbfdf0 | ||
|
87c1cc88be | ||
|
1d78551f4c | ||
|
b36d08db8e | ||
|
c99b1a1867 | ||
|
fc4380e5cc | ||
|
850ed7f76b | ||
|
0f6aa3befb | ||
|
ddd976162c | ||
|
cdd19e182b | ||
|
afc22a547e | ||
|
79ca54c5af | ||
|
0aacf20c16 | ||
|
cdfb43dbd8 | ||
|
35ec8b951c | ||
|
05bfaa0035 | ||
|
f5705b1153 | ||
|
ed1353a4eb | ||
|
a79922d7c9 | ||
|
7a7cbd570c | ||
|
d7865cfaf0 | ||
|
ead01ce1d0 | ||
|
8aca012c99 | ||
|
67a4dc63ca | ||
|
ce0678784b | ||
|
cbc4bbb818 | ||
|
1c558a884d | ||
|
d84d1428b2 | ||
|
b870ee8d62 | ||
|
ef18581e71 | ||
|
177bbceaf4 | ||
|
a13174ac4d | ||
|
e181b7d24b | ||
|
e631aa0e8a | ||
|
575ad75a0a | ||
|
394f667ab0 | ||
|
c695572b28 | ||
|
f80cf43ae8 | ||
|
79141edf70 | ||
|
b1e58396d1 | ||
|
b9cd113dc0 | ||
|
4a512af178 | ||
|
9506e9b8b4 | ||
|
6b57d29f51 | ||
|
3ff41d2002 | ||
|
f41dafe76d | ||
|
f2c4dde56e | ||
|
6f89a50fe5 | ||
|
3a22132363 | ||
|
e234440ce6 | ||
|
26685334a1 | ||
|
4d79dd7076 | ||
|
f5394534f7 | ||
|
faa66e01b6 | ||
|
bf4cb02de5 | ||
|
642b9a63d3 | ||
|
1ed7422171 | ||
|
3dd8a52f7d | ||
|
a55c55bbdb | ||
|
b851fd0ecc | ||
|
c8f7fe15ef | ||
|
73133f5ba5 | ||
|
eaf2e816b4 | ||
|
62020864ef | ||
|
f12e3ec663 | ||
|
5226df53a2 | ||
|
a59c67d774 | ||
|
1b1d5e9b4c | ||
|
37fc2d09bb | ||
|
bc94466cf7 | ||
|
6af7b6fce9 | ||
|
f2ae899938 | ||
|
c398a3c4f5 | ||
|
27027ec412 | ||
|
ddf9e83a9b | ||
|
0f661e5a34 | ||
|
09a53d5c4e | ||
|
542ab737a2 | ||
|
6e1276293f | ||
|
4e768e9103 | ||
|
55cdca0c7d | ||
|
9b52395786 | ||
|
50b02c800c | ||
|
2bdae5ea5c | ||
|
c49827ce25 | ||
|
64db701498 | ||
|
e16ce4b4f1 | ||
|
77d1e87fdb | ||
|
7d7adeeca0 | ||
|
8ad9c529b6 | ||
|
274512a58e | ||
|
ef16561272 | ||
|
767099b7ea | ||
|
98350860eb | ||
|
1343948d33 | ||
|
e616add75a | ||
|
b33b7115ef | ||
|
fb0bb62eaf | ||
|
5f84da61c8 | ||
|
6e6babd2e3 | ||
|
b28e08e2c7 | ||
|
718728a672 | ||
|
5de77e35dc | ||
|
6aef7246a0 | ||
|
5a41e9555e | ||
|
6598b585a2 | ||
|
a81474b40a | ||
|
ee159f5b36 | ||
|
ced64a5d1f | ||
|
689a4e6aae | ||
|
21b3ba2bf6 | ||
|
7be2e1b9e5 | ||
|
c1c2228937 | ||
|
3b9a66d1d8 | ||
|
a5ce5bf9ec | ||
|
43a1575187 | ||
|
eb5f207cc1 | ||
|
de3f055323 | ||
|
6012cdd9a5 | ||
|
0fab8ff935 | ||
|
00ee2d3bf6 | ||
|
c2a2e9f585 | ||
|
31fff7e021 | ||
|
0dda01269f | ||
|
d58b0e8f74 | ||
|
1bbb21c7c6 | ||
|
24713f54e2 | ||
|
5e2bd76e10 | ||
|
78d4b5797b | ||
|
ff91521a67 | ||
|
0525754337 | ||
|
ca8c525de0 | ||
|
1e7d2fcfd9 | ||
|
7e983bebb9 | ||
|
f927193ae9 | ||
|
a102bf04f4 | ||
|
1f6d9f0211 | ||
|
919948489d | ||
|
12efd5c11f | ||
|
25a2144b31 | ||
|
59682b5ba6 | ||
|
7deaeca7b5 | ||
|
a7a6adfa34 | ||
|
7f19f8c112 | ||
|
943465a390 | ||
|
2824878065 | ||
|
508a1230e9 | ||
|
0ad7ef43d5 | ||
|
67171e05b9 | ||
|
adebb7ff6d | ||
|
6fbcd46a76 | ||
|
ef3a592807 | ||
|
d8d01b077d | ||
|
831e2e60ed | ||
|
2d858e6e11 | ||
|
f9c3715d8d | ||
|
359f5b5f49 | ||
|
ed51b77b0e | ||
|
47082ceee9 | ||
|
98497f2a37 | ||
|
d3a74ed361 | ||
|
7f2f480b25 | ||
|
34d1422868 | ||
|
3248637e8c | ||
|
509ab82745 | ||
|
7f325e3eb5 | ||
|
e23ca4b8c1 | ||
|
a0f309c957 | ||
|
0db4f1643d | ||
|
cfa5888be9 | ||
|
bf8e0827e2 | ||
|
3172a5f216 | ||
|
456fc5b991 | ||
|
d9509474b0 | ||
|
e7a289ffb5 | ||
|
b9a4f0f1e0 | ||
|
0f4e5a8f6d | ||
|
83e1191a8a | ||
|
ad1e57316f | ||
|
2c791f5123 | ||
|
25a17ae2da | ||
|
0591f8a39f | ||
|
eb61b06784 | ||
|
0d1a4ec7ea | ||
|
5f82752416 | ||
|
332de409b8 | ||
|
737b3299ff | ||
|
24d8784e1b | ||
|
7708f61343 | ||
|
1a37d97a61 | ||
|
046984a447 | ||
|
1934bb71f0 | ||
|
5f516047bd | ||
|
e930ce4d47 | ||
|
3dbdf88124 | ||
|
b3ef9b0476 | ||
|
d428ce162b | ||
|
bc323e9945 | ||
|
ef69feeae7 | ||
|
8477920475 | ||
|
e36143b61c | ||
|
aa97253ec7 | ||
|
0fab0e4fc0 | ||
|
90a4949d76 | ||
|
1466fb4d6c | ||
|
d41172abb6 | ||
|
24ca81e91c | ||
|
1cae964c09 | ||
|
dd671795e6 | ||
|
2948c0c860 | ||
|
978fbf2cf9 | ||
|
60ee000b6c | ||
|
634ab7ec38 | ||
|
f98a12b96f | ||
|
7e5aa9aecf | ||
|
1c7381376c | ||
|
c7ce42fb3f | ||
|
fc3a8bb4ae | ||
|
bee8a4fcdc | ||
|
82b39586f0 | ||
|
c365c6f6e0 | ||
|
9afd52108b | ||
|
97252bb5da | ||
|
7eeaeb01a0 | ||
|
b3e44b84d2 | ||
|
f984595b97 | ||
|
af23cd4948 | ||
|
dc05ca0484 | ||
|
f94e069792 | ||
|
f01d78a9ea | ||
|
cd32f452e9 | ||
|
66cb7333c1 | ||
|
08633a993d | ||
|
2c782a23d8 | ||
|
c7b7527183 | ||
|
80bd11b44e | ||
|
99a596b2e1 | ||
|
cfde218d32 | ||
|
d8cefddebd | ||
|
50c7066f88 | ||
|
97f25de0dc | ||
|
a95dcf488d | ||
|
0fe51d355c | ||
|
97694d5d59 | ||
|
3d1b5a7394 | ||
|
e72fe3683c | ||
|
df1eaf54c8 | ||
|
44c10b60cd | ||
|
467d14bacb | ||
|
6d73554967 | ||
|
36b5bf3bb2 | ||
|
d14db1d3fb | ||
|
9c97ab14f8 | ||
|
6558ff7e05 | ||
|
86473d5639 | ||
|
374310d13c | ||
|
4396ef83a3 | ||
|
6b9ef4ab31 | ||
|
3851408100 | ||
|
794c5012ad | ||
|
1ba9f7d7d9 | ||
|
9b4330d618 | ||
|
3a32b742e8 | ||
|
87b3d25c0f | ||
|
9f28649a3a | ||
|
8f9df8961b | ||
|
9e9217bfcb | ||
|
ffdd5a3631 | ||
|
db4bf8d35a | ||
|
7b2859f96e | ||
|
03c5c33ea7 |
3
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# These are supported funding model platforms
|
||||||
|
|
||||||
|
github: [jendib]
|
84
.github/workflows/build-deploy.yml
vendored
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
name: Maven CI/CD
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [master]
|
||||||
|
tags: [v*]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_and_publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up JDK 11
|
||||||
|
uses: actions/setup-java@v2
|
||||||
|
with:
|
||||||
|
java-version: "11"
|
||||||
|
distribution: "temurin"
|
||||||
|
cache: maven
|
||||||
|
- name: Install test dependencies
|
||||||
|
run: sudo apt-get update && sudo apt-get -y -q --no-install-recommends install ffmpeg mediainfo tesseract-ocr tesseract-ocr-deu
|
||||||
|
- name: Build with Maven
|
||||||
|
run: mvn --batch-mode -Pprod clean install
|
||||||
|
- name: Upload war artifact
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: docs-web-ci.war
|
||||||
|
path: docs-web/target/docs*.war
|
||||||
|
|
||||||
|
build_docker_image:
|
||||||
|
name: Publish to Docker Hub
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: [build_and_publish]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
-
|
||||||
|
name: Download war artifact
|
||||||
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: docs-web-ci.war
|
||||||
|
path: docs-web/target
|
||||||
|
-
|
||||||
|
name: Setup up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
-
|
||||||
|
name: Login to DockerHub
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
-
|
||||||
|
name: Populate Docker metadata
|
||||||
|
id: metadata
|
||||||
|
uses: docker/metadata-action@v3
|
||||||
|
with:
|
||||||
|
images: sismics/docs
|
||||||
|
flavor: |
|
||||||
|
latest=false
|
||||||
|
tags: |
|
||||||
|
type=ref,event=tag
|
||||||
|
type=raw,value=latest,enable=${{ github.ref_type != 'tag' }}
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.title = Teedy
|
||||||
|
org.opencontainers.image.description = Teedy is an open source, lightweight document management system for individuals and businesses.
|
||||||
|
org.opencontainers.image.created = ${{ github.event_created_at }}
|
||||||
|
org.opencontainers.image.author = Sismics
|
||||||
|
org.opencontainers.image.url = https://teedy.io/
|
||||||
|
org.opencontainers.image.vendor = Sismics
|
||||||
|
org.opencontainers.image.license = GPLv2
|
||||||
|
org.opencontainers.image.version = ${{ github.event_head_commit.id }}
|
||||||
|
-
|
||||||
|
name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
tags: ${{ steps.metadata.outputs.tags }}
|
||||||
|
labels: ${{ steps.metadata.outputs.labels }}
|
12
.gitignore
vendored
@ -5,7 +5,17 @@
|
|||||||
/*/gen
|
/*/gen
|
||||||
/*/target
|
/*/target
|
||||||
/*/build
|
/*/build
|
||||||
/*/*.iml
|
|
||||||
/out
|
/out
|
||||||
/.idea
|
/.idea
|
||||||
/.project
|
/.project
|
||||||
|
*.iml
|
||||||
|
node_modules
|
||||||
|
import_test
|
||||||
|
teedy-importer-linux
|
||||||
|
teedy-importer-macos
|
||||||
|
teedy-importer-win.exe
|
||||||
|
docs/*
|
||||||
|
!docs/.gitkeep
|
||||||
|
|
||||||
|
#macos
|
||||||
|
.DS_Store
|
||||||
|
46
CODE_OF_CONDUCT.md
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@sismicsdocs.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/4/
|
79
Dockerfile
@ -1,10 +1,75 @@
|
|||||||
FROM sismics/debian-java7-jetty9
|
FROM ubuntu:22.04
|
||||||
MAINTAINER benjamin.gam@gmail.com
|
LABEL maintainer="b.gamard@sismics.com"
|
||||||
|
|
||||||
RUN apt-get -y -q install tesseract-ocr tesseract-ocr-fra tesseract-ocr-jpn
|
# Run Debian in non interactive mode
|
||||||
|
ENV DEBIAN_FRONTEND noninteractive
|
||||||
|
|
||||||
ENV TESSDATA_PREFIX /usr/share/tesseract-ocr
|
# Configure env
|
||||||
ENV LC_NUMERIC C
|
ENV LANG C.UTF-8
|
||||||
|
ENV LC_ALL C.UTF-8
|
||||||
|
ENV JAVA_HOME /usr/lib/jvm/java-11-openjdk-amd64/
|
||||||
|
ENV JAVA_OPTIONS -Dfile.encoding=UTF-8 -Xmx1g
|
||||||
|
ENV JETTY_VERSION 11.0.20
|
||||||
|
ENV JETTY_HOME /opt/jetty
|
||||||
|
|
||||||
ADD docs-web/target/docs-web-*.war /opt/jetty/webapps/docs.war
|
# Install packages
|
||||||
ADD docs.xml /opt/jetty/webapps/docs.xml
|
RUN apt-get update && \
|
||||||
|
apt-get -y -q --no-install-recommends install \
|
||||||
|
vim less procps unzip wget tzdata openjdk-11-jdk \
|
||||||
|
ffmpeg \
|
||||||
|
mediainfo \
|
||||||
|
tesseract-ocr \
|
||||||
|
tesseract-ocr-ara \
|
||||||
|
tesseract-ocr-ces \
|
||||||
|
tesseract-ocr-chi-sim \
|
||||||
|
tesseract-ocr-chi-tra \
|
||||||
|
tesseract-ocr-dan \
|
||||||
|
tesseract-ocr-deu \
|
||||||
|
tesseract-ocr-fin \
|
||||||
|
tesseract-ocr-fra \
|
||||||
|
tesseract-ocr-heb \
|
||||||
|
tesseract-ocr-hin \
|
||||||
|
tesseract-ocr-hun \
|
||||||
|
tesseract-ocr-ita \
|
||||||
|
tesseract-ocr-jpn \
|
||||||
|
tesseract-ocr-kor \
|
||||||
|
tesseract-ocr-lav \
|
||||||
|
tesseract-ocr-nld \
|
||||||
|
tesseract-ocr-nor \
|
||||||
|
tesseract-ocr-pol \
|
||||||
|
tesseract-ocr-por \
|
||||||
|
tesseract-ocr-rus \
|
||||||
|
tesseract-ocr-spa \
|
||||||
|
tesseract-ocr-swe \
|
||||||
|
tesseract-ocr-tha \
|
||||||
|
tesseract-ocr-tur \
|
||||||
|
tesseract-ocr-ukr \
|
||||||
|
tesseract-ocr-vie \
|
||||||
|
tesseract-ocr-sqi \
|
||||||
|
&& apt-get clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
RUN dpkg-reconfigure -f noninteractive tzdata
|
||||||
|
|
||||||
|
# Install Jetty
|
||||||
|
RUN wget -nv -O /tmp/jetty.tar.gz \
|
||||||
|
"https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-home/${JETTY_VERSION}/jetty-home-${JETTY_VERSION}.tar.gz" \
|
||||||
|
&& tar xzf /tmp/jetty.tar.gz -C /opt \
|
||||||
|
&& mv /opt/jetty* /opt/jetty \
|
||||||
|
&& useradd jetty -U -s /bin/false \
|
||||||
|
&& chown -R jetty:jetty /opt/jetty \
|
||||||
|
&& mkdir /opt/jetty/webapps \
|
||||||
|
&& chmod +x /opt/jetty/bin/jetty.sh
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# Install app
|
||||||
|
RUN mkdir /app && \
|
||||||
|
cd /app && \
|
||||||
|
java -jar /opt/jetty/start.jar --add-modules=server,http,webapp,deploy
|
||||||
|
|
||||||
|
ADD docs.xml /app/webapps/docs.xml
|
||||||
|
ADD docs-web/target/docs-web-*.war /app/webapps/docs.war
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
CMD ["java", "-jar", "/opt/jetty/start.jar"]
|
||||||
|
238
README.md
@ -1,50 +1,206 @@
|
|||||||
Sismics Docs
|
<h3 align="center">
|
||||||
============
|
<img src="https://teedy.io/img/github-title.png" alt="Teedy" width=500 />
|
||||||
|
</h3>
|
||||||
|
|
||||||
_Web interface_
|
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||||
|
[](https://github.com/sismics/docs/actions/workflows/build-deploy.yml)
|
||||||
|
|
||||||

|
Teedy is an open source, lightweight document management system for individuals and businesses.
|
||||||
|
|
||||||
_Android application_
|
<hr />
|
||||||
|
<h2 align="center">
|
||||||
|
✨ <a href="https://github.com/users/jendib/sponsorship">Sponsor this project if you use and appreciate it!</a> ✨
|
||||||
|
</h2>
|
||||||
|
<hr />
|
||||||
|
|
||||||
  
|

|
||||||
|
|
||||||
What is Docs?
|
# Demo
|
||||||
---------------
|
|
||||||
|
|
||||||
Docs is an open source, lightweight document management system.
|
A demo is available at [demo.teedy.io](https://demo.teedy.io)
|
||||||
|
|
||||||
Docs is written in Java, and may be run on any operating system with Java support.
|
- Guest login is enabled with read access on all documents
|
||||||
|
- "admin" login with "admin" password
|
||||||
|
- "demo" login with "password" password
|
||||||
|
|
||||||
Features
|
# Features
|
||||||
--------
|
|
||||||
|
|
||||||
- Responsive user interface
|
- Responsive user interface
|
||||||
- Optical character recognition
|
- Optical character recognition
|
||||||
- Support image and PDF files
|
- LDAP authentication 
|
||||||
- Flexible search engine
|
- Support image, PDF, ODT, DOCX, PPTX files
|
||||||
- Full text search in image and PDF
|
- Video file support
|
||||||
- SHA-256 encryption
|
- Flexible search engine with suggestions and highlighting
|
||||||
- Tag system
|
- Full text search in all supported files
|
||||||
- Multi-users ACL system
|
- All [Dublin Core](http://dublincore.org/) metadata
|
||||||
|
- Custom user-defined metadata 
|
||||||
|
- Workflow system 
|
||||||
|
- 256-bit AES encryption of stored files
|
||||||
|
- File versioning 
|
||||||
|
- Tag system with nesting
|
||||||
|
- Import document from email (EML format)
|
||||||
|
- Automatic inbox scanning and importing
|
||||||
|
- User/group permission system
|
||||||
|
- 2-factor authentication
|
||||||
|
- Hierarchical groups
|
||||||
|
- Audit log
|
||||||
|
- Comments
|
||||||
|
- Storage quota per user
|
||||||
- Document sharing by URL
|
- Document sharing by URL
|
||||||
- RESTful Web API
|
- RESTful Web API
|
||||||
- Modern Android client
|
- Webhooks to trigger external service
|
||||||
|
- Fully featured Android client
|
||||||
|
- [Bulk files importer](https://github.com/sismics/docs/tree/master/docs-importer) (single or scan mode)
|
||||||
|
- Tested to one million documents
|
||||||
|
|
||||||
Download
|
# Install with Docker
|
||||||
--------
|
|
||||||
|
A preconfigured Docker image is available, including OCR and media conversion tools, listening on port 8080. If no PostgreSQL config is provided, the database is an embedded H2 database. The H2 embedded database should only be used for testing. For production usage use the provided PostgreSQL configuration (check the Docker Compose example)
|
||||||
|
|
||||||
|
**The default admin password is "admin". Don't forget to change it before going to production.**
|
||||||
|
|
||||||
|
- Master branch, can be unstable. Not recommended for production use: `sismics/docs:latest`
|
||||||
|
- Latest stable version: `sismics/docs:v1.11`
|
||||||
|
|
||||||
|
The data directory is `/data`. Don't forget to mount a volume on it.
|
||||||
|
|
||||||
|
To build external URL, the server is expecting a `DOCS_BASE_URL` environment variable (for example https://teedy.mycompany.com)
|
||||||
|
|
||||||
|
## Available environment variables
|
||||||
|
|
||||||
|
- General
|
||||||
|
- `DOCS_BASE_URL`: The base url used by the application. Generated url's will be using this as base.
|
||||||
|
- `DOCS_GLOBAL_QUOTA`: Defines the default quota applying to all users.
|
||||||
|
- `DOCS_BCRYPT_WORK`: Defines the work factor which is used for password hashing. The default is `10`. This value may be `4...31` including `4` and `31`. The specified value will be used for all new users and users changing their password. Be aware that setting this factor to high can heavily impact login and user creation performance.
|
||||||
|
|
||||||
|
- Admin
|
||||||
|
- `DOCS_ADMIN_EMAIL_INIT`: Defines the e-mail-address the admin user should have upon initialization.
|
||||||
|
- `DOCS_ADMIN_PASSWORD_INIT`: Defines the password the admin user should have upon initialization. Needs to be a bcrypt hash. **Be aware that `$` within the hash have to be escaped with a second `$`.**
|
||||||
|
|
||||||
|
- Database
|
||||||
|
- `DATABASE_URL`: The jdbc connection string to be used by `hibernate`.
|
||||||
|
- `DATABASE_USER`: The user which should be used for the database connection.
|
||||||
|
- `DATABASE_PASSWORD`: The password to be used for the database connection.
|
||||||
|
- `DATABASE_POOL_SIZE`: The pool size to be used for the database connection.
|
||||||
|
|
||||||
|
- Language
|
||||||
|
- `DOCS_DEFAULT_LANGUAGE`: The language which will be used as default. Currently supported values are:
|
||||||
|
- `eng`, `fra`, `ita`, `deu`, `spa`, `por`, `pol`, `rus`, `ukr`, `ara`, `hin`, `chi_sim`, `chi_tra`, `jpn`, `tha`, `kor`, `nld`, `tur`, `heb`, `hun`, `fin`, `swe`, `lav`, `dan`
|
||||||
|
|
||||||
|
- E-Mail
|
||||||
|
- `DOCS_SMTP_HOSTNAME`: Hostname of the SMTP-Server to be used by Teedy.
|
||||||
|
- `DOCS_SMTP_PORT`: The port which should be used.
|
||||||
|
- `DOCS_SMTP_USERNAME`: The username to be used.
|
||||||
|
- `DOCS_SMTP_PASSWORD`: The password to be used.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
In the following examples some passwords are exposed in cleartext. This was done in order to keep the examples simple. We strongly encourage you to use variables with an `.env` file or other means to securely store your passwords.
|
||||||
|
|
||||||
|
|
||||||
|
### Default, using PostgreSQL
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
# Teedy Application
|
||||||
|
teedy-server:
|
||||||
|
image: sismics/docs:v1.11
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
# Map internal port to host
|
||||||
|
- 8080:8080
|
||||||
|
environment:
|
||||||
|
# Base url to be used
|
||||||
|
DOCS_BASE_URL: "https://docs.example.com"
|
||||||
|
# Set the admin email
|
||||||
|
DOCS_ADMIN_EMAIL_INIT: "admin@example.com"
|
||||||
|
# Set the admin password (in this example: "superSecure")
|
||||||
|
DOCS_ADMIN_PASSWORD_INIT: "$$2a$$05$$PcMNUbJvsk7QHFSfEIDaIOjk1VI9/E7IPjTKx.jkjPxkx2EOKSoPS"
|
||||||
|
# Setup the database connection. "teedy-db" is the hostname
|
||||||
|
# and "teedy" is the name of the database the application
|
||||||
|
# will connect to.
|
||||||
|
DATABASE_URL: "jdbc:postgresql://teedy-db:5432/teedy"
|
||||||
|
DATABASE_USER: "teedy_db_user"
|
||||||
|
DATABASE_PASSWORD: "teedy_db_password"
|
||||||
|
DATABASE_POOL_SIZE: "10"
|
||||||
|
volumes:
|
||||||
|
- ./docs/data:/data
|
||||||
|
networks:
|
||||||
|
- docker-internal
|
||||||
|
- internet
|
||||||
|
depends_on:
|
||||||
|
- teedy-db
|
||||||
|
|
||||||
|
# DB for Teedy
|
||||||
|
teedy-db:
|
||||||
|
image: postgres:13.1-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
expose:
|
||||||
|
- 5432
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: "teedy_db_user"
|
||||||
|
POSTGRES_PASSWORD: "teedy_db_password"
|
||||||
|
POSTGRES_DB: "teedy"
|
||||||
|
volumes:
|
||||||
|
- ./docs/db:/var/lib/postgresql/data
|
||||||
|
networks:
|
||||||
|
- docker-internal
|
||||||
|
|
||||||
|
networks:
|
||||||
|
# Network without internet access. The db does not need
|
||||||
|
# access to the host network.
|
||||||
|
docker-internal:
|
||||||
|
driver: bridge
|
||||||
|
internal: true
|
||||||
|
internet:
|
||||||
|
driver: bridge
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using the internal database (only for testing)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
# Teedy Application
|
||||||
|
teedy-server:
|
||||||
|
image: sismics/docs:v1.11
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
# Map internal port to host
|
||||||
|
- 8080:8080
|
||||||
|
environment:
|
||||||
|
# Base url to be used
|
||||||
|
DOCS_BASE_URL: "https://docs.example.com"
|
||||||
|
# Set the admin email
|
||||||
|
DOCS_ADMIN_EMAIL_INIT: "admin@example.com"
|
||||||
|
# Set the admin password (in this example: "superSecure")
|
||||||
|
DOCS_ADMIN_PASSWORD_INIT: "$$2a$$05$$PcMNUbJvsk7QHFSfEIDaIOjk1VI9/E7IPjTKx.jkjPxkx2EOKSoPS"
|
||||||
|
volumes:
|
||||||
|
- ./docs/data:/data
|
||||||
|
```
|
||||||
|
|
||||||
|
# Manual installation
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Java 11
|
||||||
|
- Tesseract 4 for OCR
|
||||||
|
- ffmpeg for video thumbnails
|
||||||
|
- mediainfo for video metadata extraction
|
||||||
|
- A webapp server like [Jetty](http://eclipse.org/jetty/) or [Tomcat](http://tomcat.apache.org/)
|
||||||
|
|
||||||
|
## Download
|
||||||
|
|
||||||
The latest release is downloadable here: <https://github.com/sismics/docs/releases> in WAR format.
|
The latest release is downloadable here: <https://github.com/sismics/docs/releases> in WAR format.
|
||||||
You will need a Java webapp server to run it, like [Jetty](http://eclipse.org/jetty/) or [Tomcat](http://tomcat.apache.org/)
|
**The default admin password is "admin". Don't forget to change it before going to production.**
|
||||||
|
|
||||||
How to build Docs from the sources
|
## How to build Teedy from the sources
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
Prerequisites: JDK 7 with JCE, Maven 3, Tesseract 3.02
|
Prerequisites: JDK 11, Maven 3, NPM, Grunt, Tesseract 4
|
||||||
|
|
||||||
Docs is organized in several Maven modules:
|
Teedy is organized in several Maven modules:
|
||||||
|
|
||||||
- docs-parent
|
|
||||||
- docs-core
|
- docs-core
|
||||||
- docs-web
|
- docs-web
|
||||||
- docs-web-common
|
- docs-web-common
|
||||||
@ -52,29 +208,39 @@ Docs is organized in several Maven modules:
|
|||||||
First off, clone the repository: `git clone git://github.com/sismics/docs.git`
|
First off, clone the repository: `git clone git://github.com/sismics/docs.git`
|
||||||
or download the sources from GitHub.
|
or download the sources from GitHub.
|
||||||
|
|
||||||
#### Launch the build
|
### Launch the build
|
||||||
|
|
||||||
From the `docs-parent` directory:
|
From the root directory:
|
||||||
|
|
||||||
mvn -Pinit validate -N
|
```console
|
||||||
mvn clean -DskipTests install
|
mvn clean -DskipTests install
|
||||||
|
```
|
||||||
|
|
||||||
#### Run a stand-alone version
|
### Run a stand-alone version
|
||||||
|
|
||||||
From the `docs-web` directory:
|
From the `docs-web` directory:
|
||||||
|
|
||||||
|
```console
|
||||||
mvn jetty:run
|
mvn jetty:run
|
||||||
|
```
|
||||||
|
|
||||||
#### Build a .war to deploy to your servlet container
|
### Build a .war to deploy to your servlet container
|
||||||
|
|
||||||
From the `docs-web` directory:
|
From the `docs-web` directory:
|
||||||
|
|
||||||
|
```console
|
||||||
mvn -Pprod -DskipTests clean install
|
mvn -Pprod -DskipTests clean install
|
||||||
|
```
|
||||||
|
|
||||||
You will get your deployable WAR in the `target` directory.
|
You will get your deployable WAR in the `docs-web/target` directory.
|
||||||
|
|
||||||
License
|
# Contributing
|
||||||
-------
|
|
||||||
|
|
||||||
Docs is released under the terms of the GPL license. See `COPYING` for more
|
All contributions are more than welcomed. Contributions may close an issue, fix a bug (reported or not reported), improve the existing code, add new feature, and so on.
|
||||||
|
|
||||||
|
The `master` branch is the default and base branch for the project. It is used for development and all Pull Requests should go there.
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
Teedy is released under the terms of the GPL license. See `COPYING` for more
|
||||||
information or see <http://opensource.org/licenses/GPL-2.0>.
|
information or see <http://opensource.org/licenses/GPL-2.0>.
|
||||||
|
18
docker-compose.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
# Teedy Application
|
||||||
|
teedy-server:
|
||||||
|
image: sismics/docs:v1.10
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
# Map internal port to host
|
||||||
|
- 8080:8080
|
||||||
|
environment:
|
||||||
|
# Base url to be used
|
||||||
|
DOCS_BASE_URL: "https://docs.example.com"
|
||||||
|
# Set the admin email
|
||||||
|
DOCS_ADMIN_EMAIL_INIT: "admin@example.com"
|
||||||
|
# Set the admin password (in this example: "superSecure")
|
||||||
|
DOCS_ADMIN_PASSWORD_INIT: "$$2a$$05$$PcMNUbJvsk7QHFSfEIDaIOjk1VI9/E7IPjTKx.jkjPxkx2EOKSoPS"
|
||||||
|
volumes:
|
||||||
|
- ./docs/data:/data
|
@ -1,121 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module external.linked.project.id=":app" external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$/.." external.system.id="GRADLE" external.system.module.group="docs-android" external.system.module.version="unspecified" type="JAVA_MODULE" version="4">
|
|
||||||
<component name="FacetManager">
|
|
||||||
<facet type="android-gradle" name="Android-Gradle">
|
|
||||||
<configuration>
|
|
||||||
<option name="GRADLE_PROJECT_PATH" value=":app" />
|
|
||||||
</configuration>
|
|
||||||
</facet>
|
|
||||||
<facet type="android" name="Android">
|
|
||||||
<configuration>
|
|
||||||
<option name="SELECTED_BUILD_VARIANT" value="debug" />
|
|
||||||
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
|
|
||||||
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
|
|
||||||
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
|
|
||||||
<option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
|
|
||||||
<option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
|
|
||||||
<option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
|
|
||||||
<option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugAndroidTestSources" />
|
|
||||||
<option name="ALLOW_USER_CONFIGURATION" value="false" />
|
|
||||||
<option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
|
|
||||||
<option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
|
|
||||||
<option name="RES_FOLDERS_RELATIVE_PATH" value="file://$MODULE_DIR$/src/main/res" />
|
|
||||||
<option name="ASSETS_FOLDER_RELATIVE_PATH" value="/src/main/assets" />
|
|
||||||
</configuration>
|
|
||||||
</facet>
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="false">
|
|
||||||
<output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
|
|
||||||
<output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/debug" isTestSource="false" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/debug" isTestSource="false" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/androidTest/debug" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/res" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/resources" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/apk" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/assets" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/classes" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/dependency-cache" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/dex" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/incremental" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/bundles" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/coverage-instrumented-classes" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.1.1/jars" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/22.0.0/jars" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.1.1/jars" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.shamanland/fab/0.0.6/jars" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/it.sephiroth.android.library.easing/android-easing/1.0.3/jars" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/it.sephiroth.android.library.imagezoom/imagezoom/1.0.5/jars" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/libs" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/lint" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/ndk" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/proguard" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/libs" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/manifests" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/ndk" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/pre-dexed" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/res" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/rs" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/source" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/symbols" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/build/tmp" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" exported="" name="appcompat-v7-22.1.1" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="fab-0.0.6" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="android-easing-1.0.3" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="imagezoom-1.0.5" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="eventbus-2.4.0" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="android-query.0.26.8" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="tokenautocomplete-1.2.1" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="support-v4-22.1.1" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="support-annotations-22.1.1" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="recyclerview-v7-22.0.0" level="project" />
|
|
||||||
<orderEntry type="library" exported="" name="android-async-http-1.4.6" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
@ -1,46 +1,27 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
jcenter()
|
||||||
|
google()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:1.2.3'
|
classpath 'com.android.tools.build:gradle:3.4.0'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
jcenter()
|
||||||
|
google()
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 22
|
compileSdkVersion 28
|
||||||
buildToolsVersion "22.0.1"
|
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 14
|
minSdkVersion 14
|
||||||
targetSdkVersion 22
|
targetSdkVersion 28
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName '1.0'
|
||||||
}
|
|
||||||
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_7
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_7
|
|
||||||
}
|
|
||||||
|
|
||||||
signingConfigs {
|
|
||||||
release {
|
|
||||||
storeFile file(System.getenv("TRACKINO_STORE_PATH"))
|
|
||||||
storePassword System.getenv("TRACKINO_STORE_PASS")
|
|
||||||
keyAlias System.getenv("TRACKINO_STORE_ALIAS")
|
|
||||||
keyPassword System.getenv("TRACKINO_STORE_KEYPASS")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
signingConfig signingConfigs.release
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
@ -49,11 +30,14 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(dir: 'libs', include: '*.jar')
|
implementation fileTree(dir: 'libs', include: '*.jar')
|
||||||
compile 'com.android.support:appcompat-v7:22.1.1'
|
implementation 'com.android.support:appcompat-v7:28.0.0'
|
||||||
compile 'com.android.support:recyclerview-v7:22.0.0'
|
implementation 'com.android.support:recyclerview-v7:28.0.0'
|
||||||
compile 'com.loopj.android:android-async-http:1.4.6'
|
implementation 'com.android.support:design:28.0.0'
|
||||||
compile 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5'
|
implementation 'it.sephiroth.android.library.imagezoom:imagezoom:1.0.5'
|
||||||
compile 'de.greenrobot:eventbus:2.4.0'
|
implementation 'org.greenrobot:eventbus:3.1.1'
|
||||||
compile 'com.shamanland:fab:0.0.6'
|
implementation 'com.squareup.picasso:picasso:2.5.2'
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.10.0'
|
||||||
|
implementation 'com.jakewharton.picasso:picasso2-okhttp3-downloader:1.1.0'
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.sismics.docs" >
|
package="com.sismics.docs"
|
||||||
|
android:installLocation="auto">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".MainApplication"
|
android:name=".MainApplication"
|
||||||
@ -27,6 +29,7 @@
|
|||||||
android:name=".activity.MainActivity"
|
android:name=".activity.MainActivity"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
|
android:theme="@style/AppTheme.NoActionBar"
|
||||||
android:windowSoftInputMode="adjustNothing">
|
android:windowSoftInputMode="adjustNothing">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEARCH" />
|
<action android:name="android.intent.action.SEARCH" />
|
||||||
@ -42,11 +45,24 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".activity.DocumentViewActivity"
|
android:name=".activity.DocumentViewActivity"
|
||||||
android:label="">
|
android:label="">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.DocumentEditActivity"
|
android:name=".activity.DocumentEditActivity"
|
||||||
android:label="@string/new_document">
|
android:label="@string/new_document">
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activity.AuditLogActivity"
|
||||||
|
android:label="@string/latest_activity">
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activity.UserProfileActivity">
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activity.GroupProfileActivity">
|
||||||
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".activity.SettingsActivity"
|
android:name=".activity.SettingsActivity"
|
||||||
android:label="@string/settings">
|
android:label="@string/settings">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package com.sismics.docs;
|
package com.sismics.docs;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.support.v7.app.AppCompatDelegate;
|
||||||
|
|
||||||
import com.androidquery.callback.BitmapAjaxCallback;
|
|
||||||
import com.sismics.docs.model.application.ApplicationContext;
|
import com.sismics.docs.model.application.ApplicationContext;
|
||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
|
|
||||||
@ -20,14 +20,10 @@ public class MainApplication extends Application {
|
|||||||
JSONObject json = PreferenceUtil.getCachedJson(getApplicationContext(), PreferenceUtil.PREF_CACHED_USER_INFO_JSON);
|
JSONObject json = PreferenceUtil.getCachedJson(getApplicationContext(), PreferenceUtil.PREF_CACHED_USER_INFO_JSON);
|
||||||
ApplicationContext.getInstance().setUserInfo(getApplicationContext(), json);
|
ApplicationContext.getInstance().setUserInfo(getApplicationContext(), json);
|
||||||
|
|
||||||
// TODO google docs app: right drawer with all actions, with acls, with deep metadatas
|
|
||||||
// TODO Provide documents to intent action get content
|
// TODO Provide documents to intent action get content
|
||||||
|
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
||||||
public void onLowMemory() {
|
|
||||||
BitmapAjaxCallback.clearCache();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,121 @@
|
|||||||
|
package com.sismics.docs.activity;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import com.sismics.docs.R;
|
||||||
|
import com.sismics.docs.adapter.AuditLogListAdapter;
|
||||||
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
|
import com.sismics.docs.model.application.ApplicationContext;
|
||||||
|
import com.sismics.docs.resource.AuditLogResource;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log activity.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class AuditLogActivity extends AppCompatActivity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// Check if logged in
|
||||||
|
if (!ApplicationContext.getInstance().isLoggedIn()) {
|
||||||
|
startActivity(new Intent(this, LoginActivity.class));
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle activity context
|
||||||
|
if (getIntent() == null) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input document ID (optional)
|
||||||
|
final String documentId = getIntent().getStringExtra("documentId");
|
||||||
|
|
||||||
|
// Setup the activity
|
||||||
|
setContentView(R.layout.auditlog_activity);
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
getSupportActionBar().setHomeButtonEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the swipe refresh layout
|
||||||
|
SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);
|
||||||
|
swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
|
||||||
|
android.R.color.holo_green_light,
|
||||||
|
android.R.color.holo_orange_light,
|
||||||
|
android.R.color.holo_red_light);
|
||||||
|
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
|
||||||
|
@Override
|
||||||
|
public void onRefresh() {
|
||||||
|
refreshView(documentId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Navigate to user profile on click
|
||||||
|
final ListView auditLogListView = findViewById(R.id.auditLogListView);
|
||||||
|
auditLogListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
if (auditLogListView.getAdapter() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AuditLogListAdapter adapter = (AuditLogListAdapter) auditLogListView.getAdapter();
|
||||||
|
String username = adapter.getItem(position).optString("username");
|
||||||
|
Intent intent = new Intent(AuditLogActivity.this, UserProfileActivity.class);
|
||||||
|
intent.putExtra("username", username);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get audit log list
|
||||||
|
refreshView(documentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the view.
|
||||||
|
*/
|
||||||
|
private void refreshView(String documentId) {
|
||||||
|
final SwipeRefreshLayout swipeRefreshLayout = findViewById(R.id.swipeRefreshLayout);
|
||||||
|
final ProgressBar progressBar = findViewById(R.id.progressBar);
|
||||||
|
final ListView auditLogListView = findViewById(R.id.auditLogListView);
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
auditLogListView.setVisibility(View.GONE);
|
||||||
|
AuditLogResource.list(this, documentId, new HttpCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(JSONObject response) {
|
||||||
|
auditLogListView.setAdapter(new AuditLogListAdapter(AuditLogActivity.this, response.optJSONArray("logs")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
auditLogListView.setVisibility(View.VISIBLE);
|
||||||
|
swipeRefreshLayout.setRefreshing(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package com.sismics.docs.activity;
|
package com.sismics.docs.activity;
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -17,7 +16,7 @@ import com.sismics.docs.adapter.LanguageAdapter;
|
|||||||
import com.sismics.docs.adapter.TagAutoCompleteAdapter;
|
import com.sismics.docs.adapter.TagAutoCompleteAdapter;
|
||||||
import com.sismics.docs.event.DocumentAddEvent;
|
import com.sismics.docs.event.DocumentAddEvent;
|
||||||
import com.sismics.docs.event.DocumentEditEvent;
|
import com.sismics.docs.event.DocumentEditEvent;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.resource.DocumentResource;
|
import com.sismics.docs.resource.DocumentResource;
|
||||||
import com.sismics.docs.ui.form.Validator;
|
import com.sismics.docs.ui.form.Validator;
|
||||||
import com.sismics.docs.ui.form.validator.Required;
|
import com.sismics.docs.ui.form.validator.Required;
|
||||||
@ -25,7 +24,7 @@ import com.sismics.docs.ui.view.DatePickerView;
|
|||||||
import com.sismics.docs.ui.view.TagsCompleteTextView;
|
import com.sismics.docs.ui.view.TagsCompleteTextView;
|
||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -36,8 +35,6 @@ import java.util.HashSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Document edition activity.
|
* Document edition activity.
|
||||||
*
|
*
|
||||||
@ -104,7 +101,7 @@ public class DocumentEditActivity extends AppCompatActivity {
|
|||||||
finish();
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
JSONArray tagArray = tags.optJSONArray("stats");
|
JSONArray tagArray = tags.optJSONArray("tags");
|
||||||
|
|
||||||
List<JSONObject> tagList = new ArrayList<>();
|
List<JSONObject> tagList = new ArrayList<>();
|
||||||
for (int i = 0; i < tagArray.length(); i++) {
|
for (int i = 0; i < tagArray.length(); i++) {
|
||||||
@ -124,7 +121,7 @@ public class DocumentEditActivity extends AppCompatActivity {
|
|||||||
} else {
|
} else {
|
||||||
setTitle(R.string.edit_document);
|
setTitle(R.string.edit_document);
|
||||||
titleEditText.setText(document.optString("title"));
|
titleEditText.setText(document.optString("title"));
|
||||||
descriptionEditText.setText(document.optString("description"));
|
descriptionEditText.setText(document.isNull("description") ? "" : document.optString("description"));
|
||||||
datePickerView.setDate(new Date(document.optLong("create_date")));
|
datePickerView.setDate(new Date(document.optLong("create_date")));
|
||||||
languageSpinner.setSelection(languageAdapter.getItemPosition(document.optString("language")));
|
languageSpinner.setSelection(languageAdapter.getItemPosition(document.optString("language")));
|
||||||
JSONArray documentTags = document.optJSONArray("tags");
|
JSONArray documentTags = document.optJSONArray("tags");
|
||||||
@ -165,18 +162,12 @@ public class DocumentEditActivity extends AppCompatActivity {
|
|||||||
// Cancellable progress dialog
|
// Cancellable progress dialog
|
||||||
final ProgressDialog progressDialog = ProgressDialog.show(this,
|
final ProgressDialog progressDialog = ProgressDialog.show(this,
|
||||||
getString(R.string.please_wait),
|
getString(R.string.please_wait),
|
||||||
getString(R.string.document_editing_message), true, true,
|
getString(R.string.document_editing_message), true, true);
|
||||||
new DialogInterface.OnCancelListener() {
|
|
||||||
@Override
|
|
||||||
public void onCancel(DialogInterface dialog) {
|
|
||||||
DocumentResource.cancel(DocumentEditActivity.this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Server callback
|
// Server callback
|
||||||
JsonHttpResponseHandler callback = new JsonHttpResponseHandler() {
|
HttpCallback callback = new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
// Build a fake document JSON to update the UI
|
// Build a fake document JSON to update the UI
|
||||||
final JSONObject outputDoc = new JSONObject();
|
final JSONObject outputDoc = new JSONObject();
|
||||||
try {
|
try {
|
||||||
@ -211,7 +202,7 @@ public class DocumentEditActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
Toast.makeText(DocumentEditActivity.this, R.string.error_editing_document, Toast.LENGTH_LONG).show();
|
Toast.makeText(DocumentEditActivity.this, R.string.error_editing_document, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
package com.sismics.docs.activity;
|
package com.sismics.docs.activity;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.DownloadManager;
|
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
|
||||||
import android.support.v4.app.DialogFragment;
|
import android.support.v4.app.DialogFragment;
|
||||||
import android.support.v4.view.GravityCompat;
|
import android.support.v4.view.GravityCompat;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
@ -19,11 +16,16 @@ import android.support.v7.app.AppCompatActivity;
|
|||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.format.DateFormat;
|
import android.text.format.DateFormat;
|
||||||
|
import android.text.method.LinkMovementMethod;
|
||||||
|
import android.view.ContextMenu;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@ -31,22 +33,30 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import com.sismics.docs.R;
|
import com.sismics.docs.R;
|
||||||
import com.sismics.docs.adapter.AclListAdapter;
|
import com.sismics.docs.adapter.AclListAdapter;
|
||||||
|
import com.sismics.docs.adapter.CommentListAdapter;
|
||||||
import com.sismics.docs.adapter.FilePagerAdapter;
|
import com.sismics.docs.adapter.FilePagerAdapter;
|
||||||
|
import com.sismics.docs.event.CommentAddEvent;
|
||||||
|
import com.sismics.docs.event.CommentDeleteEvent;
|
||||||
import com.sismics.docs.event.DocumentDeleteEvent;
|
import com.sismics.docs.event.DocumentDeleteEvent;
|
||||||
import com.sismics.docs.event.DocumentEditEvent;
|
import com.sismics.docs.event.DocumentEditEvent;
|
||||||
import com.sismics.docs.event.DocumentFullscreenEvent;
|
import com.sismics.docs.event.DocumentFullscreenEvent;
|
||||||
import com.sismics.docs.event.FileAddEvent;
|
import com.sismics.docs.event.FileAddEvent;
|
||||||
import com.sismics.docs.event.FileDeleteEvent;
|
import com.sismics.docs.event.FileDeleteEvent;
|
||||||
|
import com.sismics.docs.fragment.DocExportPdfFragment;
|
||||||
import com.sismics.docs.fragment.DocShareFragment;
|
import com.sismics.docs.fragment.DocShareFragment;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.model.application.ApplicationContext;
|
import com.sismics.docs.model.application.ApplicationContext;
|
||||||
|
import com.sismics.docs.resource.CommentResource;
|
||||||
import com.sismics.docs.resource.DocumentResource;
|
import com.sismics.docs.resource.DocumentResource;
|
||||||
import com.sismics.docs.resource.FileResource;
|
import com.sismics.docs.resource.FileResource;
|
||||||
import com.sismics.docs.service.FileUploadService;
|
import com.sismics.docs.service.FileUploadService;
|
||||||
|
import com.sismics.docs.util.NetworkUtil;
|
||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
import com.sismics.docs.util.TagUtil;
|
import com.sismics.docs.util.SpannableUtil;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -55,8 +65,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Document activity.
|
* Document activity.
|
||||||
*
|
*
|
||||||
@ -68,11 +76,6 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
*/
|
*/
|
||||||
public static final int REQUEST_CODE_ADD_FILE = 1;
|
public static final int REQUEST_CODE_ADD_FILE = 1;
|
||||||
|
|
||||||
/**
|
|
||||||
* Request code of editing document.
|
|
||||||
*/
|
|
||||||
public static final int REQUEST_CODE_EDIT_DOCUMENT = 2;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File view pager.
|
* File view pager.
|
||||||
*/
|
*/
|
||||||
@ -83,6 +86,11 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
*/
|
*/
|
||||||
private FilePagerAdapter filePagerAdapter;
|
private FilePagerAdapter filePagerAdapter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment list adapter.
|
||||||
|
*/
|
||||||
|
private CommentListAdapter commentListAdapter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Document displayed.
|
* Document displayed.
|
||||||
*/
|
*/
|
||||||
@ -142,7 +150,7 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
*
|
*
|
||||||
* @param document Document in JSON format
|
* @param document Document in JSON format
|
||||||
*/
|
*/
|
||||||
private void refreshDocument(JSONObject document) {
|
private void refreshDocument(final JSONObject document) {
|
||||||
this.document = document;
|
this.document = document;
|
||||||
|
|
||||||
String title = document.optString("title");
|
String title = document.optString("title");
|
||||||
@ -164,28 +172,33 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fill the layout
|
// Fill the layout
|
||||||
|
// Create date
|
||||||
TextView createdDateTextView = (TextView) findViewById(R.id.createdDateTextView);
|
TextView createdDateTextView = (TextView) findViewById(R.id.createdDateTextView);
|
||||||
createdDateTextView.setText(date);
|
createdDateTextView.setText(date);
|
||||||
|
|
||||||
|
// Description
|
||||||
TextView descriptionTextView = (TextView) findViewById(R.id.descriptionTextView);
|
TextView descriptionTextView = (TextView) findViewById(R.id.descriptionTextView);
|
||||||
if (description == null || description.isEmpty()) {
|
if (description.isEmpty() || document.isNull("description")) {
|
||||||
descriptionTextView.setVisibility(View.GONE);
|
descriptionTextView.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
descriptionTextView.setVisibility(View.VISIBLE);
|
descriptionTextView.setVisibility(View.VISIBLE);
|
||||||
descriptionTextView.setText(description);
|
descriptionTextView.setText(description);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tags
|
||||||
TextView tagTextView = (TextView) findViewById(R.id.tagTextView);
|
TextView tagTextView = (TextView) findViewById(R.id.tagTextView);
|
||||||
if (tags.length() == 0) {
|
if (tags.length() == 0) {
|
||||||
tagTextView.setVisibility(View.GONE);
|
tagTextView.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
tagTextView.setVisibility(View.VISIBLE);
|
tagTextView.setVisibility(View.VISIBLE);
|
||||||
tagTextView.setText(TagUtil.buildSpannable(tags));
|
tagTextView.setText(SpannableUtil.buildSpannableTags(tags));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Language
|
||||||
ImageView languageImageView = (ImageView) findViewById(R.id.languageImageView);
|
ImageView languageImageView = (ImageView) findViewById(R.id.languageImageView);
|
||||||
languageImageView.setImageResource(getResources().getIdentifier(language, "drawable", getPackageName()));
|
languageImageView.setImageResource(getResources().getIdentifier(language, "drawable", getPackageName()));
|
||||||
|
|
||||||
|
// Shared status
|
||||||
ImageView sharedImageView = (ImageView) findViewById(R.id.sharedImageView);
|
ImageView sharedImageView = (ImageView) findViewById(R.id.sharedImageView);
|
||||||
sharedImageView.setVisibility(shared ? View.VISIBLE : View.GONE);
|
sharedImageView.setVisibility(shared ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
@ -196,7 +209,7 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
Intent intent = new Intent(DocumentViewActivity.this, DocumentEditActivity.class);
|
Intent intent = new Intent(DocumentViewActivity.this, DocumentEditActivity.class);
|
||||||
intent.putExtra("document", DocumentViewActivity.this.document.toString());
|
intent.putExtra("document", DocumentViewActivity.this.document.toString());
|
||||||
startActivityForResult(intent, REQUEST_CODE_EDIT_DOCUMENT);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -231,20 +244,75 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Action export PDF
|
||||||
|
button = (Button) findViewById(R.id.actionExportPdf);
|
||||||
|
button.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
DialogFragment dialog = DocExportPdfFragment.newInstance(
|
||||||
|
document.optString("id"), document.optString("title"));
|
||||||
|
dialog.show(getSupportFragmentManager(), "DocExportPdfFragment");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Action share
|
// Action share
|
||||||
button = (Button) findViewById(R.id.actionSharing);
|
button = (Button) findViewById(R.id.actionSharing);
|
||||||
button.setOnClickListener(new View.OnClickListener() {
|
button.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
DialogFragment dialog = DocShareFragment.newInstance(DocumentViewActivity.this.document.optString("id"));
|
DialogFragment dialog = DocShareFragment.newInstance(document.optString("id"));
|
||||||
dialog.show(getSupportFragmentManager(), "DocShareFragment");
|
dialog.show(getSupportFragmentManager(), "DocShareFragment");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Action audit log
|
||||||
|
button = (Button) findViewById(R.id.actionAuditLog);
|
||||||
|
button.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
Intent intent = new Intent(DocumentViewActivity.this, AuditLogActivity.class);
|
||||||
|
intent.putExtra("documentId", document.optString("id"));
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Button add a comment
|
||||||
|
ImageButton imageButton = (ImageButton) findViewById(R.id.addCommentBtn);
|
||||||
|
imageButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View view) {
|
||||||
|
final EditText commentEditText = (EditText) findViewById(R.id.commentEditText);
|
||||||
|
if (commentEditText.getText().length() == 0) {
|
||||||
|
// No content for the new comment
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.makeText(DocumentViewActivity.this, R.string.adding_comment, Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
|
CommentResource.add(DocumentViewActivity.this,
|
||||||
|
DocumentViewActivity.this.document.optString("id"),
|
||||||
|
commentEditText.getText().toString(),
|
||||||
|
new HttpCallback() {
|
||||||
|
public void onSuccess(JSONObject response) {
|
||||||
|
EventBus.getDefault().post(new CommentAddEvent(response));
|
||||||
|
commentEditText.setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
|
Toast.makeText(DocumentViewActivity.this, R.string.comment_add_failure, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Grab the comments
|
||||||
|
updateComments();
|
||||||
|
|
||||||
// Grab the attached files
|
// Grab the attached files
|
||||||
updateFiles();
|
updateFiles();
|
||||||
|
|
||||||
// Grab the full document (used for ACLs and writable status)
|
// Grab the full document (used for ACLs, remaining metadata and writable status)
|
||||||
updateDocument();
|
updateDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,6 +336,15 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
case R.id.comments:
|
||||||
|
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||||
|
if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
|
||||||
|
drawerLayout.closeDrawer(GravityCompat.START);
|
||||||
|
} else {
|
||||||
|
drawerLayout.openDrawer(GravityCompat.START);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
case R.id.download_file:
|
case R.id.download_file:
|
||||||
downloadCurrentFile();
|
downloadCurrentFile();
|
||||||
return true;
|
return true;
|
||||||
@ -299,11 +376,11 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
int position = fileViewPager.getCurrentItem();
|
int position = fileViewPager.getCurrentItem();
|
||||||
if (mimeType == null || !mimeType.contains("/")) return;
|
if (mimeType == null || !mimeType.contains("/")) return;
|
||||||
String ext = mimeType.split("/")[1];
|
String ext = mimeType.split("/")[1];
|
||||||
String fileName = getTitle() + "-" + position + "." + ext;
|
String fileName = document.optString("title") + "-" + position + "." + ext;
|
||||||
|
|
||||||
// Download the file
|
// Download the file
|
||||||
String fileUrl = PreferenceUtil.getServerUrl(this) + "/api/file/" + file.optString("id") + "/data";
|
String fileUrl = PreferenceUtil.getServerUrl(this) + "/api/file/" + file.optString("id") + "/data";
|
||||||
downloadFile(fileUrl, fileName, getTitle().toString(), getString(R.string.downloading_file, position + 1));
|
NetworkUtil.downloadFile(this, fileUrl, fileName, document.optString("title"), getString(R.string.download_file_title));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteCurrentFile() {
|
private void deleteCurrentFile() {
|
||||||
@ -326,24 +403,18 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
// Show a progress dialog while deleting
|
// Show a progress dialog while deleting
|
||||||
final ProgressDialog progressDialog = ProgressDialog.show(DocumentViewActivity.this,
|
final ProgressDialog progressDialog = ProgressDialog.show(DocumentViewActivity.this,
|
||||||
getString(R.string.please_wait),
|
getString(R.string.please_wait),
|
||||||
getString(R.string.file_deleting_message), true, true,
|
getString(R.string.file_deleting_message), true, true);
|
||||||
new DialogInterface.OnCancelListener() {
|
|
||||||
@Override
|
|
||||||
public void onCancel(DialogInterface dialog) {
|
|
||||||
FileResource.cancel(DocumentViewActivity.this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Actual delete server call
|
// Actual delete server call
|
||||||
final String fileId = file.optString("id");
|
final String fileId = file.optString("id");
|
||||||
FileResource.delete(DocumentViewActivity.this, fileId, new JsonHttpResponseHandler() {
|
FileResource.delete(DocumentViewActivity.this, fileId, new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
EventBus.getDefault().post(new FileDeleteEvent(fileId));
|
EventBus.getDefault().post(new FileDeleteEvent(fileId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
Toast.makeText(DocumentViewActivity.this, R.string.file_delete_failure, Toast.LENGTH_LONG).show();
|
Toast.makeText(DocumentViewActivity.this, R.string.file_delete_failure, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,28 +439,8 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
private void downloadZip() {
|
private void downloadZip() {
|
||||||
if (document == null) return;
|
if (document == null) return;
|
||||||
String url = PreferenceUtil.getServerUrl(this) + "/api/file/zip?id=" + document.optString("id");
|
String url = PreferenceUtil.getServerUrl(this) + "/api/file/zip?id=" + document.optString("id");
|
||||||
String fileName = getTitle() + ".zip";
|
String fileName = document.optString("title") + ".zip";
|
||||||
downloadFile(url, fileName, getTitle().toString(), getString(R.string.downloading_document));
|
NetworkUtil.downloadFile(this, url, fileName, document.optString("title"), getString(R.string.download_document_title));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Download a file using Android download manager.
|
|
||||||
*
|
|
||||||
* @param url URL to download
|
|
||||||
* @param fileName Destination file name
|
|
||||||
* @param title Notification title
|
|
||||||
* @param description Notification description
|
|
||||||
*/
|
|
||||||
private void downloadFile(String url, String fileName, String title, String description) {
|
|
||||||
String authToken = PreferenceUtil.getAuthToken(this);
|
|
||||||
DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
|
|
||||||
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
|
||||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
|
||||||
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
|
|
||||||
request.addRequestHeader("Cookie", "auth_token=" + authToken);
|
|
||||||
request.setTitle(title);
|
|
||||||
request.setDescription(description);
|
|
||||||
downloadManager.enqueue(request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -411,24 +462,18 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
// Show a progress dialog while deleting
|
// Show a progress dialog while deleting
|
||||||
final ProgressDialog progressDialog = ProgressDialog.show(DocumentViewActivity.this,
|
final ProgressDialog progressDialog = ProgressDialog.show(DocumentViewActivity.this,
|
||||||
getString(R.string.please_wait),
|
getString(R.string.please_wait),
|
||||||
getString(R.string.document_deleting_message), true, true,
|
getString(R.string.document_deleting_message), true, true);
|
||||||
new DialogInterface.OnCancelListener() {
|
|
||||||
@Override
|
|
||||||
public void onCancel(DialogInterface dialog) {
|
|
||||||
DocumentResource.cancel(DocumentViewActivity.this);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Actual delete server call
|
// Actual delete server call
|
||||||
final String documentId = document.optString("id");
|
final String documentId = document.optString("id");
|
||||||
DocumentResource.delete(DocumentViewActivity.this, documentId, new JsonHttpResponseHandler() {
|
DocumentResource.delete(DocumentViewActivity.this, documentId, new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
EventBus.getDefault().post(new DocumentDeleteEvent(documentId));
|
EventBus.getDefault().post(new DocumentDeleteEvent(documentId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
Toast.makeText(DocumentViewActivity.this, R.string.document_delete_failure, Toast.LENGTH_LONG).show();
|
Toast.makeText(DocumentViewActivity.this, R.string.document_delete_failure, Toast.LENGTH_LONG).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,6 +498,7 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
*
|
*
|
||||||
* @param event Document fullscreen event
|
* @param event Document fullscreen event
|
||||||
*/
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(DocumentFullscreenEvent event) {
|
public void onEventMainThread(DocumentFullscreenEvent event) {
|
||||||
findViewById(R.id.detailLayout).setVisibility(event.isFullscreen() ? View.GONE : View.VISIBLE);
|
findViewById(R.id.detailLayout).setVisibility(event.isFullscreen() ? View.GONE : View.VISIBLE);
|
||||||
}
|
}
|
||||||
@ -462,6 +508,7 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
*
|
*
|
||||||
* @param event Document edit event
|
* @param event Document edit event
|
||||||
*/
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(DocumentEditEvent event) {
|
public void onEventMainThread(DocumentEditEvent event) {
|
||||||
if (document == null) return;
|
if (document == null) return;
|
||||||
if (event.getDocument().optString("id").equals(document.optString("id"))) {
|
if (event.getDocument().optString("id").equals(document.optString("id"))) {
|
||||||
@ -475,6 +522,7 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
*
|
*
|
||||||
* @param event Document delete event
|
* @param event Document delete event
|
||||||
*/
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(DocumentDeleteEvent event) {
|
public void onEventMainThread(DocumentDeleteEvent event) {
|
||||||
if (document == null) return;
|
if (document == null) return;
|
||||||
if (event.getDocumentId().equals(document.optString("id"))) {
|
if (event.getDocumentId().equals(document.optString("id"))) {
|
||||||
@ -488,6 +536,7 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
*
|
*
|
||||||
* @param event File delete event
|
* @param event File delete event
|
||||||
*/
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(FileDeleteEvent event) {
|
public void onEventMainThread(FileDeleteEvent event) {
|
||||||
if (filePagerAdapter == null) return;
|
if (filePagerAdapter == null) return;
|
||||||
filePagerAdapter.remove(event.getFileId());
|
filePagerAdapter.remove(event.getFileId());
|
||||||
@ -500,6 +549,7 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
*
|
*
|
||||||
* @param event File add event
|
* @param event File add event
|
||||||
*/
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(FileAddEvent event) {
|
public void onEventMainThread(FileAddEvent event) {
|
||||||
if (document == null) return;
|
if (document == null) return;
|
||||||
if (document.optString("id").equals(event.getDocumentId())) {
|
if (document.optString("id").equals(event.getDocumentId())) {
|
||||||
@ -507,6 +557,38 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A comment add event has been fired.
|
||||||
|
*
|
||||||
|
* @param event Comment add event
|
||||||
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
public void onEventMainThread(CommentAddEvent event) {
|
||||||
|
if (commentListAdapter == null) return;
|
||||||
|
TextView emptyView = (TextView) findViewById(R.id.commentEmptyView);
|
||||||
|
ListView listView = (ListView) findViewById(R.id.commentListView);
|
||||||
|
emptyView.setVisibility(View.GONE);
|
||||||
|
listView.setVisibility(View.VISIBLE);
|
||||||
|
commentListAdapter.add(event.getComment());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A comment delete event has been fired.
|
||||||
|
*
|
||||||
|
* @param event Comment add event
|
||||||
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
public void onEventMainThread(CommentDeleteEvent event) {
|
||||||
|
if (commentListAdapter == null) return;
|
||||||
|
TextView emptyView = (TextView) findViewById(R.id.commentEmptyView);
|
||||||
|
ListView listView = (ListView) findViewById(R.id.commentListView);
|
||||||
|
commentListAdapter.remove(event.getCommentId());
|
||||||
|
if (commentListAdapter.getCount() == 0) {
|
||||||
|
emptyView.setVisibility(View.VISIBLE);
|
||||||
|
listView.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
if (document == null) return;
|
if (document == null) return;
|
||||||
@ -550,9 +632,9 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
// Silently get the document to know if it is writable by the current user
|
// Silently get the document to know if it is writable by the current user
|
||||||
// If this call fails or is slow and the document is read-only,
|
// If this call fails or is slow and the document is read-only,
|
||||||
// write actions will be allowed and will fail
|
// write actions will be allowed and will fail
|
||||||
DocumentResource.get(this, document.optString("id"), new JsonHttpResponseHandler() {
|
DocumentResource.get(this, document.optString("id"), new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
document = response;
|
document = response;
|
||||||
boolean writable = document.optBoolean("writable");
|
boolean writable = document.optBoolean("writable");
|
||||||
|
|
||||||
@ -560,14 +642,171 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
menu.findItem(R.id.delete_file).setVisible(writable);
|
menu.findItem(R.id.delete_file).setVisible(writable);
|
||||||
}
|
}
|
||||||
|
|
||||||
findViewById(R.id.actionEditDocument).setVisibility(writable ? View.VISIBLE : View.INVISIBLE);
|
// Action only available if the document is writable
|
||||||
findViewById(R.id.actionUploadFile).setVisibility(writable ? View.VISIBLE : View.INVISIBLE);
|
findViewById(R.id.actionEditDocument).setVisibility(writable ? View.VISIBLE : View.GONE);
|
||||||
findViewById(R.id.actionSharing).setVisibility(writable ? View.VISIBLE : View.INVISIBLE);
|
findViewById(R.id.actionUploadFile).setVisibility(writable ? View.VISIBLE : View.GONE);
|
||||||
findViewById(R.id.actionDelete).setVisibility(writable ? View.VISIBLE : View.INVISIBLE);
|
findViewById(R.id.actionSharing).setVisibility(writable ? View.VISIBLE : View.GONE);
|
||||||
|
findViewById(R.id.actionDelete).setVisibility(writable ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
// ACLs
|
// ACLs
|
||||||
ListView aclListView = (ListView) findViewById(R.id.aclListView);
|
ListView aclListView = (ListView) findViewById(R.id.aclListView);
|
||||||
aclListView.setAdapter(new AclListAdapter(document.optJSONArray("acls")));
|
final AclListAdapter aclListAdapter = new AclListAdapter(document.optJSONArray("acls"));
|
||||||
|
aclListView.setAdapter(aclListAdapter);
|
||||||
|
aclListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
AclListAdapter.AclItem acl = aclListAdapter.getItem(position);
|
||||||
|
if (acl.getType().equals("USER")) {
|
||||||
|
Intent intent = new Intent(DocumentViewActivity.this, UserProfileActivity.class);
|
||||||
|
intent.putExtra("username", acl.getName());
|
||||||
|
startActivity(intent);
|
||||||
|
} else if (acl.getType().equals("GROUP")) {
|
||||||
|
Intent intent = new Intent(DocumentViewActivity.this, GroupProfileActivity.class);
|
||||||
|
intent.putExtra("name", acl.getName());
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remaining metadata
|
||||||
|
TextView creatorTextView = (TextView) findViewById(R.id.creatorTextView);
|
||||||
|
final String creator = document.optString("creator");
|
||||||
|
creatorTextView.setText(creator);
|
||||||
|
creatorTextView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent intent = new Intent(DocumentViewActivity.this, UserProfileActivity.class);
|
||||||
|
intent.putExtra("username", creator);
|
||||||
|
startActivity(intent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Contributors
|
||||||
|
TextView contributorsTextView = (TextView) findViewById(R.id.contributorsTextView);
|
||||||
|
contributorsTextView.setText(SpannableUtil.buildSpannableContributors(document.optJSONArray("contributors")));
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
JSONArray relations = document.optJSONArray("relations");
|
||||||
|
if (relations.length() > 0) {
|
||||||
|
TextView relationsTextView = (TextView) findViewById(R.id.relationsTextView);
|
||||||
|
relationsTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
relationsTextView.setText(SpannableUtil.buildSpannableRelations(relations));
|
||||||
|
} else {
|
||||||
|
findViewById(R.id.relationsLayout).setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Additional dublincore metadata
|
||||||
|
displayDublincoreMetadata(R.id.subjectTextView, R.id.subjectLayout, "subject");
|
||||||
|
displayDublincoreMetadata(R.id.identifierTextView, R.id.identifierLayout, "identifier");
|
||||||
|
displayDublincoreMetadata(R.id.publisherTextView, R.id.publisherLayout, "publisher");
|
||||||
|
displayDublincoreMetadata(R.id.formatTextView, R.id.formatLayout, "format");
|
||||||
|
displayDublincoreMetadata(R.id.sourceTextView, R.id.sourceLayout, "source");
|
||||||
|
displayDublincoreMetadata(R.id.typeTextView, R.id.typeLayout, "type");
|
||||||
|
displayDublincoreMetadata(R.id.coverageTextView, R.id.coverageLayout, "coverage");
|
||||||
|
displayDublincoreMetadata(R.id.rightsTextView, R.id.rightsLayout, "rights");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display a dublincore metadata.
|
||||||
|
*
|
||||||
|
* @param textViewId TextView ID
|
||||||
|
* @param blockViewId View ID
|
||||||
|
* @param name Name
|
||||||
|
*/
|
||||||
|
private void displayDublincoreMetadata(int textViewId, int blockViewId, String name) {
|
||||||
|
if (document == null) return;
|
||||||
|
String value = document.optString(name);
|
||||||
|
if (document.isNull(name) || value.isEmpty()) {
|
||||||
|
findViewById(blockViewId).setVisibility(View.GONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
findViewById(blockViewId).setVisibility(View.VISIBLE);
|
||||||
|
TextView textView = (TextView) findViewById(textViewId);
|
||||||
|
textView.setText(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
|
||||||
|
switch (view.getId()) {
|
||||||
|
case R.id.commentListView:
|
||||||
|
if (commentListAdapter == null || document == null) return;
|
||||||
|
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
|
||||||
|
JSONObject comment = commentListAdapter.getItem(info.position);
|
||||||
|
boolean writable = document.optBoolean("writable");
|
||||||
|
String creator = comment.optString("creator");
|
||||||
|
String username = ApplicationContext.getInstance().getUserInfo().optString("username");
|
||||||
|
if (writable || creator.equals(username)) {
|
||||||
|
menu.add(Menu.NONE, 0, 0, getString(R.string.comment_delete));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onContextItemSelected(MenuItem item) {
|
||||||
|
// Use real ids if more than one item someday
|
||||||
|
if (item.getItemId() == 0) {
|
||||||
|
// Delete a comment
|
||||||
|
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
|
||||||
|
if (commentListAdapter == null) return false;
|
||||||
|
JSONObject comment = commentListAdapter.getItem(info.position);
|
||||||
|
final String commentId = comment.optString("id");
|
||||||
|
Toast.makeText(DocumentViewActivity.this, R.string.deleting_comment, Toast.LENGTH_LONG).show();
|
||||||
|
|
||||||
|
CommentResource.remove(DocumentViewActivity.this, commentId, new HttpCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(JSONObject response) {
|
||||||
|
EventBus.getDefault().post(new CommentDeleteEvent(commentId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
|
Toast.makeText(DocumentViewActivity.this, R.string.error_deleting_comment, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh comments list.
|
||||||
|
*/
|
||||||
|
private void updateComments() {
|
||||||
|
if (document == null) return;
|
||||||
|
|
||||||
|
final View progressBar = findViewById(R.id.commentProgressView);
|
||||||
|
final TextView emptyView = (TextView) findViewById(R.id.commentEmptyView);
|
||||||
|
final ListView listView = (ListView) findViewById(R.id.commentListView);
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
emptyView.setVisibility(View.GONE);
|
||||||
|
listView.setVisibility(View.GONE);
|
||||||
|
registerForContextMenu(listView);
|
||||||
|
|
||||||
|
CommentResource.list(this, document.optString("id"), new HttpCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(JSONObject response) {
|
||||||
|
JSONArray comments = response.optJSONArray("comments");
|
||||||
|
commentListAdapter = new CommentListAdapter(DocumentViewActivity.this, comments);
|
||||||
|
listView.setAdapter(commentListAdapter);
|
||||||
|
listView.setVisibility(View.VISIBLE);
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
if (comments.length() == 0) {
|
||||||
|
listView.setVisibility(View.GONE);
|
||||||
|
emptyView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
|
emptyView.setText(R.string.error_loading_comments);
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
listView.setVisibility(View.GONE);
|
||||||
|
emptyView.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -586,9 +825,9 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
progressBar.setVisibility(View.VISIBLE);
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
filesEmptyView.setVisibility(View.GONE);
|
filesEmptyView.setVisibility(View.GONE);
|
||||||
|
|
||||||
FileResource.list(this, document.optString("id"), new JsonHttpResponseHandler() {
|
FileResource.list(this, document.optString("id"), new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
JSONArray files = response.optJSONArray("files");
|
JSONArray files = response.optJSONArray("files");
|
||||||
filePagerAdapter = new FilePagerAdapter(DocumentViewActivity.this, files);
|
filePagerAdapter = new FilePagerAdapter(DocumentViewActivity.this, files);
|
||||||
fileViewPager.setAdapter(filePagerAdapter);
|
fileViewPager.setAdapter(filePagerAdapter);
|
||||||
@ -598,7 +837,7 @@ public class DocumentViewActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
filesEmptyView.setText(R.string.error_loading_files);
|
filesEmptyView.setText(R.string.error_loading_files);
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
filesEmptyView.setVisibility(View.VISIBLE);
|
filesEmptyView.setVisibility(View.VISIBLE);
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
package com.sismics.docs.activity;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.sismics.docs.R;
|
||||||
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
|
import com.sismics.docs.model.application.ApplicationContext;
|
||||||
|
import com.sismics.docs.resource.UserResource;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Group profile activity.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class GroupProfileActivity extends AppCompatActivity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// Check if logged in
|
||||||
|
if (!ApplicationContext.getInstance().isLoggedIn()) {
|
||||||
|
startActivity(new Intent(this, LoginActivity.class));
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle activity context
|
||||||
|
if (getIntent() == null) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input name
|
||||||
|
final String name = getIntent().getStringExtra("name");
|
||||||
|
if (name == null) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the activity
|
||||||
|
setTitle(name);
|
||||||
|
setContentView(R.layout.groupprofile_activity);
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
getSupportActionBar().setHomeButtonEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the group and populate the view
|
||||||
|
final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
|
||||||
|
final View layoutView = findViewById(R.id.layout);
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
layoutView.setVisibility(View.GONE);
|
||||||
|
UserResource.get(this, name, new HttpCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(JSONObject json) {
|
||||||
|
TextView membersTextView = (TextView) findViewById(R.id.membersTextView);
|
||||||
|
JSONArray members = json.optJSONArray("members");
|
||||||
|
String output = "";
|
||||||
|
for (int i = 0; i < members.length(); i++) {
|
||||||
|
output += members.optString(i) + "; ";
|
||||||
|
}
|
||||||
|
membersTextView.setText(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
layoutView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
@ -10,11 +10,11 @@ import android.view.View;
|
|||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.androidquery.AQuery;
|
|
||||||
import com.sismics.docs.R;
|
import com.sismics.docs.R;
|
||||||
import com.sismics.docs.listener.CallbackListener;
|
import com.sismics.docs.listener.CallbackListener;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.model.application.ApplicationContext;
|
import com.sismics.docs.model.application.ApplicationContext;
|
||||||
import com.sismics.docs.resource.UserResource;
|
import com.sismics.docs.resource.UserResource;
|
||||||
import com.sismics.docs.ui.form.Validator;
|
import com.sismics.docs.ui.form.Validator;
|
||||||
@ -22,7 +22,6 @@ import com.sismics.docs.ui.form.validator.Required;
|
|||||||
import com.sismics.docs.util.DialogUtil;
|
import com.sismics.docs.util.DialogUtil;
|
||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,7 +30,6 @@ import org.json.JSONObject;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
public class LoginActivity extends AppCompatActivity {
|
public class LoginActivity extends AppCompatActivity {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User interface.
|
* User interface.
|
||||||
*/
|
*/
|
||||||
@ -43,18 +41,17 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.login_activity);
|
setContentView(R.layout.login_activity);
|
||||||
|
|
||||||
AQuery aq = new AQuery(this);
|
TextView loginExplainTextView = (TextView) findViewById(R.id.loginExplain);
|
||||||
aq.id(R.id.loginExplain)
|
loginExplainTextView.setText(Html.fromHtml(getString(R.string.login_explain)));
|
||||||
.text(Html.fromHtml(getString(R.string.login_explain)))
|
loginExplainTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
.getTextView()
|
|
||||||
.setMovementMethod(LinkMovementMethod.getInstance());
|
|
||||||
|
|
||||||
final EditText txtServer = aq.id(R.id.txtServer).getEditText();
|
final EditText txtServer = (EditText) findViewById(R.id.txtServer);
|
||||||
final EditText txtUsername = aq.id(R.id.txtUsername).getEditText();
|
final EditText txtUsername = (EditText) findViewById(R.id.txtUsername);
|
||||||
final EditText txtPassword = aq.id(R.id.txtPassword).getEditText();
|
final EditText txtPassword = (EditText) findViewById(R.id.txtPassword);
|
||||||
final Button btnConnect = aq.id(R.id.btnConnect).getButton();
|
final EditText txtValidationCode = (EditText) findViewById(R.id.txtValidationCode);
|
||||||
loginForm = aq.id(R.id.loginForm).getView();
|
final Button btnConnect = (Button) findViewById(R.id.btnConnect);
|
||||||
progressBar = aq.id(R.id.progressBar).getView();
|
loginForm = findViewById(R.id.loginForm);
|
||||||
|
progressBar = findViewById(R.id.progressBar);
|
||||||
|
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
|
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
|
||||||
|
|
||||||
@ -91,9 +88,11 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
PreferenceUtil.setServerUrl(LoginActivity.this, txtServer.getText().toString());
|
PreferenceUtil.setServerUrl(LoginActivity.this, txtServer.getText().toString());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
UserResource.login(getApplicationContext(), txtUsername.getText().toString(), txtPassword.getText().toString(), new JsonHttpResponseHandler() {
|
UserResource.login(getApplicationContext(), txtUsername.getText().toString(),
|
||||||
|
txtPassword.getText().toString(), txtValidationCode.getText().toString(),
|
||||||
|
new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject json) {
|
public void onSuccess(JSONObject json) {
|
||||||
// Empty previous user caches
|
// Empty previous user caches
|
||||||
PreferenceUtil.resetUserCache(getApplicationContext());
|
PreferenceUtil.resetUserCache(getApplicationContext());
|
||||||
|
|
||||||
@ -109,12 +108,16 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
loginForm.setVisibility(View.VISIBLE);
|
loginForm.setVisibility(View.VISIBLE);
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
|
|
||||||
if (responseBytes != null && new String(responseBytes).contains("\"ForbiddenError\"")) {
|
if (json != null && json.optString("type").equals("ForbiddenError")) {
|
||||||
DialogUtil.showOkDialog(LoginActivity.this, R.string.login_fail_title, R.string.login_fail);
|
DialogUtil.showOkDialog(LoginActivity.this, R.string.login_fail_title, R.string.login_fail);
|
||||||
|
} else if (json != null && json.optString("type").equals("ValidationCodeRequired")) {
|
||||||
|
txtValidationCode.setVisibility(View.VISIBLE);
|
||||||
|
validator.addValidable(txtValidationCode, new Required());
|
||||||
|
validator.validate();
|
||||||
} else {
|
} else {
|
||||||
DialogUtil.showOkDialog(LoginActivity.this, R.string.network_error_title, R.string.network_error);
|
DialogUtil.showOkDialog(LoginActivity.this, R.string.network_error_title, R.string.network_error);
|
||||||
}
|
}
|
||||||
@ -151,9 +154,9 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
finish();
|
finish();
|
||||||
} else {
|
} else {
|
||||||
// Trying to get user data
|
// Trying to get user data
|
||||||
UserResource.info(getApplicationContext(), new JsonHttpResponseHandler() {
|
UserResource.info(getApplicationContext(), new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, final JSONObject json) {
|
public void onSuccess(final JSONObject json) {
|
||||||
if (json.optBoolean("anonymous", true)) {
|
if (json.optBoolean("anonymous", true)) {
|
||||||
loginForm.setVisibility(View.VISIBLE);
|
loginForm.setVisibility(View.VISIBLE);
|
||||||
return;
|
return;
|
||||||
@ -169,7 +172,7 @@ public class LoginActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
DialogUtil.showOkDialog(LoginActivity.this, R.string.network_error_title, R.string.network_error);
|
DialogUtil.showOkDialog(LoginActivity.this, R.string.network_error_title, R.string.network_error);
|
||||||
loginForm.setVisibility(View.VISIBLE);
|
loginForm.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
|
@ -9,33 +9,34 @@ import android.provider.SearchRecentSuggestions;
|
|||||||
import android.support.v4.widget.DrawerLayout;
|
import android.support.v4.widget.DrawerLayout;
|
||||||
import android.support.v7.app.ActionBarDrawerToggle;
|
import android.support.v7.app.ActionBarDrawerToggle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
|
import android.widget.ImageButton;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
import android.widget.SearchView;
|
import android.widget.SearchView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.androidquery.util.AQUtility;
|
|
||||||
import com.sismics.docs.R;
|
import com.sismics.docs.R;
|
||||||
import com.sismics.docs.adapter.TagListAdapter;
|
import com.sismics.docs.adapter.TagListAdapter;
|
||||||
import com.sismics.docs.event.AdvancedSearchEvent;
|
import com.sismics.docs.event.AdvancedSearchEvent;
|
||||||
import com.sismics.docs.event.SearchEvent;
|
import com.sismics.docs.event.SearchEvent;
|
||||||
import com.sismics.docs.fragment.SearchFragment;
|
import com.sismics.docs.fragment.SearchFragment;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.model.application.ApplicationContext;
|
import com.sismics.docs.model.application.ApplicationContext;
|
||||||
import com.sismics.docs.provider.RecentSuggestionsProvider;
|
import com.sismics.docs.provider.RecentSuggestionsProvider;
|
||||||
import com.sismics.docs.resource.TagResource;
|
import com.sismics.docs.resource.TagResource;
|
||||||
import com.sismics.docs.resource.UserResource;
|
import com.sismics.docs.resource.UserResource;
|
||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main activity.
|
* Main activity.
|
||||||
*
|
*
|
||||||
@ -43,7 +44,6 @@ import de.greenrobot.event.EventBus;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity {
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
|
||||||
private ActionBarDrawerToggle drawerToggle;
|
private ActionBarDrawerToggle drawerToggle;
|
||||||
private MenuItem searchItem;
|
private MenuItem searchItem;
|
||||||
private DrawerLayout drawerLayout;
|
private DrawerLayout drawerLayout;
|
||||||
@ -63,7 +63,10 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
setContentView(R.layout.main_activity);
|
setContentView(R.layout.main_activity);
|
||||||
|
|
||||||
// Enable ActionBar app icon to behave as action to toggle nav drawer
|
// Enable ActionBar app icon to behave as action to toggle nav drawer
|
||||||
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
|
drawerLayout = findViewById(R.id.drawer_layout);
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
toolbar.setTitleTextColor(getResources().getColor(android.R.color.white));
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
if (getSupportActionBar() != null) {
|
if (getSupportActionBar() != null) {
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
getSupportActionBar().setHomeButtonEnabled(true);
|
getSupportActionBar().setHomeButtonEnabled(true);
|
||||||
@ -73,35 +76,35 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
// between the sliding drawer and the action bar app icon
|
// between the sliding drawer and the action bar app icon
|
||||||
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
|
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout,
|
||||||
R.string.drawer_open, R.string.drawer_close);
|
R.string.drawer_open, R.string.drawer_close);
|
||||||
drawerLayout.setDrawerListener(drawerToggle);
|
drawerLayout.addDrawerListener(drawerToggle);
|
||||||
|
|
||||||
// Fill the drawer user info
|
// Fill the drawer user info
|
||||||
JSONObject userInfo = ApplicationContext.getInstance().getUserInfo();
|
JSONObject userInfo = ApplicationContext.getInstance().getUserInfo();
|
||||||
TextView usernameTextView = (TextView) findViewById(R.id.usernameTextView);
|
TextView usernameTextView = findViewById(R.id.usernameTextView);
|
||||||
usernameTextView.setText(userInfo.optString("username"));
|
usernameTextView.setText(userInfo.optString("username"));
|
||||||
TextView emailTextView = (TextView) findViewById(R.id.emailTextView);
|
TextView emailTextView = findViewById(R.id.emailTextView);
|
||||||
emailTextView.setText(userInfo.optString("email"));
|
emailTextView.setText(userInfo.optString("email"));
|
||||||
|
|
||||||
// Get tag list to fill the drawer
|
// Get tag list to fill the drawer
|
||||||
final ListView tagListView = (ListView) findViewById(R.id.tagListView);
|
final ListView tagListView = findViewById(R.id.tagListView);
|
||||||
final View tagProgressView = findViewById(R.id.tagProgressView);
|
final View tagProgressView = findViewById(R.id.tagProgressView);
|
||||||
final TextView tagEmptyView = (TextView) findViewById(R.id.tagEmptyView);
|
final TextView tagEmptyView = findViewById(R.id.tagEmptyView);
|
||||||
tagListView.setEmptyView(tagProgressView);
|
tagListView.setEmptyView(tagProgressView);
|
||||||
JSONObject cacheTags = PreferenceUtil.getCachedJson(this, PreferenceUtil.PREF_CACHED_TAGS_JSON);
|
JSONObject cacheTags = PreferenceUtil.getCachedJson(this, PreferenceUtil.PREF_CACHED_TAGS_JSON);
|
||||||
if (cacheTags != null) {
|
if (cacheTags != null) {
|
||||||
tagListView.setAdapter(new TagListAdapter(cacheTags.optJSONArray("stats")));
|
tagListView.setAdapter(new TagListAdapter(cacheTags.optJSONArray("tags")));
|
||||||
}
|
}
|
||||||
TagResource.stats(this, new JsonHttpResponseHandler() {
|
TagResource.list(this, new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
PreferenceUtil.setCachedJson(MainActivity.this, PreferenceUtil.PREF_CACHED_TAGS_JSON, response);
|
PreferenceUtil.setCachedJson(MainActivity.this, PreferenceUtil.PREF_CACHED_TAGS_JSON, response);
|
||||||
tagListView.setAdapter(new TagListAdapter(response.optJSONArray("stats")));
|
tagListView.setAdapter(new TagListAdapter(response.optJSONArray("tags")));
|
||||||
tagProgressView.setVisibility(View.GONE);
|
tagProgressView.setVisibility(View.GONE);
|
||||||
tagListView.setEmptyView(tagEmptyView);
|
tagListView.setEmptyView(tagEmptyView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
tagEmptyView.setText(R.string.error_loading_tags);
|
tagEmptyView.setText(R.string.error_loading_tags);
|
||||||
tagProgressView.setVisibility(View.GONE);
|
tagProgressView.setVisibility(View.GONE);
|
||||||
tagListView.setEmptyView(tagEmptyView);
|
tagListView.setEmptyView(tagEmptyView);
|
||||||
@ -114,9 +117,9 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||||
TagListAdapter adapter = (TagListAdapter) tagListView.getAdapter();
|
TagListAdapter adapter = (TagListAdapter) tagListView.getAdapter();
|
||||||
if (adapter == null) return;
|
if (adapter == null) return;
|
||||||
JSONObject tag = adapter.getItem(position);
|
TagListAdapter.TagItem tagItem = adapter.getItem(position);
|
||||||
if (tag == null) return;
|
if (tagItem == null) return;
|
||||||
searchQuery("tag:" + tag.optString("name"));
|
searchQuery("tag:" + tagItem.getName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -138,6 +141,24 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Click on Latest activity
|
||||||
|
View auditLogLayout = findViewById(R.id.auditLogLayout);
|
||||||
|
auditLogLayout.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
startActivity(new Intent(MainActivity.this, AuditLogActivity.class));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add document button
|
||||||
|
ImageButton addDocumentButton = findViewById(R.id.addDocumentButton);
|
||||||
|
addDocumentButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
startActivity(new Intent(MainActivity.this, DocumentEditActivity.class));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
handleIntent(getIntent());
|
handleIntent(getIntent());
|
||||||
|
|
||||||
EventBus.getDefault().register(this);
|
EventBus.getDefault().register(this);
|
||||||
@ -147,10 +168,11 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.logout:
|
case R.id.logout:
|
||||||
UserResource.logout(getApplicationContext(), new JsonHttpResponseHandler() {
|
UserResource.logout(getApplicationContext(), new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onFinish() {
|
public void onFinish() {
|
||||||
// Force logout in all cases, so the user is not stuck in case of network error
|
// Force logout in all cases, so the user is not stuck in case of network error
|
||||||
|
PreferenceUtil.clearAuthToken(MainActivity.this);
|
||||||
ApplicationContext.getInstance().setUserInfo(getApplicationContext(), null);
|
ApplicationContext.getInstance().setUserInfo(getApplicationContext(), null);
|
||||||
startActivity(new Intent(MainActivity.this, LoginActivity.class));
|
startActivity(new Intent(MainActivity.this, LoginActivity.class));
|
||||||
finish();
|
finish();
|
||||||
@ -267,6 +289,7 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
*
|
*
|
||||||
* @param event Advanced search event
|
* @param event Advanced search event
|
||||||
*/
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(AdvancedSearchEvent event) {
|
public void onEventMainThread(AdvancedSearchEvent event) {
|
||||||
searchQuery(event.getQuery());
|
searchQuery(event.getQuery());
|
||||||
}
|
}
|
||||||
@ -274,10 +297,6 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
EventBus.getDefault().unregister(this);
|
EventBus.getDefault().unregister(this);
|
||||||
if(isTaskRoot()) {
|
|
||||||
int cacheSizeMb = PreferenceUtil.getIntegerPreference(this, PreferenceUtil.PREF_CACHE_SIZE, 10);
|
|
||||||
AQUtility.cleanCacheAsync(this, cacheSizeMb * 1000000, cacheSizeMb * 1000000);
|
|
||||||
}
|
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -12,7 +12,6 @@ import com.sismics.docs.fragment.SettingsFragment;
|
|||||||
* @author bgamard.
|
* @author bgamard.
|
||||||
*/
|
*/
|
||||||
public class SettingsActivity extends AppCompatActivity {
|
public class SettingsActivity extends AppCompatActivity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
@ -0,0 +1,91 @@
|
|||||||
|
package com.sismics.docs.activity;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.sismics.docs.R;
|
||||||
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
|
import com.sismics.docs.model.application.ApplicationContext;
|
||||||
|
import com.sismics.docs.resource.UserResource;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User profile activity.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class UserProfileActivity extends AppCompatActivity {
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// Check if logged in
|
||||||
|
if (!ApplicationContext.getInstance().isLoggedIn()) {
|
||||||
|
startActivity(new Intent(this, LoginActivity.class));
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle activity context
|
||||||
|
if (getIntent() == null) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Input username
|
||||||
|
final String username = getIntent().getStringExtra("username");
|
||||||
|
if (username == null) {
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the activity
|
||||||
|
setTitle(username);
|
||||||
|
setContentView(R.layout.userprofile_activity);
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
getSupportActionBar().setHomeButtonEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the user and populate the view
|
||||||
|
final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
|
||||||
|
final View layoutView = findViewById(R.id.layout);
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
layoutView.setVisibility(View.GONE);
|
||||||
|
UserResource.get(this, username, new HttpCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(JSONObject json) {
|
||||||
|
TextView emailTextView = (TextView) findViewById(R.id.emailTextView);
|
||||||
|
emailTextView.setText(json.optString("email"));
|
||||||
|
|
||||||
|
TextView quotaTextView = (TextView) findViewById(R.id.quotaTextView);
|
||||||
|
quotaTextView.setText(getString(R.string.storage_display,
|
||||||
|
Math.round(json.optLong("storage_current") / 1000000),
|
||||||
|
Math.round(json.optLong("storage_quota") / 1000000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
layoutView.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case android.R.id.home:
|
||||||
|
finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.sismics.docs.adapter;
|
package com.sismics.docs.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -24,7 +25,7 @@ public class AclListAdapter extends BaseAdapter {
|
|||||||
/**
|
/**
|
||||||
* Shares.
|
* Shares.
|
||||||
*/
|
*/
|
||||||
private List<JSONObject> acls;
|
private List<AclItem> aclItemList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ACL list adapter.
|
* ACL list adapter.
|
||||||
@ -32,28 +33,46 @@ public class AclListAdapter extends BaseAdapter {
|
|||||||
* @param acls ACLs
|
* @param acls ACLs
|
||||||
*/
|
*/
|
||||||
public AclListAdapter(JSONArray acls) {
|
public AclListAdapter(JSONArray acls) {
|
||||||
this.acls = new ArrayList<>();
|
this.aclItemList = new ArrayList<>();
|
||||||
|
|
||||||
// Extract only share ACLs
|
// Group ACLs
|
||||||
for (int i = 0; i < acls.length(); i++) {
|
for (int i = 0; i < acls.length(); i++) {
|
||||||
JSONObject acl = acls.optJSONObject(i);
|
JSONObject acl = acls.optJSONObject(i);
|
||||||
this.acls.add(acl);
|
String type = acl.optString("type");
|
||||||
|
String name = acl.optString("name");
|
||||||
|
String perm = acl.optString("perm");
|
||||||
|
|
||||||
|
boolean found = false;
|
||||||
|
for (AclItem aclItem : aclItemList) {
|
||||||
|
if (aclItem.type.equals(type) && aclItem.name.equals(name)) {
|
||||||
|
aclItem.permList.add(perm);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
AclItem aclItem = new AclItem();
|
||||||
|
aclItem.type = type;
|
||||||
|
aclItem.name = name;
|
||||||
|
aclItem.permList.add(perm);
|
||||||
|
this.aclItemList.add(aclItem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return acls.size();
|
return aclItemList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject getItem(int position) {
|
public AclItem getItem(int position) {
|
||||||
return acls.get(position);
|
return aclItemList.get(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getItemId(int position) {
|
public long getItemId(int position) {
|
||||||
return getItem(position).optString("id").hashCode();
|
return getItem(position).hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -64,14 +83,37 @@ public class AclListAdapter extends BaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fill the view
|
// Fill the view
|
||||||
final JSONObject acl = getItem(position);
|
final AclItem aclItem = getItem(position);
|
||||||
TextView typeTextView = (TextView) view.findViewById(R.id.typeTextView);
|
TextView typeTextView = (TextView) view.findViewById(R.id.typeTextView);
|
||||||
typeTextView.setText(acl.optString("type"));
|
typeTextView.setText(aclItem.type);
|
||||||
TextView nameTextView = (TextView) view.findViewById(R.id.nameTextView);
|
TextView nameTextView = (TextView) view.findViewById(R.id.nameTextView);
|
||||||
nameTextView.setText(acl.optString("name"));
|
nameTextView.setText(aclItem.name);
|
||||||
TextView permTextView = (TextView) view.findViewById(R.id.permTextView);
|
TextView permTextView = (TextView) view.findViewById(R.id.permTextView);
|
||||||
permTextView.setText(acl.optString("perm"));
|
permTextView.setText(TextUtils.join(" + ", aclItem.permList));
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An ACL item in the list.
|
||||||
|
* Permissions are grouped together.
|
||||||
|
*/
|
||||||
|
public static class AclItem {
|
||||||
|
private String type;
|
||||||
|
private String name;
|
||||||
|
private List<String> permList = new ArrayList<>();
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return (type + name).hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,113 @@
|
|||||||
|
package com.sismics.docs.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.format.DateFormat;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.sismics.docs.R;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log list adapter.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class AuditLogListAdapter extends BaseAdapter {
|
||||||
|
/**
|
||||||
|
* Shares.
|
||||||
|
*/
|
||||||
|
private List<JSONObject> logList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context.
|
||||||
|
*/
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Audit log list adapter.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @param logs Logs
|
||||||
|
*/
|
||||||
|
public AuditLogListAdapter(Context context, JSONArray logs) {
|
||||||
|
this.context = context;
|
||||||
|
this.logList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < logs.length(); i++) {
|
||||||
|
logList.add(logs.optJSONObject(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return logList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject getItem(int position) {
|
||||||
|
return logList.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return getItem(position).hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View view, final ViewGroup parent) {
|
||||||
|
if (view == null) {
|
||||||
|
LayoutInflater vi = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
view = vi.inflate(R.layout.auditlog_list_item, parent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build message
|
||||||
|
final JSONObject log = getItem(position);
|
||||||
|
StringBuilder message = new StringBuilder();
|
||||||
|
|
||||||
|
// Translate entity name
|
||||||
|
int stringId = context.getResources().getIdentifier("auditlog_" + log.optString("class"), "string", context.getPackageName());
|
||||||
|
if (stringId == 0) {
|
||||||
|
message.append(log.optString("class"));
|
||||||
|
} else {
|
||||||
|
message.append(context.getResources().getString(stringId));
|
||||||
|
}
|
||||||
|
message.append(" ");
|
||||||
|
|
||||||
|
switch (log.optString("type")) {
|
||||||
|
case "CREATE": message.append(context.getResources().getString(R.string.auditlog_created)); break;
|
||||||
|
case "UPDATE": message.append(context.getResources().getString(R.string.auditlog_updated)); break;
|
||||||
|
case "DELETE": message.append(context.getResources().getString(R.string.auditlog_deleted)); break;
|
||||||
|
}
|
||||||
|
switch (log.optString("class")) {
|
||||||
|
case "Document":
|
||||||
|
case "Acl":
|
||||||
|
case "Tag":
|
||||||
|
case "User":
|
||||||
|
case "Group":
|
||||||
|
message.append(" : ");
|
||||||
|
message.append(log.optString("message"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the view
|
||||||
|
TextView usernameTextView = view.findViewById(R.id.usernameTextView);
|
||||||
|
TextView messageTextView = view.findViewById(R.id.messageTextView);
|
||||||
|
TextView dateTextView = view.findViewById(R.id.dateTextView);
|
||||||
|
usernameTextView.setText(log.optString("username"));
|
||||||
|
messageTextView.setText(message);
|
||||||
|
String date = DateFormat.getDateFormat(parent.getContext()).format(new Date(log.optLong("create_date")));
|
||||||
|
dateTextView.setText(date);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
package com.sismics.docs.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.format.DateFormat;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.BaseAdapter;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.sismics.docs.R;
|
||||||
|
import com.sismics.docs.util.OkHttpUtil;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment list adapter.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class CommentListAdapter extends BaseAdapter {
|
||||||
|
/**
|
||||||
|
* Tags.
|
||||||
|
*/
|
||||||
|
private List<JSONObject> commentList = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context.
|
||||||
|
*/
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment list adapter.
|
||||||
|
*
|
||||||
|
* @param commentsArray Comments
|
||||||
|
*/
|
||||||
|
public CommentListAdapter(Context context, JSONArray commentsArray) {
|
||||||
|
this.context = context;
|
||||||
|
for (int i = 0; i < commentsArray.length(); i++) {
|
||||||
|
commentList.add(commentsArray.optJSONObject(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return commentList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject getItem(int position) {
|
||||||
|
return commentList.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
return getItem(position).optString("id").hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View getView(int position, View view, ViewGroup parent) {
|
||||||
|
if (view == null) {
|
||||||
|
LayoutInflater vi = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||||
|
view = vi.inflate(R.layout.comment_list_item, parent, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill the view
|
||||||
|
JSONObject comment = getItem(position);
|
||||||
|
TextView creatorTextView = (TextView) view.findViewById(R.id.creatorTextView);
|
||||||
|
TextView dateTextView = (TextView) view.findViewById(R.id.dateTextView);
|
||||||
|
TextView contentTextView = (TextView) view.findViewById(R.id.contentTextView);
|
||||||
|
ImageView gravatarImageView = (ImageView) view.findViewById(R.id.gravatarImageView);
|
||||||
|
creatorTextView.setText(comment.optString("creator"));
|
||||||
|
dateTextView.setText(DateFormat.getDateFormat(dateTextView.getContext()).format(new Date(comment.optLong("create_date"))));
|
||||||
|
contentTextView.setText(comment.optString("content"));
|
||||||
|
|
||||||
|
// Gravatar image
|
||||||
|
String gravatarUrl = "http://www.gravatar.com/avatar/" + comment.optString("creator_gravatar") + "?s=128d=identicon";
|
||||||
|
OkHttpUtil.picasso(context)
|
||||||
|
.load(gravatarUrl)
|
||||||
|
.into(gravatarImageView);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new comment.
|
||||||
|
*
|
||||||
|
* @param comment Comment
|
||||||
|
*/
|
||||||
|
public void add(JSONObject comment) {
|
||||||
|
commentList.add(comment);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a comment.
|
||||||
|
*
|
||||||
|
* @param commentId Comment ID
|
||||||
|
*/
|
||||||
|
public void remove(String commentId) {
|
||||||
|
for (JSONObject comment : commentList) {
|
||||||
|
if (comment.optString("id").equals(commentId)) {
|
||||||
|
commentList.remove(comment);
|
||||||
|
notifyDataSetChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,7 +9,7 @@ import android.widget.ImageView;
|
|||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.sismics.docs.R;
|
import com.sismics.docs.R;
|
||||||
import com.sismics.docs.util.TagUtil;
|
import com.sismics.docs.util.SpannableUtil;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -69,7 +69,7 @@ public class DocListAdapter extends RecyclerView.Adapter<DocListAdapter.ViewHold
|
|||||||
holder.titleTextView.setText(document.optString("title"));
|
holder.titleTextView.setText(document.optString("title"));
|
||||||
|
|
||||||
JSONArray tags = document.optJSONArray("tags");
|
JSONArray tags = document.optJSONArray("tags");
|
||||||
holder.subtitleTextView.setText(TagUtil.buildSpannable(tags));
|
holder.subtitleTextView.setText(SpannableUtil.buildSpannableTags(tags));
|
||||||
|
|
||||||
String date = DateFormat.getDateFormat(holder.dateTextView.getContext()).format(new Date(document.optLong("create_date")));
|
String date = DateFormat.getDateFormat(holder.dateTextView.getContext()).format(new Date(document.optLong("create_date")));
|
||||||
holder.dateTextView.setText(date);
|
holder.dateTextView.setText(date);
|
||||||
|
@ -7,10 +7,11 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
import com.androidquery.AQuery;
|
|
||||||
import com.androidquery.callback.BitmapAjaxCallback;
|
|
||||||
import com.sismics.docs.R;
|
import com.sismics.docs.R;
|
||||||
|
import com.sismics.docs.util.OkHttpUtil;
|
||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
|
import com.squareup.picasso.Callback;
|
||||||
|
import com.squareup.picasso.MemoryPolicy;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
@ -30,21 +31,11 @@ public class FilePagerAdapter extends PagerAdapter {
|
|||||||
*/
|
*/
|
||||||
private List<JSONObject> files;
|
private List<JSONObject> files;
|
||||||
|
|
||||||
/**
|
|
||||||
* AQuery.
|
|
||||||
*/
|
|
||||||
private AQuery aq;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context.
|
* Context.
|
||||||
*/
|
*/
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
/**
|
|
||||||
* Auth token used to download files.
|
|
||||||
*/
|
|
||||||
private String authToken;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File pager adapter.
|
* File pager adapter.
|
||||||
*
|
*
|
||||||
@ -57,8 +48,6 @@ public class FilePagerAdapter extends PagerAdapter {
|
|||||||
files.add(filesArray.optJSONObject(i));
|
files.add(filesArray.optJSONObject(i));
|
||||||
}
|
}
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.authToken = PreferenceUtil.getAuthToken(context);
|
|
||||||
aq = new AQuery(context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -66,15 +55,20 @@ public class FilePagerAdapter extends PagerAdapter {
|
|||||||
View view = LayoutInflater.from(container.getContext()).inflate(R.layout.file_viewpager_item, container, false);
|
View view = LayoutInflater.from(container.getContext()).inflate(R.layout.file_viewpager_item, container, false);
|
||||||
|
|
||||||
ImageViewTouch fileImageView = (ImageViewTouch) view.findViewById(R.id.fileImageView);
|
ImageViewTouch fileImageView = (ImageViewTouch) view.findViewById(R.id.fileImageView);
|
||||||
ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.fileProgressBar);
|
final ProgressBar progressBar = (ProgressBar) view.findViewById(R.id.fileProgressBar);
|
||||||
JSONObject file = files.get(position);
|
JSONObject file = files.get(position);
|
||||||
String fileUrl = PreferenceUtil.getServerUrl(context) + "/api/file/" + file.optString("id") + "/data?size=web";
|
String fileUrl = PreferenceUtil.getServerUrl(context) + "/api/file/" + file.optString("id") + "/data?size=web";
|
||||||
aq.id(fileImageView)
|
|
||||||
.image(new BitmapAjaxCallback()
|
// Load image
|
||||||
.url(fileUrl)
|
OkHttpUtil.picasso(context)
|
||||||
.progress(progressBar)
|
.load(fileUrl)
|
||||||
.animation(AQuery.FADE_IN_NETWORK)
|
.memoryPolicy(MemoryPolicy.NO_CACHE, MemoryPolicy.NO_STORE) // Don't memory cache the images
|
||||||
.cookie("auth_token", authToken));
|
.into(fileImageView, new Callback.EmptyCallback() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess() {
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
fileImageView.setDisplayType(ImageViewTouchBase.DisplayType.FIT_TO_SCREEN);
|
fileImageView.setDisplayType(ImageViewTouchBase.DisplayType.FIT_TO_SCREEN);
|
||||||
|
|
||||||
@ -109,7 +103,7 @@ public class FilePagerAdapter extends PagerAdapter {
|
|||||||
* @return Object
|
* @return Object
|
||||||
*/
|
*/
|
||||||
public JSONObject getObjectAt(int position) {
|
public JSONObject getObjectAt(int position) {
|
||||||
if (files == null) {
|
if (files == null || position < 0 || position >= files.size()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,8 @@ public class LanguageAdapter extends BaseAdapter {
|
|||||||
}
|
}
|
||||||
languageList.add(new Language("fra", R.string.language_french, R.drawable.fra));
|
languageList.add(new Language("fra", R.string.language_french, R.drawable.fra));
|
||||||
languageList.add(new Language("eng", R.string.language_english, R.drawable.eng));
|
languageList.add(new Language("eng", R.string.language_english, R.drawable.eng));
|
||||||
languageList.add(new Language("jpn", R.string.language_japanese, R.drawable.jpn));
|
languageList.add(new Language("deu", R.string.language_german, R.drawable.deu));
|
||||||
|
languageList.add(new Language("pol", R.string.language_polish, R.drawable.pol));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -12,14 +12,13 @@ import com.sismics.docs.R;
|
|||||||
import com.sismics.docs.event.ShareDeleteEvent;
|
import com.sismics.docs.event.ShareDeleteEvent;
|
||||||
import com.sismics.docs.event.ShareSendEvent;
|
import com.sismics.docs.event.ShareSendEvent;
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Share list adapter.
|
* Share list adapter.
|
||||||
*
|
*
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
package com.sismics.docs.adapter;
|
package com.sismics.docs.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.util.TypedValue;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
@ -17,9 +19,8 @@ import org.json.JSONArray;
|
|||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tag list adapter.
|
* Tag list adapter.
|
||||||
@ -30,7 +31,7 @@ public class TagListAdapter extends BaseAdapter {
|
|||||||
/**
|
/**
|
||||||
* Tags.
|
* Tags.
|
||||||
*/
|
*/
|
||||||
private List<JSONObject> tags;
|
private List<TagItem> tagItemList = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tag list adapter.
|
* Tag list adapter.
|
||||||
@ -38,33 +39,52 @@ public class TagListAdapter extends BaseAdapter {
|
|||||||
* @param tagsArray Tags
|
* @param tagsArray Tags
|
||||||
*/
|
*/
|
||||||
public TagListAdapter(JSONArray tagsArray) {
|
public TagListAdapter(JSONArray tagsArray) {
|
||||||
this.tags = new ArrayList<>();
|
List<JSONObject> tags = new ArrayList<>();
|
||||||
for (int i = 0; i < tagsArray.length(); i++) {
|
for (int i = 0; i < tagsArray.length(); i++) {
|
||||||
tags.add(tagsArray.optJSONObject(i));
|
tags.add(tagsArray.optJSONObject(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort tags by count desc
|
// Reorder tags by parent/child relation and compute depth
|
||||||
Collections.sort(tags, new Comparator<JSONObject>() {
|
int depth = 0;
|
||||||
@Override
|
initTags(tags, "", depth);
|
||||||
public int compare(JSONObject lhs, JSONObject rhs) {
|
}
|
||||||
return lhs.optInt("count") < rhs.optInt("count") ? 1 : -1;
|
|
||||||
|
/**
|
||||||
|
* Init tags model recursively.
|
||||||
|
*
|
||||||
|
* @param tags All tags from server
|
||||||
|
* @param parentId Parent ID
|
||||||
|
* @param depth Depth
|
||||||
|
*/
|
||||||
|
private void initTags(List<JSONObject> tags, String parentId, int depth) {
|
||||||
|
// Get all tags with this parent
|
||||||
|
for (JSONObject tag : tags) {
|
||||||
|
String tagParentId = tag.optString("parent");
|
||||||
|
if (parentId.equals(tagParentId)) {
|
||||||
|
TagItem tagItem = new TagItem();
|
||||||
|
tagItem.id = tag.optString("id");
|
||||||
|
tagItem.name = tag.optString("name");
|
||||||
|
tagItem.color = tag.optString("color");
|
||||||
|
tagItem.depth = depth;
|
||||||
|
tagItemList.add(tagItem);
|
||||||
|
initTags(tags, tagItem.id, depth + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return tags.size();
|
return tagItemList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JSONObject getItem(int position) {
|
public TagItem getItem(int position) {
|
||||||
return tags.get(position);
|
return tagItemList.get(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getItemId(int position) {
|
public long getItemId(int position) {
|
||||||
return getItem(position).optString("id").hashCode();
|
return getItem(position).id.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -75,19 +95,38 @@ public class TagListAdapter extends BaseAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fill the view
|
// Fill the view
|
||||||
JSONObject tag = getItem(position);
|
TagItem tagItem = getItem(position);
|
||||||
TextView tagTextView = (TextView) view.findViewById(R.id.tagTextView);
|
TextView tagTextView = (TextView) view.findViewById(R.id.tagTextView);
|
||||||
tagTextView.setText(tag.optString("name"));
|
tagTextView.setText(tagItem.name);
|
||||||
TextView tagCountTextView = (TextView) view.findViewById(R.id.tagCountTextView);
|
|
||||||
tagCountTextView.setText(tag.optString("count"));
|
|
||||||
|
|
||||||
// Label color filtering
|
// Label color filtering
|
||||||
ImageView labelImageView = (ImageView) view.findViewById(R.id.labelImageView);
|
ImageView labelImageView = (ImageView) view.findViewById(R.id.labelImageView);
|
||||||
Drawable labelDrawable = labelImageView.getDrawable().mutate();
|
Drawable labelDrawable = labelImageView.getDrawable().mutate();
|
||||||
labelDrawable.setColorFilter(Color.parseColor(tag.optString("color")), PorterDuff.Mode.MULTIPLY);
|
labelDrawable.setColorFilter(Color.parseColor(tagItem.color), PorterDuff.Mode.MULTIPLY);
|
||||||
labelImageView.setImageDrawable(labelDrawable);
|
labelImageView.setImageDrawable(labelDrawable);
|
||||||
labelImageView.invalidate();
|
labelImageView.invalidate();
|
||||||
|
|
||||||
|
// Offset according to depth
|
||||||
|
Resources resources = parent.getContext().getResources();
|
||||||
|
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) labelImageView.getLayoutParams();
|
||||||
|
layoutParams.leftMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, tagItem.depth * 12, resources.getDisplayMetrics());
|
||||||
|
labelImageView.setLayoutParams(layoutParams);
|
||||||
|
labelImageView.requestLayout();
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A tag item in the tags list.
|
||||||
|
*/
|
||||||
|
public static class TagItem {
|
||||||
|
private String id;
|
||||||
|
private String name;
|
||||||
|
private String color;
|
||||||
|
private int depth;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.sismics.docs.event;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment add event.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class CommentAddEvent {
|
||||||
|
/**
|
||||||
|
* Comment.
|
||||||
|
*/
|
||||||
|
private JSONObject comment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a comment add event.
|
||||||
|
*
|
||||||
|
* @param comment Comment
|
||||||
|
*/
|
||||||
|
public CommentAddEvent(JSONObject comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of comment.
|
||||||
|
*
|
||||||
|
* @return comment
|
||||||
|
*/
|
||||||
|
public JSONObject getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.sismics.docs.event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comment delete event.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class CommentDeleteEvent {
|
||||||
|
/**
|
||||||
|
* Comment ID.
|
||||||
|
*/
|
||||||
|
private String commentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a comment add event.
|
||||||
|
*
|
||||||
|
* @param commentId Comment ID
|
||||||
|
*/
|
||||||
|
public CommentDeleteEvent(String commentId) {
|
||||||
|
this.commentId = commentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Getter of commentId.
|
||||||
|
*
|
||||||
|
* @return commentId
|
||||||
|
*/
|
||||||
|
public String getCommentId() {
|
||||||
|
return commentId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
package com.sismics.docs.fragment;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.sismics.docs.R;
|
||||||
|
import com.sismics.docs.util.NetworkUtil;
|
||||||
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Export PDF dialog fragment.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class DocExportPdfFragment extends DialogFragment {
|
||||||
|
/**
|
||||||
|
* Export PDF dialog fragment.
|
||||||
|
*
|
||||||
|
* @param id Document ID
|
||||||
|
* @param title Document title
|
||||||
|
*/
|
||||||
|
public static DocExportPdfFragment newInstance(String id, String title) {
|
||||||
|
DocExportPdfFragment fragment = new DocExportPdfFragment();
|
||||||
|
Bundle args = new Bundle();
|
||||||
|
args.putString("id", id);
|
||||||
|
args.putString("title", title);
|
||||||
|
fragment.setArguments(args);
|
||||||
|
return fragment;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
|
|
||||||
|
// Setup the view
|
||||||
|
LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||||
|
View view = inflater.inflate(R.layout.document_export_pdf_dialog, null);
|
||||||
|
final SeekBar marginSeekBar = (SeekBar) view.findViewById(R.id.marginSeekBar);
|
||||||
|
final CheckBox exportMetadataCheckbox = (CheckBox) view.findViewById(R.id.exportMetadataCheckbox);
|
||||||
|
final CheckBox exportCommentsCheckbox = (CheckBox) view.findViewById(R.id.exportCommentsCheckbox);
|
||||||
|
final CheckBox fitToPageCheckbox = (CheckBox) view.findViewById(R.id.fitToPageCheckbox);
|
||||||
|
final TextView marginValueText = (TextView) view.findViewById(R.id.marginValueText);
|
||||||
|
|
||||||
|
// Margin label follow seekbar value
|
||||||
|
marginSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||||
|
marginValueText.setText(String.format(Locale.ENGLISH, "%d", progress));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Build the dialog
|
||||||
|
builder.setView(view)
|
||||||
|
.setPositiveButton(R.string.download, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
// Download the PDF
|
||||||
|
String pdfUrl = PreferenceUtil.getServerUrl(getActivity()) + "/api/document/" + getArguments().getString("id") + "/pdf?" +
|
||||||
|
"metadata=" + exportMetadataCheckbox.isChecked() + "&comments=" + exportCommentsCheckbox.isChecked() + "&fitimagetopage=" + fitToPageCheckbox.isChecked() +
|
||||||
|
"&margin=" + marginSeekBar.getProgress();
|
||||||
|
String title = getArguments().getString("title");
|
||||||
|
NetworkUtil.downloadFile(getActivity(), pdfUrl, title + ".pdf", title, getString(R.string.download_pdf_title));
|
||||||
|
|
||||||
|
getDialog().cancel();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||||
|
public void onClick(DialogInterface dialog, int id) {
|
||||||
|
getDialog().cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ package com.sismics.docs.fragment;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.support.v4.widget.SwipeRefreshLayout;
|
import android.support.v4.widget.SwipeRefreshLayout;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
@ -9,29 +10,27 @@ import android.support.v7.widget.RecyclerView;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.sismics.docs.R;
|
import com.sismics.docs.R;
|
||||||
import com.sismics.docs.activity.DocumentEditActivity;
|
|
||||||
import com.sismics.docs.activity.DocumentViewActivity;
|
import com.sismics.docs.activity.DocumentViewActivity;
|
||||||
import com.sismics.docs.adapter.DocListAdapter;
|
import com.sismics.docs.adapter.DocListAdapter;
|
||||||
import com.sismics.docs.event.DocumentAddEvent;
|
import com.sismics.docs.event.DocumentAddEvent;
|
||||||
import com.sismics.docs.event.DocumentDeleteEvent;
|
import com.sismics.docs.event.DocumentDeleteEvent;
|
||||||
import com.sismics.docs.event.DocumentEditEvent;
|
import com.sismics.docs.event.DocumentEditEvent;
|
||||||
import com.sismics.docs.event.SearchEvent;
|
import com.sismics.docs.event.SearchEvent;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.listener.RecyclerItemClickListener;
|
import com.sismics.docs.listener.RecyclerItemClickListener;
|
||||||
import com.sismics.docs.resource.DocumentResource;
|
import com.sismics.docs.resource.DocumentResource;
|
||||||
import com.sismics.docs.ui.view.DividerItemDecoration;
|
import com.sismics.docs.ui.view.DividerItemDecoration;
|
||||||
import com.sismics.docs.ui.view.EmptyRecyclerView;
|
import com.sismics.docs.ui.view.EmptyRecyclerView;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author bgamard.
|
* @author bgamard.
|
||||||
*/
|
*/
|
||||||
@ -46,11 +45,6 @@ public class DocListFragment extends Fragment {
|
|||||||
*/
|
*/
|
||||||
private String query;
|
private String query;
|
||||||
|
|
||||||
/**
|
|
||||||
* Request code of adding document.
|
|
||||||
*/
|
|
||||||
private static final int REQUEST_CODE_ADD_DOCUMENT = 1;
|
|
||||||
|
|
||||||
// View cache
|
// View cache
|
||||||
private EmptyRecyclerView recyclerView;
|
private EmptyRecyclerView recyclerView;
|
||||||
private SwipeRefreshLayout swipeRefreshLayout;
|
private SwipeRefreshLayout swipeRefreshLayout;
|
||||||
@ -60,23 +54,22 @@ public class DocListFragment extends Fragment {
|
|||||||
private int previousTotal = 0;
|
private int previousTotal = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
final View view = inflater.inflate(R.layout.doc_list_fragment, container, false);
|
final View view = inflater.inflate(R.layout.doc_list_fragment, container, false);
|
||||||
|
|
||||||
// Configure the RecyclerView
|
// Configure the RecyclerView
|
||||||
recyclerView = (EmptyRecyclerView) view.findViewById(R.id.docList);
|
recyclerView = view.findViewById(R.id.docList);
|
||||||
adapter = new DocListAdapter();
|
adapter = new DocListAdapter();
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
recyclerView.setHasFixedSize(true);
|
recyclerView.setHasFixedSize(true);
|
||||||
recyclerView.setLongClickable(true);
|
recyclerView.setLongClickable(true);
|
||||||
recyclerView.addItemDecoration(new DividerItemDecoration(getResources().getDrawable(R.drawable.abc_list_divider_mtrl_alpha)));
|
|
||||||
|
|
||||||
// Configure the LayoutManager
|
// Configure the LayoutManager
|
||||||
final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
|
final LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
|
||||||
recyclerView.setLayoutManager(layoutManager);
|
recyclerView.setLayoutManager(layoutManager);
|
||||||
|
|
||||||
// Configure the swipe refresh layout
|
// Configure the swipe refresh layout
|
||||||
swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefreshLayout);
|
swipeRefreshLayout = view.findViewById(R.id.swipeRefreshLayout);
|
||||||
swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
|
swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_bright,
|
||||||
android.R.color.holo_green_light,
|
android.R.color.holo_green_light,
|
||||||
android.R.color.holo_orange_light,
|
android.R.color.holo_orange_light,
|
||||||
@ -100,7 +93,7 @@ public class DocListFragment extends Fragment {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
// Infinite scrolling
|
// Infinite scrolling
|
||||||
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
|
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||||
super.onScrolled(recyclerView, dx, dy);
|
super.onScrolled(recyclerView, dx, dy);
|
||||||
@ -122,16 +115,6 @@ public class DocListFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add document button
|
|
||||||
ImageButton addDocumentButton = (ImageButton) view.findViewById(R.id.addDocumentButton);
|
|
||||||
addDocumentButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
Intent intent = new Intent(getActivity(), DocumentEditActivity.class);
|
|
||||||
startActivityForResult(intent, REQUEST_CODE_ADD_DOCUMENT);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Grab the documents
|
// Grab the documents
|
||||||
loadDocuments(view, true);
|
loadDocuments(view, true);
|
||||||
|
|
||||||
@ -150,6 +133,7 @@ public class DocListFragment extends Fragment {
|
|||||||
*
|
*
|
||||||
* @param event Search event
|
* @param event Search event
|
||||||
*/
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(SearchEvent event) {
|
public void onEventMainThread(SearchEvent event) {
|
||||||
query = event.getQuery();
|
query = event.getQuery();
|
||||||
loadDocuments(getView(), true);
|
loadDocuments(getView(), true);
|
||||||
@ -160,6 +144,7 @@ public class DocListFragment extends Fragment {
|
|||||||
*
|
*
|
||||||
* @param event Document edit event
|
* @param event Document edit event
|
||||||
*/
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(DocumentEditEvent event) {
|
public void onEventMainThread(DocumentEditEvent event) {
|
||||||
adapter.updateDocument(event.getDocument());
|
adapter.updateDocument(event.getDocument());
|
||||||
}
|
}
|
||||||
@ -169,6 +154,7 @@ public class DocListFragment extends Fragment {
|
|||||||
*
|
*
|
||||||
* @param event Document delete event
|
* @param event Document delete event
|
||||||
*/
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(DocumentDeleteEvent event) {
|
public void onEventMainThread(DocumentDeleteEvent event) {
|
||||||
adapter.deleteDocument(event.getDocumentId());
|
adapter.deleteDocument(event.getDocumentId());
|
||||||
}
|
}
|
||||||
@ -178,6 +164,7 @@ public class DocListFragment extends Fragment {
|
|||||||
*
|
*
|
||||||
* @param event Document add event
|
* @param event Document add event
|
||||||
*/
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(DocumentAddEvent event) {
|
public void onEventMainThread(DocumentAddEvent event) {
|
||||||
// Refresh the list, maybe the new document fit in it
|
// Refresh the list, maybe the new document fit in it
|
||||||
loadDocuments(getView(), true);
|
loadDocuments(getView(), true);
|
||||||
@ -206,7 +193,7 @@ public class DocListFragment extends Fragment {
|
|||||||
private void loadDocuments(final View view, final boolean reset) {
|
private void loadDocuments(final View view, final boolean reset) {
|
||||||
if (view == null) return;
|
if (view == null) return;
|
||||||
final View progressBar = view.findViewById(R.id.progressBar);
|
final View progressBar = view.findViewById(R.id.progressBar);
|
||||||
final TextView documentsEmptyView = (TextView) view.findViewById(R.id.documentsEmptyView);
|
final TextView documentsEmptyView = view.findViewById(R.id.documentsEmptyView);
|
||||||
|
|
||||||
if (reset) {
|
if (reset) {
|
||||||
loading = true;
|
loading = true;
|
||||||
@ -218,16 +205,16 @@ public class DocListFragment extends Fragment {
|
|||||||
|
|
||||||
recyclerView.setEmptyView(progressBar);
|
recyclerView.setEmptyView(progressBar);
|
||||||
|
|
||||||
DocumentResource.list(getActivity(), reset ? 0 : adapter.getItemCount(), query, new JsonHttpResponseHandler() {
|
DocumentResource.list(getActivity(), reset ? 0 : adapter.getItemCount(), query, new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
adapter.addDocuments(response.optJSONArray("documents"));
|
adapter.addDocuments(response.optJSONArray("documents"));
|
||||||
documentsEmptyView.setText(R.string.no_documents);
|
documentsEmptyView.setText(R.string.no_documents);
|
||||||
recyclerView.setEmptyView(documentsEmptyView);
|
recyclerView.setEmptyView(documentsEmptyView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject response, Exception e) {
|
||||||
documentsEmptyView.setText(R.string.error_loading_documents);
|
documentsEmptyView.setText(R.string.error_loading_documents);
|
||||||
recyclerView.setEmptyView(documentsEmptyView);
|
recyclerView.setEmptyView(documentsEmptyView);
|
||||||
|
|
||||||
|
@ -21,17 +21,17 @@ import com.sismics.docs.R;
|
|||||||
import com.sismics.docs.adapter.ShareListAdapter;
|
import com.sismics.docs.adapter.ShareListAdapter;
|
||||||
import com.sismics.docs.event.ShareDeleteEvent;
|
import com.sismics.docs.event.ShareDeleteEvent;
|
||||||
import com.sismics.docs.event.ShareSendEvent;
|
import com.sismics.docs.event.ShareSendEvent;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.resource.DocumentResource;
|
import com.sismics.docs.resource.DocumentResource;
|
||||||
import com.sismics.docs.resource.ShareResource;
|
import com.sismics.docs.resource.ShareResource;
|
||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
|
import org.greenrobot.eventbus.Subscribe;
|
||||||
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Document sharing dialog fragment.
|
* Document sharing dialog fragment.
|
||||||
*
|
*
|
||||||
@ -44,7 +44,8 @@ public class DocShareFragment extends DialogFragment {
|
|||||||
private JSONObject document;
|
private JSONObject document;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Document sharing dialog fragment
|
* Document sharing dialog fragment.
|
||||||
|
*
|
||||||
* @param id Document ID
|
* @param id Document ID
|
||||||
*/
|
*/
|
||||||
public static DocShareFragment newInstance(String id) {
|
public static DocShareFragment newInstance(String id) {
|
||||||
@ -74,15 +75,15 @@ public class DocShareFragment extends DialogFragment {
|
|||||||
shareAddButton.setEnabled(false);
|
shareAddButton.setEnabled(false);
|
||||||
|
|
||||||
ShareResource.add(getActivity(), getArguments().getString("id"), shareNameEditText.getText().toString(),
|
ShareResource.add(getActivity(), getArguments().getString("id"), shareNameEditText.getText().toString(),
|
||||||
new JsonHttpResponseHandler() {
|
new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
shareNameEditText.setText("");
|
shareNameEditText.setText("");
|
||||||
loadShares(getDialog().getWindow().getDecorView());
|
loadShares(getDialog().getWindow().getDecorView());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
Toast.makeText(getActivity(), R.string.error_adding_share, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), R.string.error_adding_share, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,9 +122,9 @@ public class DocShareFragment extends DialogFragment {
|
|||||||
final ProgressBar shareProgressBar = (ProgressBar) view.findViewById(R.id.shareProgressBar);
|
final ProgressBar shareProgressBar = (ProgressBar) view.findViewById(R.id.shareProgressBar);
|
||||||
|
|
||||||
shareListView.setEmptyView(shareProgressBar);
|
shareListView.setEmptyView(shareProgressBar);
|
||||||
DocumentResource.get(getActivity(), getArguments().getString("id"), new JsonHttpResponseHandler() {
|
DocumentResource.get(getActivity(), getArguments().getString("id"), new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
document = response;
|
document = response;
|
||||||
JSONArray acls = response.optJSONArray("acls");
|
JSONArray acls = response.optJSONArray("acls");
|
||||||
shareProgressBar.setVisibility(View.GONE);
|
shareProgressBar.setVisibility(View.GONE);
|
||||||
@ -132,27 +133,39 @@ public class DocShareFragment extends DialogFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
getDialog().cancel();
|
getDialog().cancel();
|
||||||
Toast.makeText(getActivity(), R.string.error_loading_shares, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), R.string.error_loading_shares, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A share delete event has been fired.
|
||||||
|
*
|
||||||
|
* @param event Share delete event
|
||||||
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(ShareDeleteEvent event) {
|
public void onEventMainThread(ShareDeleteEvent event) {
|
||||||
ShareResource.delete(getActivity(), event.getId(), new JsonHttpResponseHandler() {
|
ShareResource.delete(getActivity(), event.getId(), new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
loadShares(getDialog().getWindow().getDecorView());
|
loadShares(getDialog().getWindow().getDecorView());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
Toast.makeText(getActivity(), R.string.error_deleting_share, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getActivity(), R.string.error_deleting_share, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A share send event has been fired.
|
||||||
|
*
|
||||||
|
* @param event Share send event
|
||||||
|
*/
|
||||||
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
public void onEventMainThread(ShareSendEvent event) {
|
public void onEventMainThread(ShareSendEvent event) {
|
||||||
if (document == null) return;
|
if (document == null) return;
|
||||||
|
|
||||||
|
@ -22,14 +22,13 @@ import com.sismics.docs.ui.view.TagsCompleteTextView;
|
|||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
import com.sismics.docs.util.SearchQueryBuilder;
|
import com.sismics.docs.util.SearchQueryBuilder;
|
||||||
|
|
||||||
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Advanced search fragment.
|
* Advanced search fragment.
|
||||||
*
|
*
|
||||||
@ -56,6 +55,7 @@ public class SearchFragment extends DialogFragment {
|
|||||||
View view = inflater.inflate(R.layout.search_dialog, null);
|
View view = inflater.inflate(R.layout.search_dialog, null);
|
||||||
final EditText searchEditText = (EditText) view.findViewById(R.id.searchEditText);
|
final EditText searchEditText = (EditText) view.findViewById(R.id.searchEditText);
|
||||||
final EditText fulltextEditText = (EditText) view.findViewById(R.id.fulltextEditText);
|
final EditText fulltextEditText = (EditText) view.findViewById(R.id.fulltextEditText);
|
||||||
|
final EditText creatorEditText = (EditText) view.findViewById(R.id.creatorEditText);
|
||||||
final CheckBox sharedCheckbox = (CheckBox) view.findViewById(R.id.sharedCheckbox);
|
final CheckBox sharedCheckbox = (CheckBox) view.findViewById(R.id.sharedCheckbox);
|
||||||
final Spinner languageSpinner = (Spinner) view.findViewById(R.id.languageSpinner);
|
final Spinner languageSpinner = (Spinner) view.findViewById(R.id.languageSpinner);
|
||||||
final DatePickerView beforeDatePicker = (DatePickerView) view.findViewById(R.id.beforeDatePicker);
|
final DatePickerView beforeDatePicker = (DatePickerView) view.findViewById(R.id.beforeDatePicker);
|
||||||
@ -73,7 +73,7 @@ public class SearchFragment extends DialogFragment {
|
|||||||
dialog.cancel();
|
dialog.cancel();
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
JSONArray tagArray = tags.optJSONArray("stats");
|
JSONArray tagArray = tags.optJSONArray("tags");
|
||||||
|
|
||||||
List<JSONObject> tagList = new ArrayList<>();
|
List<JSONObject> tagList = new ArrayList<>();
|
||||||
for (int i = 0; i < tagArray.length(); i++) {
|
for (int i = 0; i < tagArray.length(); i++) {
|
||||||
@ -90,6 +90,7 @@ public class SearchFragment extends DialogFragment {
|
|||||||
// Build the simple criterias
|
// Build the simple criterias
|
||||||
SearchQueryBuilder queryBuilder = new SearchQueryBuilder()
|
SearchQueryBuilder queryBuilder = new SearchQueryBuilder()
|
||||||
.simpleSearch(searchEditText.getText().toString())
|
.simpleSearch(searchEditText.getText().toString())
|
||||||
|
.creator(creatorEditText.getText().toString())
|
||||||
.shared(sharedCheckbox.isChecked())
|
.shared(sharedCheckbox.isChecked())
|
||||||
.language(((LanguageAdapter.Language) languageSpinner.getSelectedItem()).getId())
|
.language(((LanguageAdapter.Language) languageSpinner.getSelectedItem()).getId())
|
||||||
.before(beforeDatePicker.getDate())
|
.before(beforeDatePicker.getDate())
|
||||||
|
@ -9,10 +9,10 @@ import android.preference.PreferenceManager;
|
|||||||
import android.provider.SearchRecentSuggestions;
|
import android.provider.SearchRecentSuggestions;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.androidquery.util.AQUtility;
|
|
||||||
import com.sismics.docs.R;
|
import com.sismics.docs.R;
|
||||||
import com.sismics.docs.provider.RecentSuggestionsProvider;
|
import com.sismics.docs.provider.RecentSuggestionsProvider;
|
||||||
import com.sismics.docs.util.ApplicationUtil;
|
import com.sismics.docs.util.ApplicationUtil;
|
||||||
|
import com.sismics.docs.util.OkHttpUtil;
|
||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,7 +52,7 @@ public class SettingsFragment extends PreferenceFragment implements SharedPrefer
|
|||||||
clearCachePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
clearCachePref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceClick(Preference preference) {
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
AQUtility.cleanCacheAsync(getActivity());
|
OkHttpUtil.clearCache(getActivity());
|
||||||
Toast.makeText(getActivity(), R.string.pref_clear_cache_success, Toast.LENGTH_LONG).show();
|
Toast.makeText(getActivity(), R.string.pref_clear_cache_success, Toast.LENGTH_LONG).show();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
package com.sismics.docs.listener;
|
||||||
|
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import okhttp3.Call;
|
||||||
|
import okhttp3.Callback;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An HTTP callback.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class HttpCallback {
|
||||||
|
public void onSuccess(JSONObject json) {
|
||||||
|
// Implement me
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
|
// Implement me
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFinish() {
|
||||||
|
// Implement me
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an OkHttp Callback from a HttpCallback.
|
||||||
|
*
|
||||||
|
* @param httpCallback HttpCallback
|
||||||
|
* @return OkHttp Callback
|
||||||
|
*/
|
||||||
|
public static Callback buildOkHttpCallback(final HttpCallback httpCallback) {
|
||||||
|
return new Callback() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(final Call call, final Response response) throws IOException {
|
||||||
|
final String body = response.body().string();
|
||||||
|
|
||||||
|
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
try {
|
||||||
|
httpCallback.onSuccess(new JSONObject(body));
|
||||||
|
} catch (Exception e) {
|
||||||
|
httpCallback.onFailure(null, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
httpCallback.onFailure(new JSONObject(body), null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
httpCallback.onFailure(null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
httpCallback.onFinish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(final Call call, final IOException e) {
|
||||||
|
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
httpCallback.onFailure(null, e);
|
||||||
|
httpCallback.onFinish();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,241 +0,0 @@
|
|||||||
/*
|
|
||||||
Android Asynchronous Http Client
|
|
||||||
Copyright (c) 2011 James Smith <james@loopj.com>
|
|
||||||
http://loopj.com
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sismics.docs.listener;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.loopj.android.http.TextHttpResponseHandler;
|
|
||||||
|
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
import org.json.JSONTokener;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used to intercept and handle the responses from requests made using {@link com.loopj.android.http.AsyncHttpClient}, with
|
|
||||||
* automatic parsing into a {@link JSONObject} or {@link JSONArray}. <p> </p> This class is
|
|
||||||
* designed to be passed to get, post, put and delete requests with the {@link #onSuccess(int,
|
|
||||||
* org.apache.http.Header[], org.json.JSONArray)} or {@link #onSuccess(int,
|
|
||||||
* org.apache.http.Header[], org.json.JSONObject)} methods anonymously overridden. <p> </p>
|
|
||||||
* Additionally, you can override the other event methods from the parent class.
|
|
||||||
*/
|
|
||||||
public class JsonHttpResponseHandler extends TextHttpResponseHandler {
|
|
||||||
|
|
||||||
private static final String LOG_TAG = "JsonHttpResponseHandler";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new JsonHttpResponseHandler, with JSON String encoding UTF-8
|
|
||||||
*/
|
|
||||||
public JsonHttpResponseHandler() {
|
|
||||||
super(DEFAULT_CHARSET);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates new JsonHttpRespnseHandler with given JSON String encoding
|
|
||||||
*
|
|
||||||
* @param encoding String encoding to be used when parsing JSON
|
|
||||||
*/
|
|
||||||
public JsonHttpResponseHandler(String encoding) {
|
|
||||||
super(encoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns when request succeeds
|
|
||||||
*
|
|
||||||
* @param statusCode http response status line
|
|
||||||
* @param headers response headers if any
|
|
||||||
* @param response parsed response if any
|
|
||||||
*/
|
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
|
||||||
Log.w(LOG_TAG, "onSuccess(int, Header[], JSONObject) was not overriden, but callback was received");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns when request succeeds
|
|
||||||
*
|
|
||||||
* @param statusCode http response status line
|
|
||||||
* @param headers response headers if any
|
|
||||||
* @param response parsed response if any
|
|
||||||
*/
|
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONArray response) {
|
|
||||||
Log.w(LOG_TAG, "onSuccess(int, Header[], JSONArray) was not overriden, but callback was received");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns when request failed
|
|
||||||
*
|
|
||||||
* @param statusCode http response status line
|
|
||||||
* @param headers response headers if any
|
|
||||||
* @param throwable throwable describing the way request failed
|
|
||||||
* @param errorResponse parsed response if any
|
|
||||||
*/
|
|
||||||
public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) {
|
|
||||||
Log.w(LOG_TAG, "onFailure(int, Header[], Throwable, JSONObject) was not overriden, but callback was received", throwable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns when request failed
|
|
||||||
*
|
|
||||||
* @param statusCode http response status line
|
|
||||||
* @param headers response headers if any
|
|
||||||
* @param throwable throwable describing the way request failed
|
|
||||||
* @param errorResponse parsed response if any
|
|
||||||
*/
|
|
||||||
public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONArray errorResponse) {
|
|
||||||
Log.w(LOG_TAG, "onFailure(int, Header[], Throwable, JSONArray) was not overriden, but callback was received", throwable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
|
|
||||||
Log.w(LOG_TAG, "onFailure(int, Header[], String, Throwable) was not overriden, but callback was received", throwable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSuccess(int statusCode, Header[] headers, String responseString) {
|
|
||||||
Log.w(LOG_TAG, "onSuccess(int, Header[], String) was not overriden, but callback was received");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void onSuccess(final int statusCode, final Header[] headers, final byte[] responseBytes) {
|
|
||||||
if (statusCode != HttpStatus.SC_NO_CONTENT) {
|
|
||||||
Runnable parser = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
final Object jsonResponse = parseResponse(responseBytes);
|
|
||||||
postRunnable(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (jsonResponse instanceof JSONObject) {
|
|
||||||
onSuccess(statusCode, headers, (JSONObject) jsonResponse);
|
|
||||||
} else if (jsonResponse instanceof JSONArray) {
|
|
||||||
onSuccess(statusCode, headers, (JSONArray) jsonResponse);
|
|
||||||
} else if (jsonResponse instanceof String) {
|
|
||||||
onFailure(statusCode, headers, (String) jsonResponse, new JSONException("Response cannot be parsed as JSON data"));
|
|
||||||
} else {
|
|
||||||
onFailure(statusCode, headers, new JSONException("Unexpected response type " + jsonResponse.getClass().getName()), (JSONObject) null);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (final JSONException ex) {
|
|
||||||
postRunnable(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
onFailure(statusCode, headers, ex, (JSONObject) null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (!getUseSynchronousMode()) {
|
|
||||||
new Thread(parser).start();
|
|
||||||
} else {
|
|
||||||
// In synchronous mode everything should be run on one thread
|
|
||||||
parser.run();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
onSuccess(statusCode, headers, new JSONObject());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void onFailure(final int statusCode, final Header[] headers, final byte[] responseBytes, final Throwable throwable) {
|
|
||||||
if (responseBytes != null) {
|
|
||||||
Runnable parser = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
final Object jsonResponse = parseResponse(responseBytes);
|
|
||||||
postRunnable(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if (jsonResponse instanceof JSONObject) {
|
|
||||||
onFailure(statusCode, headers, throwable, (JSONObject) jsonResponse);
|
|
||||||
} else if (jsonResponse instanceof JSONArray) {
|
|
||||||
onFailure(statusCode, headers, throwable, (JSONArray) jsonResponse);
|
|
||||||
} else if (jsonResponse instanceof String) {
|
|
||||||
onFailure(statusCode, headers, (String) jsonResponse, throwable);
|
|
||||||
} else {
|
|
||||||
onFailure(statusCode, headers, new JSONException("Unexpected response type " + jsonResponse.getClass().getName()), (JSONObject) null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (final JSONException ex) {
|
|
||||||
postRunnable(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
onFailure(statusCode, headers, ex, (JSONObject) null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (!getUseSynchronousMode()) {
|
|
||||||
new Thread(parser).start();
|
|
||||||
} else {
|
|
||||||
// In synchronous mode everything should be run on one thread
|
|
||||||
parser.run();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Log.v(LOG_TAG, "response body is null, calling onFailure(Throwable, JSONObject)");
|
|
||||||
onFailure(statusCode, headers, throwable, (JSONObject) null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// In all cases, call the default failure listener
|
|
||||||
onAllFailure(statusCode, headers, responseBytes, throwable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
|
||||||
// All failures go there
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns Object of type {@link JSONObject}, {@link JSONArray}, String, Boolean, Integer, Long,
|
|
||||||
* Double or {@link JSONObject#NULL}, see {@link org.json.JSONTokener#nextValue()}
|
|
||||||
*
|
|
||||||
* @param responseBody response bytes to be assembled in String and parsed as JSON
|
|
||||||
* @return Object parsedResponse
|
|
||||||
* @throws org.json.JSONException exception if thrown while parsing JSON
|
|
||||||
*/
|
|
||||||
protected Object parseResponse(byte[] responseBody) throws JSONException {
|
|
||||||
if (null == responseBody)
|
|
||||||
return null;
|
|
||||||
Object result = null;
|
|
||||||
//trim the string to prevent start with blank, and test if the string is valid JSON, because the parser don't do this :(. If JSON is not valid this will return null
|
|
||||||
String jsonString = getResponseString(responseBody, getCharset());
|
|
||||||
if (jsonString != null) {
|
|
||||||
jsonString = jsonString.trim();
|
|
||||||
if (jsonString.startsWith(UTF8_BOM)) {
|
|
||||||
jsonString = jsonString.substring(1);
|
|
||||||
}
|
|
||||||
if (jsonString.startsWith("{") || jsonString.startsWith("[")) {
|
|
||||||
result = new JSONTokener(jsonString).nextValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (result == null) {
|
|
||||||
result = jsonString;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,7 +11,7 @@ public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListen
|
|||||||
private OnItemClickListener mListener;
|
private OnItemClickListener mListener;
|
||||||
|
|
||||||
public interface OnItemClickListener {
|
public interface OnItemClickListener {
|
||||||
public void onItemClick(View view, int position);
|
void onItemClick(View view, int position);
|
||||||
}
|
}
|
||||||
|
|
||||||
GestureDetector mGestureDetector;
|
GestureDetector mGestureDetector;
|
||||||
@ -25,13 +25,18 @@ public class RecyclerItemClickListener implements RecyclerView.OnItemTouchListen
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
|
@Override
|
||||||
|
public boolean onInterceptTouchEvent(RecyclerView view, MotionEvent e) {
|
||||||
View childView = view.findChildViewUnder(e.getX(), e.getY());
|
View childView = view.findChildViewUnder(e.getX(), e.getY());
|
||||||
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
|
if (childView != null && mListener != null && mGestureDetector.onTouchEvent(e)) {
|
||||||
mListener.onItemClick(childView, view.getChildPosition(childView));
|
mListener.onItemClick(childView, view.getChildAdapterPosition(childView));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }
|
@Override
|
||||||
|
public void onTouchEvent(RecyclerView view, MotionEvent motionEvent) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) { }
|
||||||
}
|
}
|
@ -4,11 +4,10 @@ import android.app.Activity;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.sismics.docs.listener.CallbackListener;
|
import com.sismics.docs.listener.CallbackListener;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.resource.UserResource;
|
import com.sismics.docs.resource.UserResource;
|
||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,9 +79,9 @@ public class ApplicationContext {
|
|||||||
* @param callbackListener CallbackListener
|
* @param callbackListener CallbackListener
|
||||||
*/
|
*/
|
||||||
public void fetchUserInfo(final Activity activity, final CallbackListener callbackListener) {
|
public void fetchUserInfo(final Activity activity, final CallbackListener callbackListener) {
|
||||||
UserResource.info(activity.getApplicationContext(), new JsonHttpResponseHandler() {
|
UserResource.info(activity.getApplicationContext(), new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, final JSONObject json) {
|
public void onSuccess(JSONObject json) {
|
||||||
// Save data in application context
|
// Save data in application context
|
||||||
if (!json.optBoolean("anonymous", true)) {
|
if (!json.optBoolean("anonymous", true)) {
|
||||||
setUserInfo(activity.getApplicationContext(), json);
|
setUserInfo(activity.getApplicationContext(), json);
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.sismics.docs.resource;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
|
import com.sismics.docs.util.OkHttpUtil;
|
||||||
|
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to /auditlog API.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class AuditLogResource extends BaseResource {
|
||||||
|
/**
|
||||||
|
* GET /auditlog.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @param documentId Document ID
|
||||||
|
* @param callback Callback
|
||||||
|
*/
|
||||||
|
public static void list(Context context, String documentId, HttpCallback callback) {
|
||||||
|
HttpUrl.Builder httpUrlBuilder = HttpUrl.parse(getApiUrl(context) + "/auditlog")
|
||||||
|
.newBuilder();
|
||||||
|
if (documentId != null) {
|
||||||
|
httpUrlBuilder.addQueryParameter("document", documentId);
|
||||||
|
}
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(httpUrlBuilder.build())
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
|
}
|
||||||
|
}
|
@ -1,125 +1,15 @@
|
|||||||
package com.sismics.docs.resource;
|
package com.sismics.docs.resource;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import com.androidquery.callback.AbstractAjaxCallback;
|
|
||||||
import com.loopj.android.http.AsyncHttpClient;
|
|
||||||
import com.loopj.android.http.PersistentCookieStore;
|
|
||||||
import com.sismics.docs.util.ApplicationUtil;
|
|
||||||
import com.sismics.docs.util.PreferenceUtil;
|
import com.sismics.docs.util.PreferenceUtil;
|
||||||
|
|
||||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.security.KeyManagementException;
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.UnrecoverableKeyException;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for API access.
|
* Base class for API access.
|
||||||
*
|
*
|
||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
public class BaseResource {
|
public class BaseResource {
|
||||||
|
|
||||||
/**
|
|
||||||
* User-Agent to use.
|
|
||||||
*/
|
|
||||||
protected static String USER_AGENT = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Accept-Language header.
|
|
||||||
*/
|
|
||||||
protected static String ACCEPT_LANGUAGE = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HTTP client.
|
|
||||||
*/
|
|
||||||
protected static AsyncHttpClient client = new AsyncHttpClient();
|
|
||||||
|
|
||||||
static {
|
|
||||||
// 20sec default timeout
|
|
||||||
client.setTimeout(60000);
|
|
||||||
try {
|
|
||||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
||||||
trustStore.load(null, null);
|
|
||||||
MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
|
|
||||||
sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
|
||||||
client.setSSLSocketFactory(sf);
|
|
||||||
AbstractAjaxCallback.setSSF(sf);
|
|
||||||
} catch (Exception e) {
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resource initialization.
|
|
||||||
*
|
|
||||||
* @param context Context
|
|
||||||
*/
|
|
||||||
protected static void init(Context context) {
|
|
||||||
client.setCookieStore(new PersistentCookieStore(context));
|
|
||||||
|
|
||||||
if (USER_AGENT == null) {
|
|
||||||
USER_AGENT = "Sismics Docs Android " + ApplicationUtil.getVersionName(context) + "/Android " + Build.VERSION.RELEASE + "/" + Build.MODEL;
|
|
||||||
client.setUserAgent(USER_AGENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ACCEPT_LANGUAGE == null) {
|
|
||||||
Locale locale = Locale.getDefault();
|
|
||||||
ACCEPT_LANGUAGE = locale.getLanguage() + "_" + locale.getCountry();
|
|
||||||
client.addHeader("Accept-Language", ACCEPT_LANGUAGE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Socket factory to allow self-signed certificates.
|
|
||||||
*
|
|
||||||
* @author bgamard
|
|
||||||
*/
|
|
||||||
public static class MySSLSocketFactory extends SSLSocketFactory {
|
|
||||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
|
||||||
|
|
||||||
public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
|
|
||||||
super(truststore);
|
|
||||||
|
|
||||||
TrustManager tm = new X509TrustManager() {
|
|
||||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
|
||||||
}
|
|
||||||
|
|
||||||
public X509Certificate[] getAcceptedIssuers() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sslContext.init(null, new TrustManager[] { tm }, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
|
|
||||||
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Socket createSocket() throws IOException {
|
|
||||||
return sslContext.getSocketFactory().createSocket();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns cleaned API URL.
|
* Returns cleaned API URL.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
package com.sismics.docs.resource;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
|
import com.sismics.docs.util.OkHttpUtil;
|
||||||
|
|
||||||
|
import okhttp3.FormBody;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Access to /comment API.
|
||||||
|
*
|
||||||
|
* @author bgamard
|
||||||
|
*/
|
||||||
|
public class CommentResource extends BaseResource {
|
||||||
|
/**
|
||||||
|
* GET /comment/id.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @param documentId Document ID
|
||||||
|
* @param callback Callback
|
||||||
|
*/
|
||||||
|
public static void list(Context context, String documentId, HttpCallback callback) {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/comment/" + documentId))
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT /comment.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @param documentId Document ID
|
||||||
|
* @param content Comment content
|
||||||
|
* @param callback Callback
|
||||||
|
*/
|
||||||
|
public static void add(Context context, String documentId, String content, HttpCallback callback) {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/comment"))
|
||||||
|
.put(new FormBody.Builder()
|
||||||
|
.add("id", documentId)
|
||||||
|
.add("content", content)
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE /comment/id.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @param commentId Comment ID
|
||||||
|
* @param callback Callback
|
||||||
|
*/
|
||||||
|
public static void remove(Context context, String commentId, HttpCallback callback) {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/comment/" + commentId))
|
||||||
|
.delete()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
|
}
|
||||||
|
}
|
@ -2,11 +2,15 @@ package com.sismics.docs.resource;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.loopj.android.http.RequestParams;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.util.OkHttpUtil;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import okhttp3.FormBody;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to /document API.
|
* Access to /document API.
|
||||||
*
|
*
|
||||||
@ -19,18 +23,23 @@ public class DocumentResource extends BaseResource {
|
|||||||
* @param context Context
|
* @param context Context
|
||||||
* @param offset Offset
|
* @param offset Offset
|
||||||
* @param query Search query
|
* @param query Search query
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void list(Context context, int offset, String query, JsonHttpResponseHandler responseHandler) {
|
public static void list(Context context, int offset, String query, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/document/list")
|
||||||
RequestParams params = new RequestParams();
|
.newBuilder()
|
||||||
params.put("limit", 20);
|
.addQueryParameter("limit", "20")
|
||||||
params.put("offset", offset);
|
.addQueryParameter("offset", Integer.toString(offset))
|
||||||
params.put("sort_column", 3);
|
.addQueryParameter("sort_column", "3")
|
||||||
params.put("asc", false);
|
.addQueryParameter("asc", "false")
|
||||||
params.put("search", query);
|
.addQueryParameter("search", query)
|
||||||
client.get(getApiUrl(context) + "/document/list", params, responseHandler);
|
.build())
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,12 +47,16 @@ public class DocumentResource extends BaseResource {
|
|||||||
*
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param id ID
|
* @param id ID
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void get(Context context, String id, JsonHttpResponseHandler responseHandler) {
|
public static void get(Context context, String id, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/document/" + id))
|
||||||
client.get(getApiUrl(context) + "/document/" + id, responseHandler);
|
.get()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,12 +64,16 @@ public class DocumentResource extends BaseResource {
|
|||||||
*
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param id ID
|
* @param id ID
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void delete(Context context, String id, JsonHttpResponseHandler responseHandler) {
|
public static void delete(Context context, String id, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/document/" + id))
|
||||||
client.delete(getApiUrl(context) + "/document/" + id, responseHandler);
|
.delete()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,19 +85,26 @@ public class DocumentResource extends BaseResource {
|
|||||||
* @param tagIdList Tags ID list
|
* @param tagIdList Tags ID list
|
||||||
* @param language Language
|
* @param language Language
|
||||||
* @param createDate Create date
|
* @param createDate Create date
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void add(Context context, String title, String description,
|
public static void add(Context context, String title, String description,
|
||||||
Set<String> tagIdList, String language, long createDate, JsonHttpResponseHandler responseHandler) {
|
Set<String> tagIdList, String language, long createDate, HttpCallback callback) {
|
||||||
init(context);
|
FormBody.Builder formBuilder = new FormBody.Builder()
|
||||||
|
.add("title", title)
|
||||||
|
.add("description", description)
|
||||||
|
.add("language", language)
|
||||||
|
.add("create_date", Long.toString(createDate));
|
||||||
|
for( String tagId : tagIdList) {
|
||||||
|
formBuilder.add("tags", tagId);
|
||||||
|
}
|
||||||
|
|
||||||
RequestParams params = new RequestParams();
|
Request request = new Request.Builder()
|
||||||
params.put("title", title);
|
.url(HttpUrl.parse(getApiUrl(context) + "/document"))
|
||||||
params.put("description", description);
|
.put(formBuilder.build())
|
||||||
params.put("tags", tagIdList);
|
.build();
|
||||||
params.put("language", language);
|
OkHttpUtil.buildClient(context)
|
||||||
params.put("create_date", createDate);
|
.newCall(request)
|
||||||
client.put(getApiUrl(context) + "/document", params, responseHandler);
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -93,27 +117,25 @@ public class DocumentResource extends BaseResource {
|
|||||||
* @param tagIdList Tags ID list
|
* @param tagIdList Tags ID list
|
||||||
* @param language Language
|
* @param language Language
|
||||||
* @param createDate Create date
|
* @param createDate Create date
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void edit(Context context, String id, String title, String description,
|
public static void edit(Context context, String id, String title, String description,
|
||||||
Set<String> tagIdList, String language, long createDate, JsonHttpResponseHandler responseHandler) {
|
Set<String> tagIdList, String language, long createDate, HttpCallback callback) {
|
||||||
init(context);
|
FormBody.Builder formBuilder = new FormBody.Builder()
|
||||||
|
.add("title", title)
|
||||||
RequestParams params = new RequestParams();
|
.add("description", description)
|
||||||
params.put("title", title);
|
.add("language", language)
|
||||||
params.put("description", description);
|
.add("create_date", Long.toString(createDate));
|
||||||
params.put("tags", tagIdList);
|
for( String tagId : tagIdList) {
|
||||||
params.put("language", language);
|
formBuilder.add("tags", tagId);
|
||||||
params.put("create_date", createDate);
|
|
||||||
client.post(getApiUrl(context) + "/document/" + id, params, responseHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
Request request = new Request.Builder()
|
||||||
* Cancel pending requests.
|
.url(HttpUrl.parse(getApiUrl(context) + "/document/" + id))
|
||||||
*
|
.post(formBuilder.build())
|
||||||
* @param context Context
|
.build();
|
||||||
*/
|
OkHttpUtil.buildClient(context)
|
||||||
public static void cancel(Context context) {
|
.newCall(request)
|
||||||
client.cancelRequests(context, true);
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,24 @@ package com.sismics.docs.resource;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.loopj.android.http.PersistentCookieStore;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.loopj.android.http.RequestParams;
|
import com.sismics.docs.util.OkHttpUtil;
|
||||||
import com.loopj.android.http.SyncHttpClient;
|
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.security.KeyStore;
|
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.MultipartBody;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import okhttp3.internal.Util;
|
||||||
|
import okio.BufferedSink;
|
||||||
|
import okio.Okio;
|
||||||
|
import okio.Source;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -22,12 +33,19 @@ public class FileResource extends BaseResource {
|
|||||||
*
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param documentId Document ID
|
* @param documentId Document ID
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void list(Context context, String documentId, JsonHttpResponseHandler responseHandler) {
|
public static void list(Context context, String documentId, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/file/list")
|
||||||
client.get(getApiUrl(context) + "/file/list?id=" + documentId, responseHandler);
|
.newBuilder()
|
||||||
|
.addQueryParameter("id", documentId)
|
||||||
|
.build())
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,12 +53,16 @@ public class FileResource extends BaseResource {
|
|||||||
*
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param id ID
|
* @param id ID
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void delete(Context context, String id, JsonHttpResponseHandler responseHandler) {
|
public static void delete(Context context, String id, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/file/" + id))
|
||||||
client.delete(getApiUrl(context) + "/file/" + id, responseHandler);
|
.delete()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -49,34 +71,53 @@ public class FileResource extends BaseResource {
|
|||||||
* @param context Context
|
* @param context Context
|
||||||
* @param documentId Document ID
|
* @param documentId Document ID
|
||||||
* @param is Input stream
|
* @param is Input stream
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public static void addSync(Context context, String documentId, InputStream is, JsonHttpResponseHandler responseHandler) throws Exception {
|
public static void addSync(Context context, String documentId, final InputStream is, HttpCallback callback) throws Exception {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/file"))
|
||||||
SyncHttpClient client = new SyncHttpClient();
|
.put(new MultipartBody.Builder()
|
||||||
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
.setType(MultipartBody.FORM)
|
||||||
trustStore.load(null, null);
|
.addFormDataPart("id", documentId)
|
||||||
MySSLSocketFactory sf = new MySSLSocketFactory(trustStore);
|
.addFormDataPart("file", "file", new RequestBody() {
|
||||||
sf.setHostnameVerifier(MySSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
@Override
|
||||||
client.setSSLSocketFactory(sf);
|
public MediaType contentType() {
|
||||||
client.setCookieStore(new PersistentCookieStore(context));
|
return MediaType.parse("application/octet-stream");
|
||||||
client.setUserAgent(USER_AGENT);
|
|
||||||
client.addHeader("Accept-Language", ACCEPT_LANGUAGE);
|
|
||||||
|
|
||||||
RequestParams params = new RequestParams();
|
|
||||||
params.put("id", documentId);
|
|
||||||
params.put("file", is, "file", "application/octet-stream", true);
|
|
||||||
client.put(getApiUrl(context) + "/file", params, responseHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Cancel pending requests.
|
public void writeTo(BufferedSink sink) throws IOException {
|
||||||
*
|
Source source = Okio.source(is);
|
||||||
* @param context Context
|
try {
|
||||||
*/
|
sink.writeAll(source);
|
||||||
public static void cancel(Context context) {
|
} finally {
|
||||||
client.cancelRequests(context, true);
|
Util.closeQuietly(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
Response response = OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
// Call the right callback
|
||||||
|
final String body = response.body().string();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
try {
|
||||||
|
callback.onSuccess(new JSONObject(body));
|
||||||
|
} catch (Exception e) {
|
||||||
|
callback.onFailure(null, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
callback.onFailure(new JSONObject(body), null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
callback.onFailure(null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.onFinish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,12 @@ package com.sismics.docs.resource;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.loopj.android.http.RequestParams;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.util.OkHttpUtil;
|
||||||
|
|
||||||
|
import okhttp3.FormBody;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,15 +22,19 @@ public class ShareResource extends BaseResource {
|
|||||||
* @param context Context
|
* @param context Context
|
||||||
* @param documentId Document ID
|
* @param documentId Document ID
|
||||||
* @param name Name
|
* @param name Name
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void add(Context context, String documentId, String name, JsonHttpResponseHandler responseHandler) {
|
public static void add(Context context, String documentId, String name, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/share"))
|
||||||
RequestParams params = new RequestParams();
|
.put(new FormBody.Builder()
|
||||||
params.put("id", documentId);
|
.add("id", documentId)
|
||||||
params.put("name", name);
|
.add("name", name)
|
||||||
client.put(getApiUrl(context) + "/share", params, responseHandler);
|
.build())
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,11 +42,15 @@ public class ShareResource extends BaseResource {
|
|||||||
*
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param id ID
|
* @param id ID
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void delete(Context context, String id, JsonHttpResponseHandler responseHandler) {
|
public static void delete(Context context, String id, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/share/" + id))
|
||||||
client.delete(getApiUrl(context) + "/share/" + id, responseHandler);
|
.delete()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,11 @@ package com.sismics.docs.resource;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
|
import com.sismics.docs.util.OkHttpUtil;
|
||||||
|
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -12,14 +16,18 @@ import com.sismics.docs.listener.JsonHttpResponseHandler;
|
|||||||
*/
|
*/
|
||||||
public class TagResource extends BaseResource {
|
public class TagResource extends BaseResource {
|
||||||
/**
|
/**
|
||||||
* GET /tag/stats.
|
* GET /tag/list.
|
||||||
*
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void stats(Context context, JsonHttpResponseHandler responseHandler) {
|
public static void list(Context context, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/tag/list"))
|
||||||
client.get(getApiUrl(context) + "/tag/stats", responseHandler);
|
.get()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,12 @@ package com.sismics.docs.resource;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.loopj.android.http.RequestParams;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.util.OkHttpUtil;
|
||||||
|
|
||||||
|
import okhttp3.FormBody;
|
||||||
|
import okhttp3.HttpUrl;
|
||||||
|
import okhttp3.Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to /user API.
|
* Access to /user API.
|
||||||
@ -18,41 +22,69 @@ public class UserResource extends BaseResource {
|
|||||||
* @param context Context
|
* @param context Context
|
||||||
* @param username Username
|
* @param username Username
|
||||||
* @param password Password
|
* @param password Password
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void login(Context context, String username, String password, JsonHttpResponseHandler responseHandler) {
|
public static void login(Context context, String username, String password, String code, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/user/login"))
|
||||||
RequestParams params = new RequestParams();
|
.post(new FormBody.Builder()
|
||||||
params.put("username", username);
|
.add("username", username)
|
||||||
params.put("password", password);
|
.add("password", password)
|
||||||
params.put("remember", "true");
|
.add("code", code)
|
||||||
client.post(getApiUrl(context) + "/user/login", params, responseHandler);
|
.add("remember", "true")
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /user.
|
* GET /user.
|
||||||
*
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void info(Context context, JsonHttpResponseHandler responseHandler) {
|
public static void info(Context context, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/user"))
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
|
}
|
||||||
|
|
||||||
RequestParams params = new RequestParams();
|
/**
|
||||||
client.get(getApiUrl(context) + "/user", params, responseHandler);
|
* GET /user/username.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* param username Username
|
||||||
|
* @param callback Callback
|
||||||
|
*/
|
||||||
|
public static void get(Context context, String username, HttpCallback callback) {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/user/" + username))
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST /user/logout.
|
* POST /user/logout.
|
||||||
*
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param responseHandler Callback
|
* @param callback Callback
|
||||||
*/
|
*/
|
||||||
public static void logout(Context context, JsonHttpResponseHandler responseHandler) {
|
public static void logout(Context context, HttpCallback callback) {
|
||||||
init(context);
|
Request request = new Request.Builder()
|
||||||
|
.url(HttpUrl.parse(getApiUrl(context) + "/user/logout"))
|
||||||
RequestParams params = new RequestParams();
|
.post(new FormBody.Builder().build())
|
||||||
client.post(getApiUrl(context) + "/user/logout", params, responseHandler);
|
.build();
|
||||||
|
OkHttpUtil.buildClient(context)
|
||||||
|
.newCall(request)
|
||||||
|
.enqueue(HttpCallback.buildOkHttpCallback(callback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,229 @@
|
|||||||
|
package com.sismics.docs.resource.cookie;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.net.CookieStore;
|
||||||
|
import java.net.HttpCookie;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A persistent cookie store which implements the Apache HttpClient CookieStore interface.
|
||||||
|
* Cookies are stored and will persist on the user's device between application sessions since they
|
||||||
|
* are serialized and stored in SharedPreferences.
|
||||||
|
*/
|
||||||
|
public class PersistentCookieStore implements CookieStore {
|
||||||
|
|
||||||
|
private static final String LOG_TAG = "PersistentCookieStore";
|
||||||
|
private static final String COOKIE_PREFS = "CookiePrefsFileOkHttp";
|
||||||
|
private static final String COOKIE_NAME_PREFIX = "cookie_okhttp_";
|
||||||
|
|
||||||
|
private final HashMap<String, ConcurrentHashMap<String, HttpCookie>> cookies;
|
||||||
|
private final SharedPreferences cookiePrefs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a persistent cookie store.
|
||||||
|
*
|
||||||
|
* @param context Context to attach cookie store to
|
||||||
|
*/
|
||||||
|
public PersistentCookieStore(Context context) {
|
||||||
|
cookiePrefs = context.getSharedPreferences(COOKIE_PREFS, 0);
|
||||||
|
cookies = new HashMap<>();
|
||||||
|
|
||||||
|
// Load any previously stored cookies into the store
|
||||||
|
Map<String, ?> prefsMap = cookiePrefs.getAll();
|
||||||
|
for (Map.Entry<String, ?> entry : prefsMap.entrySet()) {
|
||||||
|
if (entry.getValue() != null && !((String) entry.getValue()).startsWith(COOKIE_NAME_PREFIX)) {
|
||||||
|
String[] cookieNames = TextUtils.split((String) entry.getValue(), ",");
|
||||||
|
for (String name : cookieNames) {
|
||||||
|
String encodedCookie = cookiePrefs.getString(COOKIE_NAME_PREFIX + name, null);
|
||||||
|
if (encodedCookie != null) {
|
||||||
|
HttpCookie decodedCookie = decodeCookie(encodedCookie);
|
||||||
|
if (decodedCookie != null) {
|
||||||
|
if (!cookies.containsKey(entry.getKey()))
|
||||||
|
cookies.put(entry.getKey(), new ConcurrentHashMap<String, HttpCookie>());
|
||||||
|
cookies.get(entry.getKey()).put(name, decodedCookie);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(URI uri, HttpCookie cookie) {
|
||||||
|
String name = getCookieToken(uri, cookie);
|
||||||
|
|
||||||
|
// Save cookie into local store, or remove if expired
|
||||||
|
if (!cookie.hasExpired()) {
|
||||||
|
if (!cookies.containsKey(uri.getHost()))
|
||||||
|
cookies.put(uri.getHost(), new ConcurrentHashMap<String, HttpCookie>());
|
||||||
|
cookies.get(uri.getHost()).put(name, cookie);
|
||||||
|
} else {
|
||||||
|
if (cookies.containsKey(uri.toString()))
|
||||||
|
cookies.get(uri.getHost()).remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save cookie into persistent store
|
||||||
|
SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
|
||||||
|
prefsWriter.putString(uri.getHost(), TextUtils.join(",", cookies.get(uri.getHost()).keySet()));
|
||||||
|
prefsWriter.putString(COOKIE_NAME_PREFIX + name, encodeCookie(new SerializableHttpCookie(cookie)));
|
||||||
|
prefsWriter.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getCookieToken(URI uri, HttpCookie cookie) {
|
||||||
|
return cookie.getName() + cookie.getDomain();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HttpCookie> get(URI uri) {
|
||||||
|
ArrayList<HttpCookie> ret = new ArrayList<>();
|
||||||
|
if (cookies.containsKey(uri.getHost()))
|
||||||
|
ret.addAll(cookies.get(uri.getHost()).values());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean removeAll() {
|
||||||
|
SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
|
||||||
|
prefsWriter.clear();
|
||||||
|
prefsWriter.apply();
|
||||||
|
cookies.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean remove(URI uri, HttpCookie cookie) {
|
||||||
|
String name = getCookieToken(uri, cookie);
|
||||||
|
|
||||||
|
if (cookies.containsKey(uri.getHost()) && cookies.get(uri.getHost()).containsKey(name)) {
|
||||||
|
cookies.get(uri.getHost()).remove(name);
|
||||||
|
|
||||||
|
SharedPreferences.Editor prefsWriter = cookiePrefs.edit();
|
||||||
|
if (cookiePrefs.contains(COOKIE_NAME_PREFIX + name)) {
|
||||||
|
prefsWriter.remove(COOKIE_NAME_PREFIX + name);
|
||||||
|
}
|
||||||
|
prefsWriter.putString(uri.getHost(), TextUtils.join(",", cookies.get(uri.getHost()).keySet()));
|
||||||
|
prefsWriter.apply();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<HttpCookie> getCookies() {
|
||||||
|
ArrayList<HttpCookie> ret = new ArrayList<>();
|
||||||
|
for (String key : cookies.keySet())
|
||||||
|
ret.addAll(cookies.get(key).values());
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<URI> getURIs() {
|
||||||
|
ArrayList<URI> ret = new ArrayList<>();
|
||||||
|
for (String key : cookies.keySet())
|
||||||
|
try {
|
||||||
|
ret.add(new URI(key));
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Serializes Cookie object into String
|
||||||
|
*
|
||||||
|
* @param cookie cookie to be encoded, can be null
|
||||||
|
* @return cookie encoded as String
|
||||||
|
*/
|
||||||
|
protected String encodeCookie(SerializableHttpCookie cookie) {
|
||||||
|
if (cookie == null)
|
||||||
|
return null;
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
ObjectOutputStream outputStream = new ObjectOutputStream(os);
|
||||||
|
outputStream.writeObject(cookie);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.d(LOG_TAG, "IOException in encodeCookie", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return byteArrayToHexString(os.toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns cookie decoded from cookie string
|
||||||
|
*
|
||||||
|
* @param cookieString string of cookie as returned from http request
|
||||||
|
* @return decoded cookie or null if exception occured
|
||||||
|
*/
|
||||||
|
protected HttpCookie decodeCookie(String cookieString) {
|
||||||
|
byte[] bytes = hexStringToByteArray(cookieString);
|
||||||
|
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
|
||||||
|
HttpCookie cookie = null;
|
||||||
|
try {
|
||||||
|
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
|
||||||
|
cookie = ((SerializableHttpCookie) objectInputStream.readObject()).getCookie();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.d(LOG_TAG, "IOException in decodeCookie", e);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
Log.d(LOG_TAG, "ClassNotFoundException in decodeCookie", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Using some super basic byte array <-> hex conversions so we don't have to rely on any
|
||||||
|
* large Base64 libraries. Can be overridden if you like!
|
||||||
|
*
|
||||||
|
* @param bytes byte array to be converted
|
||||||
|
* @return string containing hex values
|
||||||
|
*/
|
||||||
|
protected String byteArrayToHexString(byte[] bytes) {
|
||||||
|
StringBuilder sb = new StringBuilder(bytes.length * 2);
|
||||||
|
for (byte element : bytes) {
|
||||||
|
int v = element & 0xff;
|
||||||
|
if (v < 16) {
|
||||||
|
sb.append('0');
|
||||||
|
}
|
||||||
|
sb.append(Integer.toHexString(v));
|
||||||
|
}
|
||||||
|
return sb.toString().toUpperCase(Locale.US);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts hex values from strings to byte arra
|
||||||
|
*
|
||||||
|
* @param hexString string of hex-encoded values
|
||||||
|
* @return decoded byte array
|
||||||
|
*/
|
||||||
|
protected byte[] hexStringToByteArray(String hexString) {
|
||||||
|
int len = hexString.length();
|
||||||
|
byte[] data = new byte[len / 2];
|
||||||
|
for (int i = 0; i < len; i += 2) {
|
||||||
|
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i + 1), 16));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
package com.sismics.docs.resource.cookie;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.net.HttpCookie;
|
||||||
|
|
||||||
|
public class SerializableHttpCookie implements Serializable {
|
||||||
|
private static final long serialVersionUID = 6374381323722046732L;
|
||||||
|
|
||||||
|
private transient final HttpCookie cookie;
|
||||||
|
private transient HttpCookie clientCookie;
|
||||||
|
|
||||||
|
public SerializableHttpCookie(HttpCookie cookie) {
|
||||||
|
this.cookie = cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpCookie getCookie() {
|
||||||
|
HttpCookie bestCookie = cookie;
|
||||||
|
if (clientCookie != null) {
|
||||||
|
bestCookie = clientCookie;
|
||||||
|
}
|
||||||
|
return bestCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||||
|
out.writeObject(cookie.getName());
|
||||||
|
out.writeObject(cookie.getValue());
|
||||||
|
out.writeObject(cookie.getComment());
|
||||||
|
out.writeObject(cookie.getCommentURL());
|
||||||
|
out.writeObject(cookie.getDomain());
|
||||||
|
out.writeLong(cookie.getMaxAge());
|
||||||
|
out.writeObject(cookie.getPath());
|
||||||
|
out.writeObject(cookie.getPortlist());
|
||||||
|
out.writeInt(cookie.getVersion());
|
||||||
|
out.writeBoolean(cookie.getSecure());
|
||||||
|
out.writeBoolean(cookie.getDiscard());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||||
|
String name = (String) in.readObject();
|
||||||
|
String value = (String) in.readObject();
|
||||||
|
clientCookie = new HttpCookie(name, value);
|
||||||
|
clientCookie.setComment((String) in.readObject());
|
||||||
|
clientCookie.setCommentURL((String) in.readObject());
|
||||||
|
clientCookie.setDomain((String) in.readObject());
|
||||||
|
clientCookie.setMaxAge(in.readLong());
|
||||||
|
clientCookie.setPath((String) in.readObject());
|
||||||
|
clientCookie.setPortlist((String) in.readObject());
|
||||||
|
clientCookie.setVersion(in.readInt());
|
||||||
|
clientCookie.setSecure(in.readBoolean());
|
||||||
|
clientCookie.setDiscard(in.readBoolean());
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
package com.sismics.docs.service;
|
package com.sismics.docs.service;
|
||||||
|
|
||||||
import android.app.IntentService;
|
import android.app.IntentService;
|
||||||
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v4.app.NotificationCompat.Builder;
|
import android.support.v4.app.NotificationCompat.Builder;
|
||||||
@ -12,16 +14,16 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.sismics.docs.R;
|
import com.sismics.docs.R;
|
||||||
import com.sismics.docs.event.FileAddEvent;
|
import com.sismics.docs.event.FileAddEvent;
|
||||||
import com.sismics.docs.listener.JsonHttpResponseHandler;
|
import com.sismics.docs.listener.HttpCallback;
|
||||||
import com.sismics.docs.resource.FileResource;
|
import com.sismics.docs.resource.FileResource;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.greenrobot.eventbus.EventBus;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
import okhttp3.internal.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to upload a file to a document in the background.
|
* Service to upload a file to a document in the background.
|
||||||
@ -29,7 +31,8 @@ import de.greenrobot.event.EventBus;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
public class FileUploadService extends IntentService {
|
public class FileUploadService extends IntentService {
|
||||||
private static final String TAG = "FileUploadService";
|
private static final String TAG = "sismicsdocs:fileupload";
|
||||||
|
private static final String CHANNEL_ID = "FileUploadService";
|
||||||
|
|
||||||
private static final int UPLOAD_NOTIFICATION_ID = 1;
|
private static final int UPLOAD_NOTIFICATION_ID = 1;
|
||||||
private static final int UPLOAD_NOTIFICATION_ID_DONE = 2;
|
private static final int UPLOAD_NOTIFICATION_ID_DONE = 2;
|
||||||
@ -49,18 +52,30 @@ public class FileUploadService extends IntentService {
|
|||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||||
notification = new NotificationCompat.Builder(this);
|
initChannels();
|
||||||
|
notification = new NotificationCompat.Builder(this, CHANNEL_ID);
|
||||||
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
|
||||||
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initChannels() {
|
||||||
|
if (Build.VERSION.SDK_INT < 26) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
|
||||||
|
"File Upload", NotificationManager.IMPORTANCE_HIGH);
|
||||||
|
channel.setDescription("Used to show file upload progress");
|
||||||
|
notificationManager.createNotificationChannel(channel);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onHandleIntent(Intent intent) {
|
protected void onHandleIntent(Intent intent) {
|
||||||
if (intent == null) {
|
if (intent == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wakeLock.acquire();
|
wakeLock.acquire(60_000 * 30); // 30 minutes upload time maximum
|
||||||
try {
|
try {
|
||||||
onStart();
|
onStart();
|
||||||
handleFileUpload(intent.getStringExtra(PARAM_DOCUMENT_ID), (Uri) intent.getParcelableExtra(PARAM_URI));
|
handleFileUpload(intent.getStringExtra(PARAM_DOCUMENT_ID), (Uri) intent.getParcelableExtra(PARAM_URI));
|
||||||
@ -77,21 +92,26 @@ public class FileUploadService extends IntentService {
|
|||||||
*
|
*
|
||||||
* @param documentId Document ID
|
* @param documentId Document ID
|
||||||
* @param uri Data URI
|
* @param uri Data URI
|
||||||
* @throws IOException
|
* @throws IOException e
|
||||||
*/
|
*/
|
||||||
private void handleFileUpload(final String documentId, final Uri uri) throws Exception {
|
private void handleFileUpload(final String documentId, final Uri uri) throws Exception {
|
||||||
final InputStream is = getContentResolver().openInputStream(uri);
|
final InputStream is = getContentResolver().openInputStream(uri);
|
||||||
FileResource.addSync(this, documentId, is, new JsonHttpResponseHandler() {
|
FileResource.addSync(this, documentId, is, new HttpCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
|
public void onSuccess(JSONObject response) {
|
||||||
EventBus.getDefault().post(new FileAddEvent(documentId, response.optString("id")));
|
EventBus.getDefault().post(new FileAddEvent(documentId, response.optString("id")));
|
||||||
FileUploadService.this.onComplete();
|
FileUploadService.this.onComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAllFailure(int statusCode, Header[] headers, byte[] responseBytes, Throwable throwable) {
|
public void onFailure(JSONObject json, Exception e) {
|
||||||
FileUploadService.this.onError();
|
FileUploadService.this.onError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFinish() {
|
||||||
|
Util.closeQuietly(is);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,47 @@
|
|||||||
|
package com.sismics.docs.ui;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
import android.support.design.widget.AppBarLayout;
|
||||||
|
import android.support.design.widget.CoordinatorLayout;
|
||||||
|
import android.support.design.widget.FloatingActionButton;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import com.sismics.docs.R;
|
||||||
|
|
||||||
|
public class ScrollingFABBehavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
|
||||||
|
private int toolbarHeight;
|
||||||
|
|
||||||
|
public ScrollingFABBehavior(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
this.toolbarHeight = getToolbarHeight(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean layoutDependsOn(@NonNull CoordinatorLayout parent, @NonNull FloatingActionButton fab, @NonNull View dependency) {
|
||||||
|
return dependency instanceof AppBarLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onDependentViewChanged(@NonNull CoordinatorLayout parent, @NonNull FloatingActionButton fab, @NonNull View dependency) {
|
||||||
|
if (dependency instanceof AppBarLayout) {
|
||||||
|
CoordinatorLayout.LayoutParams lp = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
|
||||||
|
int fabBottomMargin = lp.bottomMargin;
|
||||||
|
int distanceToScroll = fab.getHeight() + fabBottomMargin;
|
||||||
|
float ratio = dependency.getY() /(float) toolbarHeight;
|
||||||
|
fab.setTranslationY(- distanceToScroll * ratio);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getToolbarHeight(Context context) {
|
||||||
|
final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes(
|
||||||
|
new int[] { R.attr.actionBarSize });
|
||||||
|
int toolbarHeight = (int) styledAttributes.getDimension(0, 0);
|
||||||
|
styledAttributes.recycle();
|
||||||
|
|
||||||
|
return toolbarHeight;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
package com.sismics.docs.ui.view;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ListView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Non-scrollable ListView.
|
||||||
|
* All items are visible from the start.
|
||||||
|
*
|
||||||
|
* @author http://stackoverflow.com/questions/18813296/non-scrollable-listview-inside-scrollview/24629341#24629341
|
||||||
|
*/
|
||||||
|
public class NonScrollListView extends ListView {
|
||||||
|
|
||||||
|
public NonScrollListView(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
public NonScrollListView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
public NonScrollListView(Context context, AttributeSet attrs, int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||||
|
int heightMeasureSpec_custom = MeasureSpec.makeMeasureSpec(
|
||||||
|
Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec_custom);
|
||||||
|
ViewGroup.LayoutParams params = getLayoutParams();
|
||||||
|
params.height = getMeasuredHeight();
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
public class ApplicationUtil {
|
public class ApplicationUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns version name.
|
* Returns version name.
|
||||||
*
|
*
|
||||||
|
@ -12,7 +12,6 @@ import com.sismics.docs.R;
|
|||||||
* @author bgamard
|
* @author bgamard
|
||||||
*/
|
*/
|
||||||
public class DialogUtil {
|
public class DialogUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a dialog with an OK button.
|
* Create a dialog with an OK button.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.sismics.docs.util;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.DownloadManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.support.v4.app.ActivityCompat;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for network actions.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class NetworkUtil {
|
||||||
|
/**
|
||||||
|
* Download a file using Android download manager.
|
||||||
|
*
|
||||||
|
* @param url URL to download
|
||||||
|
* @param fileName Destination file name
|
||||||
|
* @param title Notification title
|
||||||
|
* @param description Notification description
|
||||||
|
*/
|
||||||
|
public static void downloadFile(Activity activity, String url, String fileName, String title, String description) {
|
||||||
|
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
ActivityCompat.requestPermissions(activity, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String authToken = PreferenceUtil.getAuthToken(activity);
|
||||||
|
DownloadManager downloadManager = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||||
|
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
|
||||||
|
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||||
|
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
|
||||||
|
request.addRequestHeader("Cookie", "auth_token=" + authToken);
|
||||||
|
request.setTitle(title);
|
||||||
|
request.setDescription(description);
|
||||||
|
downloadManager.enqueue(request);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,187 @@
|
|||||||
|
package com.sismics.docs.util;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.jakewharton.picasso.OkHttp3Downloader;
|
||||||
|
import com.sismics.docs.resource.cookie.PersistentCookieStore;
|
||||||
|
import com.squareup.picasso.Picasso;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.CookieManager;
|
||||||
|
import java.net.CookiePolicy;
|
||||||
|
import java.security.cert.CertificateException;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.net.ssl.TrustManager;
|
||||||
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import okhttp3.Cache;
|
||||||
|
import okhttp3.Interceptor;
|
||||||
|
import okhttp3.JavaNetCookieJar;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities for OkHttp.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class OkHttpUtil {
|
||||||
|
/**
|
||||||
|
* OkHttp singleton client.
|
||||||
|
*/
|
||||||
|
private static OkHttpClient okHttpClient = new OkHttpClient();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton cache.
|
||||||
|
*/
|
||||||
|
private static Cache cache = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User-Agent to use.
|
||||||
|
*/
|
||||||
|
protected static String userAgent = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept-Language header.
|
||||||
|
*/
|
||||||
|
protected static String acceptLanguage = null;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// OkHttp configuration
|
||||||
|
try {
|
||||||
|
// Create a trust manager that does not validate certificate chains
|
||||||
|
final TrustManager[] trustAllCerts = new TrustManager[] {
|
||||||
|
new X509TrustManager() {
|
||||||
|
@Override
|
||||||
|
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Install the all-trusting trust manager
|
||||||
|
final SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||||
|
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
|
||||||
|
final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
|
||||||
|
|
||||||
|
// Configure OkHttpClient
|
||||||
|
okHttpClient = okHttpClient.newBuilder()
|
||||||
|
.connectTimeout(30, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(30, TimeUnit.SECONDS)
|
||||||
|
.writeTimeout(30, TimeUnit.SECONDS)
|
||||||
|
.sslSocketFactory(sslSocketFactory)
|
||||||
|
.build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// NOP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a Picasso object with base config.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @return Picasso object
|
||||||
|
*/
|
||||||
|
public static Picasso picasso(Context context) {
|
||||||
|
OkHttpClient okHttpClient = buildClient(context)
|
||||||
|
.newBuilder()
|
||||||
|
.addInterceptor(new Interceptor() {
|
||||||
|
@Override
|
||||||
|
public Response intercept(Interceptor.Chain chain) throws IOException { // Override cache configuration
|
||||||
|
final Request original = chain.request();
|
||||||
|
return chain.proceed(original.newBuilder()
|
||||||
|
.header("Cache-Control", "max-age=" + (3600 * 24 * 365))
|
||||||
|
.method(original.method(), original.body())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.cache(getCache(context))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Picasso picasso = new Picasso.Builder(context)
|
||||||
|
.downloader(new OkHttp3Downloader(okHttpClient))
|
||||||
|
.build();
|
||||||
|
picasso.setIndicatorsEnabled(false); // Debug stuff
|
||||||
|
return picasso;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get and eventually build the singleton cache.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @return Cache
|
||||||
|
*/
|
||||||
|
private static Cache getCache(Context context) {
|
||||||
|
if (cache == null) {
|
||||||
|
cache = new Cache(context.getCacheDir(),
|
||||||
|
PreferenceUtil.getIntegerPreference(context, PreferenceUtil.PREF_CACHE_SIZE, 0) * 1000000);
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the HTTP cache.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
*/
|
||||||
|
public static void clearCache(Context context) {
|
||||||
|
Cache cache = getCache(context);
|
||||||
|
try {
|
||||||
|
cache.evictAll();
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e("OKHttpUtil", "Error clearing cache", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build an OkHttpClient.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
* @return OkHttpClient
|
||||||
|
*/
|
||||||
|
public static OkHttpClient buildClient(final Context context) {
|
||||||
|
// One-time header computation
|
||||||
|
if (userAgent == null) {
|
||||||
|
userAgent = "Teedy Android " + ApplicationUtil.getVersionName(context) + "/Android " + Build.VERSION.RELEASE + "/" + Build.MODEL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acceptLanguage == null) {
|
||||||
|
Locale locale = Locale.getDefault();
|
||||||
|
acceptLanguage = locale.getLanguage() + "_" + locale.getCountry();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cookie handling
|
||||||
|
PersistentCookieStore cookieStore = new PersistentCookieStore(context);
|
||||||
|
CookieManager cookieManager = new CookieManager(cookieStore, CookiePolicy.ACCEPT_ALL);
|
||||||
|
|
||||||
|
// Runtime configuration
|
||||||
|
return okHttpClient.newBuilder()
|
||||||
|
.cookieJar(new JavaNetCookieJar(cookieManager))
|
||||||
|
.addNetworkInterceptor(new Interceptor() {
|
||||||
|
@Override
|
||||||
|
public Response intercept(Chain chain) throws IOException {
|
||||||
|
Request original = chain.request();
|
||||||
|
return chain.proceed(original.newBuilder()
|
||||||
|
.header("User-Agent", userAgent)
|
||||||
|
.header("Accept-Language", acceptLanguage)
|
||||||
|
.method(original.method(), original.body())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -5,11 +5,11 @@ import android.content.SharedPreferences;
|
|||||||
import android.content.SharedPreferences.Editor;
|
import android.content.SharedPreferences.Editor;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.loopj.android.http.PersistentCookieStore;
|
import com.sismics.docs.resource.cookie.PersistentCookieStore;
|
||||||
|
|
||||||
import org.apache.http.cookie.Cookie;
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.net.HttpCookie;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,6 +26,7 @@ public class PreferenceUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a preference of boolean type.
|
* Returns a preference of boolean type.
|
||||||
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param key Shared preference key
|
* @param key Shared preference key
|
||||||
* @return Shared preference value
|
* @return Shared preference value
|
||||||
@ -37,6 +38,7 @@ public class PreferenceUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a preference of string type.
|
* Returns a preference of string type.
|
||||||
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param key Shared preference key
|
* @param key Shared preference key
|
||||||
* @return Shared preference value
|
* @return Shared preference value
|
||||||
@ -48,6 +50,7 @@ public class PreferenceUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a preference of integer type.
|
* Returns a preference of integer type.
|
||||||
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param key Shared preference key
|
* @param key Shared preference key
|
||||||
* @return Shared preference value
|
* @return Shared preference value
|
||||||
@ -69,6 +72,7 @@ public class PreferenceUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Update JSON cache.
|
* Update JSON cache.
|
||||||
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param key Shared preference key
|
* @param key Shared preference key
|
||||||
* @param json JSON data
|
* @param json JSON data
|
||||||
@ -80,6 +84,7 @@ public class PreferenceUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a JSON cache.
|
* Returns a JSON cache.
|
||||||
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @param key Shared preference key
|
* @param key Shared preference key
|
||||||
* @return JSON data
|
* @return JSON data
|
||||||
@ -96,6 +101,7 @@ public class PreferenceUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Update server URL.
|
* Update server URL.
|
||||||
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
*/
|
*/
|
||||||
public static void setServerUrl(Context context, String serverUrl) {
|
public static void setServerUrl(Context context, String serverUrl) {
|
||||||
@ -105,6 +111,7 @@ public class PreferenceUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty user caches.
|
* Empty user caches.
|
||||||
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
*/
|
*/
|
||||||
public static void resetUserCache(Context context) {
|
public static void resetUserCache(Context context) {
|
||||||
@ -118,12 +125,14 @@ public class PreferenceUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns auth token cookie from shared preferences.
|
* Returns auth token cookie from shared preferences.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
* @return Auth token
|
* @return Auth token
|
||||||
*/
|
*/
|
||||||
public static String getAuthToken(Context context) {
|
public static String getAuthToken(Context context) {
|
||||||
PersistentCookieStore cookieStore = new PersistentCookieStore(context);
|
PersistentCookieStore cookieStore = new PersistentCookieStore(context);
|
||||||
List<Cookie> cookieList = cookieStore.getCookies();
|
List<HttpCookie> cookieList = cookieStore.getCookies();
|
||||||
for (Cookie cookie : cookieList) {
|
for (HttpCookie cookie : cookieList) {
|
||||||
if (cookie.getName().equals("auth_token")) {
|
if (cookie.getName().equals("auth_token")) {
|
||||||
return cookie.getValue();
|
return cookie.getValue();
|
||||||
}
|
}
|
||||||
@ -132,8 +141,19 @@ public class PreferenceUtil {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all auth tokens.
|
||||||
|
*
|
||||||
|
* @param context Context
|
||||||
|
*/
|
||||||
|
public static void clearAuthToken(Context context) {
|
||||||
|
PersistentCookieStore cookieStore = new PersistentCookieStore(context);
|
||||||
|
cookieStore.removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns cleaned server URL.
|
* Returns cleaned server URL.
|
||||||
|
*
|
||||||
* @param context Context
|
* @param context Context
|
||||||
* @return Server URL
|
* @return Server URL
|
||||||
*/
|
*/
|
||||||
|
@ -39,7 +39,9 @@ public class SearchQueryBuilder {
|
|||||||
*/
|
*/
|
||||||
public SearchQueryBuilder simpleSearch(String simpleSearch) {
|
public SearchQueryBuilder simpleSearch(String simpleSearch) {
|
||||||
if (isValid(simpleSearch)) {
|
if (isValid(simpleSearch)) {
|
||||||
query.append(SEARCH_SEPARATOR).append(simpleSearch);
|
query.append(SEARCH_SEPARATOR)
|
||||||
|
.append("simple:")
|
||||||
|
.append(simpleSearch);
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -59,6 +61,21 @@ public class SearchQueryBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a creator criteria.
|
||||||
|
*
|
||||||
|
* @param creator Creator criteria
|
||||||
|
* @return The builder
|
||||||
|
*/
|
||||||
|
public SearchQueryBuilder creator(String creator) {
|
||||||
|
if (isValid(creator)) {
|
||||||
|
query.append(SEARCH_SEPARATOR)
|
||||||
|
.append("by:")
|
||||||
|
.append(creator);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a language criteria.
|
* Add a language criteria.
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,85 @@
|
|||||||
|
package com.sismics.docs.util;
|
||||||
|
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.text.Spannable;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.style.BackgroundColorSpan;
|
||||||
|
import android.text.style.ForegroundColorSpan;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for spannable.
|
||||||
|
*
|
||||||
|
* @author bgamard.
|
||||||
|
*/
|
||||||
|
public class SpannableUtil {
|
||||||
|
/**
|
||||||
|
* Create a colored spannable from tags.
|
||||||
|
*
|
||||||
|
* @param tags Tags
|
||||||
|
* @return Colored spannable
|
||||||
|
*/
|
||||||
|
public static Spannable buildSpannableTags(JSONArray tags) {
|
||||||
|
return buildSpannable(tags, "name", "color");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a spannable for contributors.
|
||||||
|
*
|
||||||
|
* @param contributors Contributors
|
||||||
|
* @return Spannable
|
||||||
|
*/
|
||||||
|
public static Spannable buildSpannableContributors(JSONArray contributors) {
|
||||||
|
return buildSpannable(contributors, "username", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a spannable for relations.
|
||||||
|
*
|
||||||
|
* @param relations Relations
|
||||||
|
* @return Spannable
|
||||||
|
*/
|
||||||
|
public static Spannable buildSpannableRelations(JSONArray relations) {
|
||||||
|
return buildSpannable(relations, "title", null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a spannable from a JSONArray.
|
||||||
|
*
|
||||||
|
* @param array JSONArray
|
||||||
|
* @param valueName Name of the value part
|
||||||
|
* @param colorName Name of the color part (optional)
|
||||||
|
* @return Spannable
|
||||||
|
*/
|
||||||
|
private static Spannable buildSpannable(JSONArray array, String valueName, String colorName) {
|
||||||
|
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < array.length(); i++) {
|
||||||
|
final JSONObject tag = array.optJSONObject(i);
|
||||||
|
int start = builder.length();
|
||||||
|
builder.append(" ").append(tag.optString(valueName)).append(" ");
|
||||||
|
builder.setSpan(new ForegroundColorSpan(Color.WHITE), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
builder.setSpan(new BackgroundColorSpan(Color.parseColor(tag.optString(colorName, "#5bc0de"))), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
/*
|
||||||
|
TODO : Make tags, relations and contributors clickable
|
||||||
|
builder.setSpan(new ClickableSpan() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View widget) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateDrawState(TextPaint ds) {
|
||||||
|
super.updateDrawState(ds);
|
||||||
|
ds.setColor(Color.WHITE);
|
||||||
|
ds.setUnderlineText(false);
|
||||||
|
}
|
||||||
|
}, start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);*/
|
||||||
|
builder.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
@ -1,39 +0,0 @@
|
|||||||
package com.sismics.docs.util;
|
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.text.Spannable;
|
|
||||||
import android.text.SpannableStringBuilder;
|
|
||||||
import android.text.Spanned;
|
|
||||||
import android.text.style.BackgroundColorSpan;
|
|
||||||
import android.text.style.ForegroundColorSpan;
|
|
||||||
|
|
||||||
import org.json.JSONArray;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class for tags.
|
|
||||||
*
|
|
||||||
* @author bgamard.
|
|
||||||
*/
|
|
||||||
public class TagUtil {
|
|
||||||
/**
|
|
||||||
* Create a colored spannable from tags.
|
|
||||||
*
|
|
||||||
* @param tags Tags
|
|
||||||
* @return Colored spannable
|
|
||||||
*/
|
|
||||||
public static Spannable buildSpannable(JSONArray tags) {
|
|
||||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
|
||||||
|
|
||||||
for (int i = 0; i < tags.length(); i++) {
|
|
||||||
JSONObject tag = tags.optJSONObject(i);
|
|
||||||
int start = builder.length();
|
|
||||||
builder.append(" ").append(tag.optString("name")).append(" ");
|
|
||||||
builder.setSpan(new ForegroundColorSpan(Color.WHITE), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
||||||
builder.setSpan(new BackgroundColorSpan(Color.parseColor(tag.optString("color"))), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
||||||
builder.append(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
|
BIN
docs-android/app/src/main/res/drawable-xhdpi/deu.png
Normal file
After Width: | Height: | Size: 9.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 353 B |
After Width: | Height: | Size: 448 B |
Before Width: | Height: | Size: 558 B |
BIN
docs-android/app/src/main/res/drawable-xhdpi/pol.png
Normal file
After Width: | Height: | Size: 238 B |
BIN
docs-android/app/src/main/res/drawable-xxhdpi/deu.png
Normal file
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 461 B |
After Width: | Height: | Size: 565 B |
Before Width: | Height: | Size: 813 B |
30
docs-android/app/src/main/res/layout/auditlog_activity.xml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.v4.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/swipeRefreshLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:id="@+id/auditLogListView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:choiceMode="singleChoice"
|
||||||
|
android:dividerHeight="0dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
</ListView>
|
||||||
|
</android.support.v4.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
60
docs-android/app/src/main/res/layout/auditlog_list_item.xml
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/assignImageView"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_assignment_grey600_48dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/usernameTextView"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_toRightOf="@+id/assignImageView"
|
||||||
|
android:layout_toEndOf="@+id/assignImageView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:textColor="#212121"
|
||||||
|
android:text="admin"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/messageTextView"
|
||||||
|
android:layout_below="@+id/usernameTextView"
|
||||||
|
android:layout_toRightOf="@+id/assignImageView"
|
||||||
|
android:layout_toEndOf="@+id/assignImageView"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:textColor="#777777"
|
||||||
|
android:text="Document created : test doc 1"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:ellipsize="end"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dateTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="2014-12-02"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:textColor="#777777"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
57
docs-android/app/src/main/res/layout/comment_list_item.xml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/gravatarImageView"
|
||||||
|
android:layout_width="32dp"
|
||||||
|
android:layout_height="32dp"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_marginRight="12dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/creatorTextView"
|
||||||
|
android:layout_toRightOf="@id/gravatarImageView"
|
||||||
|
android:layout_toEndOf="@id/gravatarImageView"
|
||||||
|
android:layout_alignParentTop="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="#212121"
|
||||||
|
android:text="Creator"
|
||||||
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/contentTextView"
|
||||||
|
android:layout_toRightOf="@id/gravatarImageView"
|
||||||
|
android:layout_toEndOf="@id/gravatarImageView"
|
||||||
|
android:layout_below="@id/creatorTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:textColor="#212121"
|
||||||
|
android:text="Comment content"
|
||||||
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/dateTextView"
|
||||||
|
android:layout_toRightOf="@id/gravatarImageView"
|
||||||
|
android:layout_toEndOf="@id/gravatarImageView"
|
||||||
|
android:layout_below="@id/contentTextView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:textColor="#888"
|
||||||
|
android:text="2015-11-10"
|
||||||
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -1,6 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
@ -37,17 +36,4 @@
|
|||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:layout_centerInParent="true"/>
|
android:layout_centerInParent="true"/>
|
||||||
|
|
||||||
<com.shamanland.fab.FloatingActionButton
|
|
||||||
android:id="@+id/addDocumentButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentBottom="true"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
android:layout_marginBottom="20dp"
|
|
||||||
android:src="@drawable/ic_add_white_24dp"
|
|
||||||
app:floatingActionButtonColor="#263238"/>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
@ -13,6 +13,7 @@
|
|||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_marginRight="12dp"
|
android:layout_marginRight="12dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
android:id="@+id/folderImageView"
|
android:id="@+id/folderImageView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -22,11 +23,13 @@
|
|||||||
android:id="@+id/titleTextView"
|
android:id="@+id/titleTextView"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_toRightOf="@+id/folderImageView"
|
android:layout_toRightOf="@+id/folderImageView"
|
||||||
|
android:layout_toEndOf="@+id/folderImageView"
|
||||||
android:layout_toLeftOf="@+id/dateTextView"
|
android:layout_toLeftOf="@+id/dateTextView"
|
||||||
|
android:layout_toStartOf="@+id/dateTextView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="sans-serif-light"
|
android:fontFamily="sans-serif-light"
|
||||||
android:textColor="#212121"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:text="Test"
|
android:text="Test"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
@ -43,7 +46,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fontFamily="sans-serif-light"
|
android:fontFamily="sans-serif-light"
|
||||||
android:textColor="#777777"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:text="test2"
|
android:text="test2"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
@ -66,7 +69,7 @@
|
|||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:textColor="#777777"
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
android:fontFamily="sans-serif-light"/>
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="12dp">
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="6dp"
|
||||||
|
android:text="@string/export_metadata"
|
||||||
|
android:id="@+id/exportMetadataCheckbox" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="6dp"
|
||||||
|
android:text="@string/export_comments"
|
||||||
|
android:id="@+id/exportCommentsCheckbox" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="6dp"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/fit_image_to_page"
|
||||||
|
android:id="@+id/fitToPageCheckbox" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/margin"
|
||||||
|
android:layout_weight="0"/>
|
||||||
|
|
||||||
|
<SeekBar
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:id="@+id/marginSeekBar"
|
||||||
|
android:progress="10"
|
||||||
|
android:max="50"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/marginValueText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:text="10"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="4dp"
|
||||||
|
android:layout_marginStart="4dp"
|
||||||
|
android:layout_weight="0"
|
||||||
|
android:text="@string/mm"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
@ -37,18 +37,125 @@
|
|||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<!-- Right drawer -->
|
<!-- Left drawer -->
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/right_drawer"
|
android:id="@+id/left_drawer"
|
||||||
android:layout_width="300dp"
|
android:layout_width="300dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="end"
|
android:layout_gravity="start"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:background="#fff"
|
android:background="#fff"
|
||||||
android:elevation="5dp">
|
android:elevation="5dp">
|
||||||
|
|
||||||
|
<!-- Comments -->
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:drawableStart="@drawable/ic_comment_grey600_24dp"
|
||||||
|
android:drawableLeft="@drawable/ic_comment_grey600_24dp"
|
||||||
|
android:drawablePadding="6dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="#de000000"
|
||||||
|
android:text="@string/comments"
|
||||||
|
android:layout_margin="12dp"/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#eee"/>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:id="@+id/commentListView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:choiceMode="singleChoice"
|
||||||
|
android:divider="@android:color/transparent"
|
||||||
|
android:transcriptMode="normal"
|
||||||
|
android:dividerHeight="0dp"/>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:id="@+id/commentProgressView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
style="?android:progressBarStyle"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:indeterminate="true"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/commentEmptyView"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/no_comments"
|
||||||
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#eee"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="6dp"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/commentEditText"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:lines="1"
|
||||||
|
android:inputType="text"
|
||||||
|
android:hint="@string/add_comment"
|
||||||
|
android:maxLength="4000"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/addCommentBtn"
|
||||||
|
android:layout_width="48dp"
|
||||||
|
android:layout_height="48dp"
|
||||||
|
android:src="@drawable/ic_send_grey600_24dp"
|
||||||
|
android:contentDescription="@string/send"
|
||||||
|
android:background="?android:selectableItemBackground"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Right drawer -->
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@+id/right_drawer"
|
||||||
|
android:layout_width="300dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clickable="true"
|
||||||
|
android:background="#fff"
|
||||||
|
android:elevation="5dp"
|
||||||
|
android:layout_gravity="end">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<!-- Actions -->
|
<!-- Actions -->
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@ -63,28 +170,6 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
style="?android:buttonBarStyle">
|
style="?android:buttonBarStyle">
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/actionEditDocument"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:drawableTop="@drawable/ic_create_grey600_24dp"
|
|
||||||
style="?android:buttonBarButtonStyle"
|
|
||||||
android:text="@string/edit_document"
|
|
||||||
android:textColor="@color/button_material_dark"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:layout_margin="8dp"/>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/actionUploadFile"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:drawableTop="@drawable/ic_file_upload_grey600_24dp"
|
|
||||||
style="?android:buttonBarButtonStyle"
|
|
||||||
android:text="@string/upload_file"
|
|
||||||
android:textColor="@color/button_material_dark"
|
|
||||||
android:textAllCaps="false"
|
|
||||||
android:layout_margin="8dp"/>
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/actionDownload"
|
android:id="@+id/actionDownload"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -92,7 +177,29 @@
|
|||||||
android:drawableTop="@drawable/ic_file_download_grey600_24dp"
|
android:drawableTop="@drawable/ic_file_download_grey600_24dp"
|
||||||
style="?android:buttonBarButtonStyle"
|
style="?android:buttonBarButtonStyle"
|
||||||
android:text="@string/download_document"
|
android:text="@string/download_document"
|
||||||
android:textColor="@color/button_material_dark"
|
android:textColor="#ff5a595b"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:layout_margin="8dp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/actionExportPdf"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableTop="@drawable/ic_description_grey600_24dp"
|
||||||
|
style="?android:buttonBarButtonStyle"
|
||||||
|
android:text="@string/export_pdf"
|
||||||
|
android:textColor="#ff5a595b"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:layout_margin="8dp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/actionAuditLog"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableTop="@drawable/ic_assignment_grey600_24dp"
|
||||||
|
style="?android:buttonBarButtonStyle"
|
||||||
|
android:text="@string/activity"
|
||||||
|
android:textColor="#ff5a595b"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:layout_margin="8dp"/>
|
android:layout_margin="8dp"/>
|
||||||
|
|
||||||
@ -104,6 +211,28 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
style="?android:buttonBarStyle">
|
style="?android:buttonBarStyle">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/actionEditDocument"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableTop="@drawable/ic_create_grey600_24dp"
|
||||||
|
style="?android:buttonBarButtonStyle"
|
||||||
|
android:text="@string/edit_document"
|
||||||
|
android:textColor="#ff5a595b"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:layout_margin="0dp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/actionUploadFile"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableTop="@drawable/ic_file_upload_grey600_24dp"
|
||||||
|
style="?android:buttonBarButtonStyle"
|
||||||
|
android:text="@string/upload_file"
|
||||||
|
android:textColor="#ff5a595b"
|
||||||
|
android:textAllCaps="false"
|
||||||
|
android:layout_margin="0dp"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/actionSharing"
|
android:id="@+id/actionSharing"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -111,9 +240,9 @@
|
|||||||
android:drawableTop="@drawable/ic_share_grey600_24dp"
|
android:drawableTop="@drawable/ic_share_grey600_24dp"
|
||||||
style="?android:buttonBarButtonStyle"
|
style="?android:buttonBarButtonStyle"
|
||||||
android:text="@string/share"
|
android:text="@string/share"
|
||||||
android:textColor="@color/button_material_dark"
|
android:textColor="#ff5a595b"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:layout_margin="8dp"/>
|
android:layout_margin="0dp"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/actionDelete"
|
android:id="@+id/actionDelete"
|
||||||
@ -122,9 +251,9 @@
|
|||||||
android:drawableTop="@drawable/ic_delete_grey600_24dp"
|
android:drawableTop="@drawable/ic_delete_grey600_24dp"
|
||||||
style="?android:buttonBarButtonStyle"
|
style="?android:buttonBarButtonStyle"
|
||||||
android:text="@string/delete_document"
|
android:text="@string/delete_document"
|
||||||
android:textColor="@color/button_material_dark"
|
android:textColor="#ff5a595b"
|
||||||
android:textAllCaps="false"
|
android:textAllCaps="false"
|
||||||
android:layout_margin="8dp"/>
|
android:layout_margin="0dp"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -160,18 +289,41 @@
|
|||||||
android:id="@+id/createdDateTextView"
|
android:id="@+id/createdDateTextView"
|
||||||
android:layout_toRightOf="@id/createdDateLabel"
|
android:layout_toRightOf="@id/createdDateLabel"
|
||||||
android:layout_toEndOf="@id/createdDateLabel"
|
android:layout_toEndOf="@id/createdDateLabel"
|
||||||
|
android:layout_toLeftOf="@id/sharedImageView"
|
||||||
|
android:layout_toStartOf="@id/sharedImageView"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:fontFamily="sans-serif-light"/>
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/creatorLabel"
|
||||||
|
android:layout_width="100dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_below="@+id/createdDateLabel"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/creator"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/creatorTextView"
|
||||||
|
android:layout_toRightOf="@id/creatorLabel"
|
||||||
|
android:layout_toEndOf="@id/creatorLabel"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_below="@+id/createdDateTextView"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tagTextView"
|
android:id="@+id/tagTextView"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/createdDateLabel"
|
android:layout_below="@id/creatorLabel"
|
||||||
android:layout_marginRight="8dp"
|
android:layout_marginRight="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
@ -186,6 +338,7 @@
|
|||||||
android:fontFamily="sans-serif-light"/>
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
android:contentDescription="@string/shared"
|
||||||
android:id="@+id/sharedImageView"
|
android:id="@+id/sharedImageView"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
@ -197,6 +350,7 @@
|
|||||||
android:layout_toStartOf="@+id/languageImageView"/>
|
android:layout_toStartOf="@+id/languageImageView"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
android:contentDescription="@string/language"
|
||||||
android:id="@+id/languageImageView"
|
android:id="@+id/languageImageView"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
@ -206,6 +360,278 @@
|
|||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<!-- Additional dublincore metadata -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="12dp"
|
||||||
|
android:paddingRight="12dp"
|
||||||
|
android:paddingBottom="12dp">
|
||||||
|
|
||||||
|
<!-- Subject -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/subjectLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_weight="0.33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/subject"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/subjectTextView"
|
||||||
|
android:layout_weight="0.67"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Identifier -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/identifierLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_weight="0.33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/identifier"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/identifierTextView"
|
||||||
|
android:layout_weight="0.67"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Publisher -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/publisherLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_weight="0.33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/publisher"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/publisherTextView"
|
||||||
|
android:layout_weight="0.67"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Format -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/formatLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_weight="0.33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/format"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/formatTextView"
|
||||||
|
android:layout_weight="0.67"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Source -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/sourceLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_weight="0.33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/source"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/sourceTextView"
|
||||||
|
android:layout_weight="0.67"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Type -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/typeLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_weight="0.33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/type"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/typeTextView"
|
||||||
|
android:layout_weight="0.67"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Coverage -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/coverageLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_weight="0.33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/coverage"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/coverageTextView"
|
||||||
|
android:layout_weight="0.67"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Rights -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/rightsLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_weight="0.33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/rights"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/rightsTextView"
|
||||||
|
android:layout_weight="0.67"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Contributors -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_weight="0.33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/contributors"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/contributorsTextView"
|
||||||
|
android:layout_weight="0.67"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Relations -->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/relationsLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="2dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_weight="0.33"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:layout_marginEnd="8dp"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:text="@string/relations"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/relationsTextView"
|
||||||
|
android:layout_weight="0.67"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif-light"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
@ -219,18 +645,20 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:textColor="@color/primary_text_default_material_light"
|
android:textColor="#de000000"
|
||||||
android:text="@string/who_can_access"
|
android:text="@string/who_can_access"
|
||||||
android:layout_margin="12dp"/>
|
android:layout_margin="12dp"/>
|
||||||
|
|
||||||
<ListView
|
<com.sismics.docs.ui.view.NonScrollListView
|
||||||
android:id="@+id/aclListView"
|
android:id="@+id/aclListView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:choiceMode="singleChoice"
|
android:choiceMode="singleChoice"
|
||||||
android:divider="@android:color/transparent"
|
android:divider="@android:color/transparent"
|
||||||
android:dividerHeight="0dp"/>
|
android:dividerHeight="0dp"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
</android.support.v4.widget.DrawerLayout>
|
</android.support.v4.widget.DrawerLayout>
|
@ -9,7 +9,7 @@
|
|||||||
android:layout_width="200dp"
|
android:layout_width="200dp"
|
||||||
android:layout_height="15dip"
|
android:layout_height="15dip"
|
||||||
android:id="@+id/fileProgressBar"
|
android:id="@+id/fileProgressBar"
|
||||||
android:indeterminate="false"
|
android:indeterminate="true"
|
||||||
android:layout_centerInParent="true"/>
|
android:layout_centerInParent="true"/>
|
||||||
|
|
||||||
<it.sephiroth.android.library.imagezoom.ImageViewTouch
|
<it.sephiroth.android.library.imagezoom.ImageViewTouch
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/membersTextView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -61,6 +61,17 @@
|
|||||||
android:inputType="textPassword">
|
android:inputType="textPassword">
|
||||||
</EditText>
|
</EditText>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:visibility="gone"
|
||||||
|
android:id="@+id/txtValidationCode"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
android:ems="10"
|
||||||
|
android:hint="@string/validation_code"
|
||||||
|
android:inputType="number">
|
||||||
|
</EditText>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/btnConnect"
|
android:id="@+id/btnConnect"
|
||||||
android:layout_width="fill_parent"
|
android:layout_width="fill_parent"
|
||||||
|
@ -6,12 +6,47 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.design.widget.CoordinatorLayout
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/overview_coordinator_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<android.support.design.widget.AppBarLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
|
||||||
|
<android.support.v7.widget.Toolbar
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
app:popupTheme="@style/AppTheme"
|
||||||
|
app:layout_scrollFlags="enterAlways|scroll|snap" />
|
||||||
|
|
||||||
|
</android.support.design.widget.AppBarLayout>
|
||||||
|
|
||||||
<fragment
|
<fragment
|
||||||
android:id="@+id/main_fragment"
|
android:id="@+id/main_fragment"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||||
class="com.sismics.docs.fragment.DocListFragment"/>
|
class="com.sismics.docs.fragment.DocListFragment"/>
|
||||||
|
|
||||||
|
<android.support.design.widget.FloatingActionButton
|
||||||
|
android:id="@+id/addDocumentButton"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end|bottom"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:src="@drawable/ic_add_white_24dp"
|
||||||
|
app:layout_anchor="@id/main_fragment"
|
||||||
|
app:layout_behavior="com.sismics.docs.ui.ScrollingFABBehavior"
|
||||||
|
app:layout_anchorGravity="bottom|right|end"
|
||||||
|
app:fabSize="normal"/>
|
||||||
|
|
||||||
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/left_drawer"
|
android:id="@+id/left_drawer"
|
||||||
android:layout_width="240dp"
|
android:layout_width="240dp"
|
||||||
@ -117,6 +152,40 @@
|
|||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
|
<!-- Audit log -->
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/auditLogLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="12dp"
|
||||||
|
android:clickable="true"
|
||||||
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/auditLogImageView"
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_alignParentStart="true"
|
||||||
|
android:layout_alignParentLeft="true"
|
||||||
|
android:layout_marginRight="12dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_assignment_grey600_24dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_centerVertical="true"
|
||||||
|
android:layout_toRightOf="@+id/auditLogImageView"
|
||||||
|
android:layout_toEndOf="@+id/auditLogImageView"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:textColor="#212121"
|
||||||
|
android:text="@string/latest_activity"
|
||||||
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
<!-- Separator -->
|
<!-- Separator -->
|
||||||
|
|
||||||
<View
|
<View
|
||||||
|
@ -27,6 +27,15 @@
|
|||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:hint="@string/fulltext_search"/>
|
android:hint="@string/fulltext_search"/>
|
||||||
|
|
||||||
|
<!-- Creator -->
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/creatorEditText"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:hint="@string/creator"/>
|
||||||
|
|
||||||
<!-- Language -->
|
<!-- Language -->
|
||||||
<Spinner
|
<Spinner
|
||||||
android:id="@+id/languageSpinner"
|
android:id="@+id/languageSpinner"
|
||||||
|
@ -29,16 +29,4 @@
|
|||||||
android:text="Appartement"
|
android:text="Appartement"
|
||||||
android:textSize="14sp"/>
|
android:textSize="14sp"/>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tagCountTextView"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:fontFamily="sans-serif"
|
|
||||||
android:textColor="#888"
|
|
||||||
android:text="5"
|
|
||||||
android:textSize="14sp"/>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
@ -0,0 +1,77 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layout"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="120dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:gravity="end"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:text="@string/email"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/emailTextView"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:text="user1@sismicsdocs.com"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="120dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:gravity="end"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:text="@string/storage_quota"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/quotaTextView"
|
||||||
|
android:layout_marginLeft="12dp"
|
||||||
|
android:layout_marginStart="12dp"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:text="35/500 MB"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
@ -9,6 +9,12 @@
|
|||||||
android:title="@string/toggle_informations">
|
android:title="@string/toggle_informations">
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/comments"
|
||||||
|
app:showAsAction="collapseActionView"
|
||||||
|
android:title="@string/comments">
|
||||||
|
</item>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/download_file"
|
android:id="@+id/download_file"
|
||||||
app:showAsAction="collapseActionView"
|
app:showAsAction="collapseActionView"
|
||||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 6.3 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 9.7 KiB |
159
docs-android/app/src/main/res/values-de/strings.xml
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Validation -->
|
||||||
|
<string name="validate_error_email">Ungültige E-Mail</string>
|
||||||
|
<string name="validate_error_length_min">Zu kurz (min. %d)</string>
|
||||||
|
<string name="validate_error_length_max">Zu lang (max. %d)</string>
|
||||||
|
<string name="validate_error_required">Erforderlich</string>
|
||||||
|
<string name="validate_error_alphanumeric">Nur Buchstaben und Zahlen</string>
|
||||||
|
|
||||||
|
<!-- App -->
|
||||||
|
<string name="drawer_open">Navigationsleiste öffnen</string>
|
||||||
|
<string name="drawer_close">Navigationsleiste schließen</string>
|
||||||
|
<string name="login_explain"><![CDATA[Um zu beginnen, müssen Sie Teedy Server herunterladen und installieren <a href="https://github.com/sismics/docs">github.com/sismics/docs</a>, sowie die Login-Daten unten eingeben]]></string>
|
||||||
|
<string name="server">Server</string>
|
||||||
|
<string name="username">Username</string>
|
||||||
|
<string name="password">Password</string>
|
||||||
|
<string name="login">Login</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Abbrechen</string>
|
||||||
|
<string name="login_fail_title">Login gescheitert</string>
|
||||||
|
<string name="login_fail">Benutzername oder Passwort falsch</string>
|
||||||
|
<string name="network_error_title">Netzwerkfehler</string>
|
||||||
|
<string name="network_error">Netzwerkfehler, überprüfen Sie die Internetverbindung und die Server-URL</string>
|
||||||
|
<string name="invalid_url_title">Ungültige URL</string>
|
||||||
|
<string name="invalid_url">Bitte überprüfen Sie die Server-URL und versuchen Sie es erneut</string>
|
||||||
|
<string name="crash_toast_text">Ein Absturz ist aufgetreten, ein Bericht wurde gesendet, um dieses Problem zu beheben</string>
|
||||||
|
<string name="created_date">Erstellungsdatum</string>
|
||||||
|
<string name="download_file">Aktuelle Datei herunterladen</string>
|
||||||
|
<string name="download_document">Herunterladen</string>
|
||||||
|
<string name="action_search">Dokumente durchsuchen</string>
|
||||||
|
<string name="all_documents">Alle Dokumente</string>
|
||||||
|
<string name="shared_documents">Geteilte Dokumente</string>
|
||||||
|
<string name="all_tags">Alle Tags</string>
|
||||||
|
<string name="no_tags">Keine Tags</string>
|
||||||
|
<string name="error_loading_tags">Fehler beim Laden von Tags</string>
|
||||||
|
<string name="no_documents">Keine Dokumente</string>
|
||||||
|
<string name="error_loading_documents">Fehler beim Laden von Dokumenten</string>
|
||||||
|
<string name="no_files">Keine Dateien</string>
|
||||||
|
<string name="error_loading_files">Fehler beim Laden von Dateien</string>
|
||||||
|
<string name="new_document">Neues Dokument</string>
|
||||||
|
<string name="share">Teilen</string>
|
||||||
|
<string name="close">Schließen</string>
|
||||||
|
<string name="add">Hinzufügen</string>
|
||||||
|
<string name="add_share_hint">Freigabename (optional)</string>
|
||||||
|
<string name="document_not_shared">Dieses Dokument wird derzeit nicht freigegeben</string>
|
||||||
|
<string name="delete_share">Diese Freigabe löschen</string>
|
||||||
|
<string name="send_share">Send this share link</string>
|
||||||
|
<string name="error_loading_shares">Fehler beim Laden von Freigaben</string>
|
||||||
|
<string name="error_adding_share">Fehler beim Hinzufügen der Freigabe</string>
|
||||||
|
<string name="share_default_name">Freigabe Link</string>
|
||||||
|
<string name="error_deleting_share">Fehler beim Löschen der Freigabe</string>
|
||||||
|
<string name="send_share_to">Freigabe senden an</string>
|
||||||
|
<string name="upload_file">Datei hinzufügen</string>
|
||||||
|
<string name="upload_from">Datei hochladen von</string>
|
||||||
|
<string name="settings">Einstellungen</string>
|
||||||
|
<string name="logout">Ausloggen</string>
|
||||||
|
<string name="version">Version</string>
|
||||||
|
<string name="build">Build</string>
|
||||||
|
<string name="pref_advanced_category">Erweiterte Einstellungen</string>
|
||||||
|
<string name="pref_about_category">Über</string>
|
||||||
|
<string name="pref_github">GitHub</string>
|
||||||
|
<string name="pref_issue">Fehler berichten</string>
|
||||||
|
<string name="pref_clear_cache_title">Cache leeren</string>
|
||||||
|
<string name="pref_clear_cache_summary">Zwischengespeicherte Dateien löschen</string>
|
||||||
|
<string name="pref_clear_cache_success">Cache wurde geleert</string>
|
||||||
|
<string name="pref_clear_history_title">Suchhistorie löschen</string>
|
||||||
|
<string name="pref_clear_history_summary">Leert die aktuellen Suchvorschläge</string>
|
||||||
|
<string name="pref_clear_history_success">Suchvorschläge wurden gelöscht</string>
|
||||||
|
<string name="pref_cache_size">Cache Größe</string>
|
||||||
|
<string name="save">Speichern</string>
|
||||||
|
<string name="edit_document">Bearbeiten</string>
|
||||||
|
<string name="error_editing_document">Netzwerkfehler, bitte versuchen Sie es erneut</string>
|
||||||
|
<string name="please_wait">Bitte warten</string>
|
||||||
|
<string name="document_editing_message">Daten werden gesendet</string>
|
||||||
|
<string name="delete_document">Löschen</string>
|
||||||
|
<string name="delete_document_title">Dokument löschen</string>
|
||||||
|
<string name="delete_document_message">Dieses Dokument und alle zugehörigen Dateien wirklich löschen?</string>
|
||||||
|
<string name="document_delete_failure">Netzwerkfehler beim Löschen des Dokuments</string>
|
||||||
|
<string name="document_deleting_message">Lösche Dokument</string>
|
||||||
|
<string name="delete_file_title">Datei löschen</string>
|
||||||
|
<string name="delete_file_message">Die aktuelle Datei wirklich löschen?</string>
|
||||||
|
<string name="file_delete_failure">Netzwerkfehler beim Löschen der Datei</string>
|
||||||
|
<string name="file_deleting_message">Lösche Datei</string>
|
||||||
|
<string name="error_reading_file">Fehler beim Lesen der Datei</string>
|
||||||
|
<string name="upload_notification_title">Teedy</string>
|
||||||
|
<string name="upload_notification_message">Neue Datei in das Dokument hochladen</string>
|
||||||
|
<string name="upload_notification_error">Fehler beim Hochladen der neuen Datei</string>
|
||||||
|
<string name="delete_file">Aktuelle Datei löschen</string>
|
||||||
|
<string name="advanced_search">Erweiterte Suche</string>
|
||||||
|
<string name="search">Suche</string>
|
||||||
|
<string name="add_tags">Tags hinzufügen</string>
|
||||||
|
<string name="creation_date">Erstellungsdatum</string>
|
||||||
|
<string name="description">Beschreibung</string>
|
||||||
|
<string name="title">Titel</string>
|
||||||
|
<string name="simple_search">Einfache Suche</string>
|
||||||
|
<string name="fulltext_search">Volltextsuche</string>
|
||||||
|
<string name="creator">Ersteller</string>
|
||||||
|
<string name="after_date">Nach Datum</string>
|
||||||
|
<string name="before_date">Vor Datum</string>
|
||||||
|
<string name="search_tags">Tags durchsuchen</string>
|
||||||
|
<string name="all_languages">Alle Sprachen</string>
|
||||||
|
<string name="toggle_informations">Informationen anzeigen</string>
|
||||||
|
<string name="who_can_access">Wer kann darauf zugreifen?</string>
|
||||||
|
<string name="comments">Kommentare</string>
|
||||||
|
<string name="no_comments">Keine Kommentare</string>
|
||||||
|
<string name="error_loading_comments">Fehler beim Laden von Kommentaren</string>
|
||||||
|
<string name="send">Senden</string>
|
||||||
|
<string name="add_comment">Kommentar hinzufügen</string>
|
||||||
|
<string name="comment_add_failure">Fehler beim Hinzufügen des Kommentars</string>
|
||||||
|
<string name="adding_comment">Füge Kommentar hinzu</string>
|
||||||
|
<string name="comment_delete">Kommentar löschen</string>
|
||||||
|
<string name="deleting_comment">Lösche Kommentar</string>
|
||||||
|
<string name="error_deleting_comment">Fehler beim Löschen des Kommentars</string>
|
||||||
|
<string name="export_pdf">PDF</string>
|
||||||
|
<string name="download">Download</string>
|
||||||
|
<string name="margin">Rand</string>
|
||||||
|
<string name="fit_image_to_page">Bild an Seite anpassen</string>
|
||||||
|
<string name="export_comments">Kommentare exportieren</string>
|
||||||
|
<string name="export_metadata">Metadaten exportieren</string>
|
||||||
|
<string name="mm">mm</string>
|
||||||
|
<string name="download_file_title">Teedy Datei Export</string>
|
||||||
|
<string name="download_document_title">Teedy Dokumentenexport</string>
|
||||||
|
<string name="download_pdf_title">Teedy PDF Export</string>
|
||||||
|
<string name="latest_activity">Letzte Aktivität</string>
|
||||||
|
<string name="activity">Aktivitäten</string>
|
||||||
|
<string name="email">E-Mail</string>
|
||||||
|
<string name="storage_quota">Speicherbegrenzung</string>
|
||||||
|
<string name="storage_display">%1$d/%2$d MB</string>
|
||||||
|
<string name="validation_code">Validierungscode</string>
|
||||||
|
<string name="shared">Geteilt</string>
|
||||||
|
<string name="language">Sprache</string>
|
||||||
|
<string name="coverage">Geltungsbereich</string>
|
||||||
|
<string name="type">Typ</string>
|
||||||
|
<string name="source">Quelle</string>
|
||||||
|
<string name="format">Format</string>
|
||||||
|
<string name="publisher">Verleger</string>
|
||||||
|
<string name="identifier">Identifikator</string>
|
||||||
|
<string name="subject">Thema</string>
|
||||||
|
<string name="rights">Rechte</string>
|
||||||
|
<string name="contributors">Mitwirkende</string>
|
||||||
|
<string name="relations">Beziehungen</string>
|
||||||
|
|
||||||
|
<!-- Audit log -->
|
||||||
|
<string name="auditlog_Acl">ACL</string>
|
||||||
|
<string name="auditlog_Comment">Kommentar</string>
|
||||||
|
<string name="auditlog_Document">Dokument</string>
|
||||||
|
<string name="auditlog_File">Datei</string>
|
||||||
|
<string name="auditlog_Group">Gruppe</string>
|
||||||
|
<string name="auditlog_Route">Workflow</string>
|
||||||
|
<string name="auditlog_RouteModel">Workflow-Muster</string>
|
||||||
|
<string name="auditlog_Tag">Tag</string>
|
||||||
|
<string name="auditlog_User">Benutzer</string>
|
||||||
|
<string name="auditlog_Webhook">Webhook</string>
|
||||||
|
<string name="auditlog_created">erstellt</string>
|
||||||
|
<string name="auditlog_updated">aktualisiert</string>
|
||||||
|
<string name="auditlog_deleted">gelöscht</string>
|
||||||
|
|
||||||
|
</resources>
|
159
docs-android/app/src/main/res/values-fr/strings.xml
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Validation -->
|
||||||
|
<string name="validate_error_email">Email invalide</string>
|
||||||
|
<string name="validate_error_length_min">Trop court (min. %d)</string>
|
||||||
|
<string name="validate_error_length_max">Trop long (max. %d)</string>
|
||||||
|
<string name="validate_error_required">Requis</string>
|
||||||
|
<string name="validate_error_alphanumeric">Seuls les lettres et les nombres sont autorisés</string>
|
||||||
|
|
||||||
|
<!-- App -->
|
||||||
|
<string name="drawer_open">Ouvrir le menu de navigation</string>
|
||||||
|
<string name="drawer_close">Fermer le menu de navigation</string>
|
||||||
|
<string name="login_explain"><![CDATA[Pour commencer, vous devez télécharger et installer le serveur Teedy sur <a href="https://github.com/sismics/docs">github.com/sismics/docs</a> et entrer son URL ci-dessous]]></string>
|
||||||
|
<string name="server">Serveur</string>
|
||||||
|
<string name="username">Nom d\'utilisateur</string>
|
||||||
|
<string name="password">Mot de passe</string>
|
||||||
|
<string name="login">Connexion</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Annuler</string>
|
||||||
|
<string name="login_fail_title">Echec de la connexion</string>
|
||||||
|
<string name="login_fail">Mauvais nom d\'utilisateur ou de mot de passe</string>
|
||||||
|
<string name="network_error_title">Erreur réseau</string>
|
||||||
|
<string name="network_error">Erreur réseau, veuillez vérifier votre connexion internet et l\'URL du serveur</string>
|
||||||
|
<string name="invalid_url_title">URL invalide</string>
|
||||||
|
<string name="invalid_url">Veuillez vérifier l\URL du serveur et réessayer</string>
|
||||||
|
<string name="crash_toast_text">Une erreur s\'est produite, un rapport a été envoyé afin de corriger ce problème</string>
|
||||||
|
<string name="created_date">Date création</string>
|
||||||
|
<string name="download_file">Télécharger ce fichier</string>
|
||||||
|
<string name="download_document">Télécharger</string>
|
||||||
|
<string name="action_search">Rechercher dans les documents</string>
|
||||||
|
<string name="all_documents">Tous les documents</string>
|
||||||
|
<string name="shared_documents">Documents partagés</string>
|
||||||
|
<string name="all_tags">Tous les tags</string>
|
||||||
|
<string name="no_tags">Aucun tag</string>
|
||||||
|
<string name="error_loading_tags">Erreur de chargement des tags</string>
|
||||||
|
<string name="no_documents">Aucun document</string>
|
||||||
|
<string name="error_loading_documents">Erreur de chargement des documents</string>
|
||||||
|
<string name="no_files">Aucun fichier</string>
|
||||||
|
<string name="error_loading_files">Erreur de chargement des fichiers</string>
|
||||||
|
<string name="new_document">Nouveau document</string>
|
||||||
|
<string name="share">Partage</string>
|
||||||
|
<string name="close">Fermer</string>
|
||||||
|
<string name="add">Ajouter</string>
|
||||||
|
<string name="add_share_hint">Nom du partage (facultatif)</string>
|
||||||
|
<string name="document_not_shared">Ce document n\'est pas partagé</string>
|
||||||
|
<string name="delete_share">Supprimer ce partage</string>
|
||||||
|
<string name="send_share">Envoi ce lien de partage</string>
|
||||||
|
<string name="error_loading_shares">Erreur de chargement des partages</string>
|
||||||
|
<string name="error_adding_share">Erreur lors de l\'ajout du partage</string>
|
||||||
|
<string name="share_default_name">Lien de partage</string>
|
||||||
|
<string name="error_deleting_share">Erreur lors de la suppression de ce partage</string>
|
||||||
|
<string name="send_share_to">Envoi ce lien de partage à</string>
|
||||||
|
<string name="upload_file">Aj. fichier</string>
|
||||||
|
<string name="upload_from">Envoyer un fichier depuis</string>
|
||||||
|
<string name="settings">Paramètres</string>
|
||||||
|
<string name="logout">Déconnexion</string>
|
||||||
|
<string name="version">Version</string>
|
||||||
|
<string name="build">Build</string>
|
||||||
|
<string name="pref_advanced_category">Paramètres avancés</string>
|
||||||
|
<string name="pref_about_category">A propors</string>
|
||||||
|
<string name="pref_github">GitHub</string>
|
||||||
|
<string name="pref_issue">Rapporter un bug</string>
|
||||||
|
<string name="pref_clear_cache_title">Vider le cache</string>
|
||||||
|
<string name="pref_clear_cache_summary">Nettoyer les fichiers en cache</string>
|
||||||
|
<string name="pref_clear_cache_success">Cache vidé</string>
|
||||||
|
<string name="pref_clear_history_title">Vider l\'historique de recherche</string>
|
||||||
|
<string name="pref_clear_history_summary">Supprimer les recherches récentes</string>
|
||||||
|
<string name="pref_clear_history_success">Historique de recherche vidé</string>
|
||||||
|
<string name="pref_cache_size">Taille du cache</string>
|
||||||
|
<string name="save">Enregistrer</string>
|
||||||
|
<string name="edit_document">Modifier</string>
|
||||||
|
<string name="error_editing_document">Erreur réseau, veuillez réessayer</string>
|
||||||
|
<string name="please_wait">Veuillez patienter</string>
|
||||||
|
<string name="document_editing_message">Envoi des données</string>
|
||||||
|
<string name="delete_document">Suppr.</string>
|
||||||
|
<string name="delete_document_title">Supprimer le document</string>
|
||||||
|
<string name="delete_document_message">Etes-vous sûr de vouloir supprimer ce document et tous les fichiers associés ?</string>
|
||||||
|
<string name="document_delete_failure">Erreur réseau lors de la suppression de ce document</string>
|
||||||
|
<string name="document_deleting_message">Suppression du document</string>
|
||||||
|
<string name="delete_file_title">Supprimer le fichier</string>
|
||||||
|
<string name="delete_file_message">Etes-vous sûr de vouloir supprimer ce fichier ?</string>
|
||||||
|
<string name="file_delete_failure">Erreur réseau lors de la suppression du fichier</string>
|
||||||
|
<string name="file_deleting_message">Suppression du fichier</string>
|
||||||
|
<string name="error_reading_file">Erreur lors de la lecture du fichier</string>
|
||||||
|
<string name="upload_notification_title">Teedy</string>
|
||||||
|
<string name="upload_notification_message">Envoi du nouveau fichier</string>
|
||||||
|
<string name="upload_notification_error">Erreur lors de l\'envoi du nouveau fichier</string>
|
||||||
|
<string name="delete_file">Supprimer ce fichier</string>
|
||||||
|
<string name="advanced_search">Recherche avancée</string>
|
||||||
|
<string name="search">Rechercher</string>
|
||||||
|
<string name="add_tags">Ajouter des tags</string>
|
||||||
|
<string name="creation_date">Date de création</string>
|
||||||
|
<string name="description">Description</string>
|
||||||
|
<string name="title">Titre</string>
|
||||||
|
<string name="simple_search">Recherche simple</string>
|
||||||
|
<string name="fulltext_search">Recherche texte intégral</string>
|
||||||
|
<string name="creator">Créateur</string>
|
||||||
|
<string name="after_date">Après cette date</string>
|
||||||
|
<string name="before_date">Avant cette date</string>
|
||||||
|
<string name="search_tags">Rechercher dans les tags</string>
|
||||||
|
<string name="all_languages">Toutes les langues</string>
|
||||||
|
<string name="toggle_informations">Afficher/masquer les informations</string>
|
||||||
|
<string name="who_can_access">Qui a accès</string>
|
||||||
|
<string name="comments">Commentaires</string>
|
||||||
|
<string name="no_comments">Aucun commentaire</string>
|
||||||
|
<string name="error_loading_comments">Erreur de chargement des commentaires</string>
|
||||||
|
<string name="send">Envoyer</string>
|
||||||
|
<string name="add_comment">Ajouter un commentaire</string>
|
||||||
|
<string name="comment_add_failure">Erreur lors de l\'ajout du commentaire</string>
|
||||||
|
<string name="adding_comment">Ajout du commentaire</string>
|
||||||
|
<string name="comment_delete">Supprimer le commentaire</string>
|
||||||
|
<string name="deleting_comment">Suppression du commentaire</string>
|
||||||
|
<string name="error_deleting_comment">Erreur lors de la suppression du commentaire</string>
|
||||||
|
<string name="export_pdf">PDF</string>
|
||||||
|
<string name="download">Télécharger</string>
|
||||||
|
<string name="margin">Marge</string>
|
||||||
|
<string name="fit_image_to_page">Ajuster les images à la page</string>
|
||||||
|
<string name="export_comments">Exporter les commentaires</string>
|
||||||
|
<string name="export_metadata">Exporter les métadonnées</string>
|
||||||
|
<string name="mm">mm</string>
|
||||||
|
<string name="download_file_title">Export de fichier Teedy</string>
|
||||||
|
<string name="download_document_title">Export de document Teedy</string>
|
||||||
|
<string name="download_pdf_title">Export PDF Teedy</string>
|
||||||
|
<string name="latest_activity">Activité récente</string>
|
||||||
|
<string name="activity">Activité</string>
|
||||||
|
<string name="email">E-mail</string>
|
||||||
|
<string name="storage_quota">Quota de stockage</string>
|
||||||
|
<string name="storage_display">%1$d/%2$d Mo</string>
|
||||||
|
<string name="validation_code">Code de validation</string>
|
||||||
|
<string name="shared">Partagé</string>
|
||||||
|
<string name="language">Langue</string>
|
||||||
|
<string name="coverage">Couverture</string>
|
||||||
|
<string name="type">Type</string>
|
||||||
|
<string name="source">Source</string>
|
||||||
|
<string name="format">Format</string>
|
||||||
|
<string name="publisher">Editeur</string>
|
||||||
|
<string name="identifier">Identifiant</string>
|
||||||
|
<string name="subject">Sujet</string>
|
||||||
|
<string name="rights">Droits</string>
|
||||||
|
<string name="contributors">Contributeurs</string>
|
||||||
|
<string name="relations">Relations</string>
|
||||||
|
|
||||||
|
<!-- Audit log -->
|
||||||
|
<string name="auditlog_Acl">ACL</string>
|
||||||
|
<string name="auditlog_Comment">Commentaire</string>
|
||||||
|
<string name="auditlog_Document">Document</string>
|
||||||
|
<string name="auditlog_File">Fichier</string>
|
||||||
|
<string name="auditlog_Group">Groupe</string>
|
||||||
|
<string name="auditlog_Route">Workflow</string>
|
||||||
|
<string name="auditlog_RouteModel">Modèle de workflow</string>
|
||||||
|
<string name="auditlog_Tag">Tag</string>
|
||||||
|
<string name="auditlog_User">Utilisateur</string>
|
||||||
|
<string name="auditlog_Webhook">Webhook</string>
|
||||||
|
<string name="auditlog_created">créé</string>
|
||||||
|
<string name="auditlog_updated">mis à jour</string>
|
||||||
|
<string name="auditlog_deleted">supprimé</string>
|
||||||
|
|
||||||
|
</resources>
|
164
docs-android/app/src/main/res/values-pl/strings.xml
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<!-- Validation -->
|
||||||
|
<string name="validate_error_email">Nieprawidłowy email</string>
|
||||||
|
<string name="validate_error_length_min">Za krótki (min. %d)</string>
|
||||||
|
<string name="validate_error_length_max">Za długi (max. %d)</string>
|
||||||
|
<string name="validate_error_required">Wymagany</string>
|
||||||
|
<string name="validate_error_alphanumeric">Tylko litery i cyfry</string>
|
||||||
|
|
||||||
|
<!-- App -->
|
||||||
|
<string name="app_name" translatable="false">Teedy</string>
|
||||||
|
<string name="drawer_open">Otwórz szufladę nawigacji</string>
|
||||||
|
<string name="drawer_close">Zamknij szufladę nawigacji</string>
|
||||||
|
<string name="login_explain"><![CDATA[Aby rozpocząć, musisz pobrać i zainstalować serwer Teedy na <a href="https://github.com/sismics/docs">github.com/sismics/docs</a> i poniżej wprowadzić adres]]></string>
|
||||||
|
<string name="server">Serwer</string>
|
||||||
|
<string name="username">Użytkownik</string>
|
||||||
|
<string name="password">Hasło</string>
|
||||||
|
<string name="login">Zaloguj</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Anuluj</string>
|
||||||
|
<string name="login_fail_title">Błąd logowania</string>
|
||||||
|
<string name="login_fail">Nieprawidłowa nazwa użytkownika lub hasło</string>
|
||||||
|
<string name="network_error_title">Błąd sieci</string>
|
||||||
|
<string name="network_error">Błąd sieci, sprawdź połączenie z interneterm oraz adres URL serwera</string>
|
||||||
|
<string name="invalid_url_title">Nieprawidłowy adres URL</string>
|
||||||
|
<string name="invalid_url">Sprawdź adres URL serwera i spróbuj ponownie</string>
|
||||||
|
<string name="crash_toast_text">Wystąpiła awaria, wysłano raport w celu rozwiązania tego problemu</string>
|
||||||
|
<string name="created_date">Data utworzenia</string>
|
||||||
|
<string name="download_file">Pobierz bieżący plik</string>
|
||||||
|
<string name="download_document">Pobierz</string>
|
||||||
|
<string name="action_search">Znadź dokumenty</string>
|
||||||
|
<string name="all_documents">Wszystkie dokumenty</string>
|
||||||
|
<string name="shared_documents">Udostępnione dokumenty</string>
|
||||||
|
<string name="all_tags">Wszystkie etykiety</string>
|
||||||
|
<string name="no_tags">Brak etykiet</string>
|
||||||
|
<string name="error_loading_tags">Błąd ładowania etykiet</string>
|
||||||
|
<string name="no_documents">Brak dokumentów</string>
|
||||||
|
<string name="error_loading_documents">Błąd ładowania dokumentów</string>
|
||||||
|
<string name="no_files">Brak plików</string>
|
||||||
|
<string name="error_loading_files">Błąd ładowania plików</string>
|
||||||
|
<string name="new_document">Nowy dokument</string>
|
||||||
|
<string name="share">Udostępnij</string>
|
||||||
|
<string name="close">Zamknij</string>
|
||||||
|
<string name="add">Dodaj</string>
|
||||||
|
<string name="add_share_hint">Nazwa udostępnienia (opcjonalnie)</string>
|
||||||
|
<string name="document_not_shared">Ten dokument nie jest obecnie udostępniony</string>
|
||||||
|
<string name="delete_share">Usuń udostępnienie</string>
|
||||||
|
<string name="send_share">Wyślij link udostępnienia</string>
|
||||||
|
<string name="error_loading_shares">Błąd ładowania udostępnień</string>
|
||||||
|
<string name="error_adding_share">Błąd dodawania udostępnienia</string>
|
||||||
|
<string name="share_default_name">Udostępnij link</string>
|
||||||
|
<string name="error_deleting_share">Błąd usuwania udostępnienia</string>
|
||||||
|
<string name="send_share_to">Wyślij link udostępnienia do</string>
|
||||||
|
<string name="upload_file">dodaj plik</string>
|
||||||
|
<string name="upload_from">Przeslij plik z</string>
|
||||||
|
<string name="settings">ustawienia</string>
|
||||||
|
<string name="logout">Wyloguj</string>
|
||||||
|
<string name="version">Wersja</string>
|
||||||
|
<string name="build">Kompilacja</string>
|
||||||
|
<string name="pref_advanced_category">Ustawienia zaawansowane</string>
|
||||||
|
<string name="pref_about_category">O programie</string>
|
||||||
|
<string name="pref_github">GitHub</string>
|
||||||
|
<string name="pref_issue">Zgłoś błąd</string>
|
||||||
|
<string name="pref_clear_cache_title">Wyczyść cache</string>
|
||||||
|
<string name="pref_clear_cache_summary">Wyczyść podręczne pliki</string>
|
||||||
|
<string name="pref_clear_cache_success">Cache wyczyszczony</string>
|
||||||
|
<string name="pref_clear_history_title">Wyczyść historię wyszukiwania</string>
|
||||||
|
<string name="pref_clear_history_summary">Opróżnij ostatnie sugestie wyszukiwania</string>
|
||||||
|
<string name="pref_clear_history_success">Historia wyszukiwania wyczyszczona</string>
|
||||||
|
<string name="pref_cache_size">Rozmiar cache</string>
|
||||||
|
<string name="language_french" translatable="false">Francuski</string>
|
||||||
|
<string name="language_english" translatable="false">Angielski</string>
|
||||||
|
<string name="language_german" translatable="false">Niemiecki</string>
|
||||||
|
<string name="language_polish" translatable="false">Polski</string>
|
||||||
|
<string name="save">Zapisz</string>
|
||||||
|
<string name="edit_document">Edytuj</string>
|
||||||
|
<string name="error_editing_document">Błąd sieci, spróbuj ponownie</string>
|
||||||
|
<string name="please_wait">Proszę czekać</string>
|
||||||
|
<string name="document_editing_message">Wysyłam twoje dane</string>
|
||||||
|
<string name="delete_document">Usuń</string>
|
||||||
|
<string name="delete_document_title">Usuń dokument</string>
|
||||||
|
<string name="delete_document_message">Naprawdę chcesz usunąć dokument i powiązane z nim pliki?</string>
|
||||||
|
<string name="document_delete_failure">Błąd sieci w czasie usuwania tego dokumentu</string>
|
||||||
|
<string name="document_deleting_message">Usuwanie dokumentu</string>
|
||||||
|
<string name="delete_file_title">Usuń plik</string>
|
||||||
|
<string name="delete_file_message">Naprawdę chcesz usunąć ten plik?</string>
|
||||||
|
<string name="file_delete_failure">Błąd sieci w czasie usuwania bieżącego pliku</string>
|
||||||
|
<string name="file_deleting_message">Usuwanie pliku</string>
|
||||||
|
<string name="error_reading_file">Błąd podczas odczytu pliku</string>
|
||||||
|
<string name="upload_notification_title">Teedy</string>
|
||||||
|
<string name="upload_notification_message">Przesyłanie nowego pliku do dokumentu</string>
|
||||||
|
<string name="upload_notification_error">Błąd przsyłania nowego pliku</string>
|
||||||
|
<string name="delete_file">Usuń bieżący plik</string>
|
||||||
|
<string name="advanced_search">Zaawansowane wyszukiwanie</string>
|
||||||
|
<string name="search">Znajdź</string>
|
||||||
|
<string name="add_tags">Dodaj eytkiety</string>
|
||||||
|
<string name="creation_date">Data utworzenia</string>
|
||||||
|
<string name="description">Opis</string>
|
||||||
|
<string name="title">Tytuł</string>
|
||||||
|
<string name="simple_search">Proste wyszukiwanie</string>
|
||||||
|
<string name="fulltext_search">Wyszukiwanie pełnotekstowe</string>
|
||||||
|
<string name="creator">Autor</string>
|
||||||
|
<string name="after_date">Po dacie</string>
|
||||||
|
<string name="before_date">Przed datą</string>
|
||||||
|
<string name="search_tags">Znajdź etykiety</string>
|
||||||
|
<string name="all_languages">Wszystkie języki</string>
|
||||||
|
<string name="toggle_informations">Przełącz informacje</string>
|
||||||
|
<string name="who_can_access">Kto ma dostęp</string>
|
||||||
|
<string name="comments">Komentarze</string>
|
||||||
|
<string name="no_comments">Brak komentarzy</string>
|
||||||
|
<string name="error_loading_comments">Błąd ładowania komentarzy</string>
|
||||||
|
<string name="send">Wyślij</string>
|
||||||
|
<string name="add_comment">Dodaj komentarz</string>
|
||||||
|
<string name="comment_add_failure">Błąd dodawania komentarza</string>
|
||||||
|
<string name="adding_comment">Dodawanie komentarza</string>
|
||||||
|
<string name="comment_delete">Usuń komentarz</string>
|
||||||
|
<string name="deleting_comment">Usuwanie komentarza</string>
|
||||||
|
<string name="error_deleting_comment">Błąd usuwania komentarza</string>
|
||||||
|
<string name="export_pdf">PDF</string>
|
||||||
|
<string name="download">Pobierz</string>
|
||||||
|
<string name="margin">Margines</string>
|
||||||
|
<string name="fit_image_to_page">Dostosuj obraz do strony</string>
|
||||||
|
<string name="export_comments">Eksport komentarzy</string>
|
||||||
|
<string name="export_metadata">Eksport metadanych</string>
|
||||||
|
<string name="mm">mm</string>
|
||||||
|
<string name="download_file_title">Eksport plików Teedy</string>
|
||||||
|
<string name="download_document_title">Eksport dokumentu Teedy</string>
|
||||||
|
<string name="download_pdf_title">Eksport Teedy jako PDF</string>
|
||||||
|
<string name="latest_activity">Ostatnie aktywności</string>
|
||||||
|
<string name="activity">Aktywności</string>
|
||||||
|
<string name="email">E-mail</string>
|
||||||
|
<string name="storage_quota">Limit magazynu</string>
|
||||||
|
<string name="storage_display">%1$d/%2$d MB</string>
|
||||||
|
<string name="validation_code">Kod weryfikujący</string>
|
||||||
|
<string name="shared">Udostępnienie</string>
|
||||||
|
<string name="language">Język</string>
|
||||||
|
<string name="coverage">Zakres</string>
|
||||||
|
<string name="type">Rodzaj</string>
|
||||||
|
<string name="source">Źródło</string>
|
||||||
|
<string name="format">Format</string>
|
||||||
|
<string name="publisher">Udostępniający</string>
|
||||||
|
<string name="identifier">Identifikator</string>
|
||||||
|
<string name="subject">temat</string>
|
||||||
|
<string name="rights">Prawa</string>
|
||||||
|
<string name="contributors">Współtwórcy</string>
|
||||||
|
<string name="relations">Powiązania</string>
|
||||||
|
|
||||||
|
<!-- Audit log -->
|
||||||
|
<string name="auditlog_Acl">ACL</string>
|
||||||
|
<string name="auditlog_Comment">Komentarz</string>
|
||||||
|
<string name="auditlog_Document">Dokument</string>
|
||||||
|
<string name="auditlog_File">Plik</string>
|
||||||
|
<string name="auditlog_Group">Grupa</string>
|
||||||
|
<string name="auditlog_Route">Przepływ</string>
|
||||||
|
<string name="auditlog_RouteModel">Model przepływu</string>
|
||||||
|
<string name="auditlog_Tag">Etykieta</string>
|
||||||
|
<string name="auditlog_User">Użytkownik</string>
|
||||||
|
<string name="auditlog_Webhook">Webhook</string>
|
||||||
|
<string name="auditlog_created">utworzony</string>
|
||||||
|
<string name="auditlog_updated">zaktualizowany</string>
|
||||||
|
<string name="auditlog_deleted">usunięty</string>
|
||||||
|
|
||||||
|
</resources>
|
@ -9,10 +9,10 @@
|
|||||||
<string name="validate_error_alphanumeric">Only letters and numbers</string>
|
<string name="validate_error_alphanumeric">Only letters and numbers</string>
|
||||||
|
|
||||||
<!-- App -->
|
<!-- App -->
|
||||||
<string name="app_name">Sismics Docs</string>
|
<string name="app_name" translatable="false">Teedy</string>
|
||||||
<string name="drawer_open">Open navigation drawer</string>
|
<string name="drawer_open">Open navigation drawer</string>
|
||||||
<string name="drawer_close">Close navigation drawer</string>
|
<string name="drawer_close">Close navigation drawer</string>
|
||||||
<string name="login_explain"><![CDATA[To start, you must download and install Sismics Docs Server on <a href="http://www.sismics.com/docs">www.sismics.com/docs</a> and enter your server URL below]]></string>
|
<string name="login_explain"><![CDATA[To start, you must download and install Teedy Server on <a href="https://github.com/sismics/docs">github.com/sismics/docs</a> and enter its below]]></string>
|
||||||
<string name="server">Server</string>
|
<string name="server">Server</string>
|
||||||
<string name="username">Username</string>
|
<string name="username">Username</string>
|
||||||
<string name="password">Password</string>
|
<string name="password">Password</string>
|
||||||
@ -28,9 +28,7 @@
|
|||||||
<string name="crash_toast_text">A crash occurred, a report has been sent to resolve this problem</string>
|
<string name="crash_toast_text">A crash occurred, a report has been sent to resolve this problem</string>
|
||||||
<string name="created_date">Created date</string>
|
<string name="created_date">Created date</string>
|
||||||
<string name="download_file">Download current file</string>
|
<string name="download_file">Download current file</string>
|
||||||
<string name="downloading_file">Downloading file number %1s</string>
|
|
||||||
<string name="download_document">Download</string>
|
<string name="download_document">Download</string>
|
||||||
<string name="downloading_document">Downloading document</string>
|
|
||||||
<string name="action_search">Search documents</string>
|
<string name="action_search">Search documents</string>
|
||||||
<string name="all_documents">All documents</string>
|
<string name="all_documents">All documents</string>
|
||||||
<string name="shared_documents">Shared documents</string>
|
<string name="shared_documents">Shared documents</string>
|
||||||
@ -48,7 +46,7 @@
|
|||||||
<string name="add_share_hint">Name the share (optional)</string>
|
<string name="add_share_hint">Name the share (optional)</string>
|
||||||
<string name="document_not_shared">This document is not currently shared</string>
|
<string name="document_not_shared">This document is not currently shared</string>
|
||||||
<string name="delete_share">Delete this share</string>
|
<string name="delete_share">Delete this share</string>
|
||||||
<string name="send_share">Send this share</string>
|
<string name="send_share">Send this share link</string>
|
||||||
<string name="error_loading_shares">Error loading shares</string>
|
<string name="error_loading_shares">Error loading shares</string>
|
||||||
<string name="error_adding_share">Error adding share</string>
|
<string name="error_adding_share">Error adding share</string>
|
||||||
<string name="share_default_name">Share link</string>
|
<string name="share_default_name">Share link</string>
|
||||||
@ -71,9 +69,10 @@
|
|||||||
<string name="pref_clear_history_summary">Wipe the recent search suggestions</string>
|
<string name="pref_clear_history_summary">Wipe the recent search suggestions</string>
|
||||||
<string name="pref_clear_history_success">Search history cleared</string>
|
<string name="pref_clear_history_success">Search history cleared</string>
|
||||||
<string name="pref_cache_size">Cache size</string>
|
<string name="pref_cache_size">Cache size</string>
|
||||||
<string name="language_french">French</string>
|
<string name="language_french" translatable="false">Français</string>
|
||||||
<string name="language_english">English</string>
|
<string name="language_english" translatable="false">English</string>
|
||||||
<string name="language_japanese">Japanese</string>
|
<string name="language_german" translatable="false">Deutsch</string>
|
||||||
|
<string name="language_polish" translatable="false">Polski</string>
|
||||||
<string name="save">Save</string>
|
<string name="save">Save</string>
|
||||||
<string name="edit_document">Edit</string>
|
<string name="edit_document">Edit</string>
|
||||||
<string name="error_editing_document">Network error, please try again</string>
|
<string name="error_editing_document">Network error, please try again</string>
|
||||||
@ -89,7 +88,7 @@
|
|||||||
<string name="file_delete_failure">Network error while deleting the current file</string>
|
<string name="file_delete_failure">Network error while deleting the current file</string>
|
||||||
<string name="file_deleting_message">Deleting file</string>
|
<string name="file_deleting_message">Deleting file</string>
|
||||||
<string name="error_reading_file">Error while reading the file</string>
|
<string name="error_reading_file">Error while reading the file</string>
|
||||||
<string name="upload_notification_title">Sismics Docs</string>
|
<string name="upload_notification_title">Teedy</string>
|
||||||
<string name="upload_notification_message">Uploading the new file to the document</string>
|
<string name="upload_notification_message">Uploading the new file to the document</string>
|
||||||
<string name="upload_notification_error">Error uploading the new file</string>
|
<string name="upload_notification_error">Error uploading the new file</string>
|
||||||
<string name="delete_file">Delete current file</string>
|
<string name="delete_file">Delete current file</string>
|
||||||
@ -101,12 +100,65 @@
|
|||||||
<string name="title">Title</string>
|
<string name="title">Title</string>
|
||||||
<string name="simple_search">Simple search</string>
|
<string name="simple_search">Simple search</string>
|
||||||
<string name="fulltext_search">Fulltext search</string>
|
<string name="fulltext_search">Fulltext search</string>
|
||||||
|
<string name="creator">Creator</string>
|
||||||
<string name="after_date">After date</string>
|
<string name="after_date">After date</string>
|
||||||
<string name="before_date">Before date</string>
|
<string name="before_date">Before date</string>
|
||||||
<string name="search_tags">Search tags</string>
|
<string name="search_tags">Search tags</string>
|
||||||
<string name="all_languages">All languages</string>
|
<string name="all_languages">All languages</string>
|
||||||
<string name="toggle_informations">Toggle informations</string>
|
<string name="toggle_informations">Toggle informations</string>
|
||||||
<string name="who_can_access">Who can access</string>
|
<string name="who_can_access">Who can access</string>
|
||||||
|
<string name="comments">Comments</string>
|
||||||
|
<string name="no_comments">No comments</string>
|
||||||
|
<string name="error_loading_comments">Error loading comments</string>
|
||||||
|
<string name="send">Send</string>
|
||||||
|
<string name="add_comment">Add a comment</string>
|
||||||
|
<string name="comment_add_failure">Error adding a comment</string>
|
||||||
|
<string name="adding_comment">Adding a comment</string>
|
||||||
|
<string name="comment_delete">Delete comment</string>
|
||||||
|
<string name="deleting_comment">Deleting comment</string>
|
||||||
|
<string name="error_deleting_comment">Error deleting comment</string>
|
||||||
|
<string name="export_pdf">PDF</string>
|
||||||
|
<string name="download">Download</string>
|
||||||
|
<string name="margin">Margin</string>
|
||||||
|
<string name="fit_image_to_page">Fit image to page</string>
|
||||||
|
<string name="export_comments">Export comments</string>
|
||||||
|
<string name="export_metadata">Export metadata</string>
|
||||||
|
<string name="mm">mm</string>
|
||||||
|
<string name="download_file_title">Teedy file export</string>
|
||||||
|
<string name="download_document_title">Teedy document export</string>
|
||||||
|
<string name="download_pdf_title">Teedy PDF export</string>
|
||||||
|
<string name="latest_activity">Latest activity</string>
|
||||||
|
<string name="activity">Activity</string>
|
||||||
|
<string name="email">E-mail</string>
|
||||||
|
<string name="storage_quota">Storage quota</string>
|
||||||
|
<string name="storage_display">%1$d/%2$d MB</string>
|
||||||
|
<string name="validation_code">Validation code</string>
|
||||||
|
<string name="shared">Shared</string>
|
||||||
|
<string name="language">Language</string>
|
||||||
|
<string name="coverage">Coverage</string>
|
||||||
|
<string name="type">Type</string>
|
||||||
|
<string name="source">Source</string>
|
||||||
|
<string name="format">Format</string>
|
||||||
|
<string name="publisher">Publisher</string>
|
||||||
|
<string name="identifier">Identifier</string>
|
||||||
|
<string name="subject">Subject</string>
|
||||||
|
<string name="rights">Rights</string>
|
||||||
|
<string name="contributors">Contributors</string>
|
||||||
|
<string name="relations">Relations</string>
|
||||||
|
|
||||||
|
<!-- Audit log -->
|
||||||
|
<string name="auditlog_Acl">ACL</string>
|
||||||
|
<string name="auditlog_Comment">Comment</string>
|
||||||
|
<string name="auditlog_Document">Document</string>
|
||||||
|
<string name="auditlog_File">File</string>
|
||||||
|
<string name="auditlog_Group">Group</string>
|
||||||
|
<string name="auditlog_Route">Workflow</string>
|
||||||
|
<string name="auditlog_RouteModel">Workflow model</string>
|
||||||
|
<string name="auditlog_Tag">Tag</string>
|
||||||
|
<string name="auditlog_User">User</string>
|
||||||
|
<string name="auditlog_Webhook">Webhook</string>
|
||||||
|
<string name="auditlog_created">created</string>
|
||||||
|
<string name="auditlog_updated">updated</string>
|
||||||
|
<string name="auditlog_deleted">deleted</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1,12 +1,20 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppThemeDark" parent="Theme.AppCompat.NoActionBar">
|
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||||
|
<item name="windowActionBar">false</item>
|
||||||
|
<item name="windowNoTitle">true</item>
|
||||||
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style name="AppThemeDark" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||||
<item name="colorPrimary">@color/colorPrimary</item>
|
<item name="colorPrimary">@color/colorPrimary</item>
|
||||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||||
<item name="colorAccent">@color/colorAccent</item>
|
<item name="colorAccent">@color/colorAccent</item>
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||||
|
|
||||||
|
org.gradle.jvmargs=-Xmx3072m
|
||||||
|
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
# This option should only be used with decoupled projects. More details, visit
|
# This option should only be used with decoupled projects. More details, visit
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#Wed Nov 26 21:58:48 CET 2014
|
#Tue May 07 11:49:13 CEST 2019
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
|
||||||
|