Compare commits
711 commits
stay-awake
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
0236586e44 | ||
|
e13c7ae68c | ||
|
1d68123ea1 | ||
|
cf7b706582 | ||
|
c42d030d02 | ||
|
edfce9b492 | ||
|
e5d1ecd9f3 | ||
|
42a7813776 | ||
|
627faba0db | ||
|
a4ebaf52f5 | ||
|
660fe527f2 | ||
|
1a0ed7f298 | ||
062f5d3811 | |||
034c70542f | |||
|
ef244c3319 | ||
|
556505894c | ||
|
7c63ad66f9 | ||
|
26772a48eb | ||
|
2ded14deda | ||
|
465c082328 | ||
|
25e6660e8e | ||
f58afe92cb | |||
2b3ca0dff9 | |||
|
1e88a31f90 | ||
|
026d32c92a | ||
|
a28b9df6b5 | ||
d2bde99e1f | |||
f8ffedb5db | |||
4b7d17c02f | |||
0ae98f96b5 | |||
|
fb3d314ee2 | ||
|
b032b32db1 | ||
|
63f4b37655 | ||
|
bdc0423bf3 | ||
749f05816c | |||
06ebe95309 | |||
|
40ec4b0968 | ||
|
c4c9dc83c0 | ||
9a37db94ae | |||
|
0ba3a8cd7f | ||
|
0aeaf50c92 | ||
|
a9947ff9f7 | ||
|
c7324c020b | ||
|
46419b0960 | ||
|
c1c8729023 | ||
|
9bcc9ab690 | ||
|
0b6a2db2f1 | ||
61a04b034a | |||
|
ca42a5e7e0 | ||
400cda8dcd | |||
fe50ead4ee | |||
f1717cbd29 | |||
|
5394fde136 | ||
1ad324aa23 | |||
59b99a0a28 | |||
12dbac7480 | |||
258466beeb | |||
656e8ccfe7 | |||
22930628ae | |||
0d26167ee3 | |||
723105382d | |||
c9773fb5ab | |||
51227c1323 | |||
aac7fd7328 | |||
f3dd33c4ca | |||
|
83f0c54f8b | ||
71d1831ed3 | |||
|
29621b739a | ||
|
0b91948141 | ||
|
9d37635500 | ||
|
df6322c712 | ||
|
5de2e94f32 | ||
|
85732c6fbc | ||
|
a7ab0ed33a | ||
|
f152bbeb5b | ||
|
b469135877 | ||
|
a9b6bf5817 | ||
|
f91eb7936a | ||
|
5465d454f5 | ||
|
227c9146f2 | ||
|
ec2a1cf398 | ||
|
0a76ede35a | ||
|
99910a3f3a | ||
|
9ff7a8371d | ||
|
fa8a77a265 | ||
|
03fad6da6d | ||
|
0cc6f959fc | ||
|
033f96b366 | ||
|
7c56bbeae4 | ||
|
723371e9c9 | ||
|
2c53848d04 | ||
|
23df9d05ee | ||
|
0e7ae00a67 | ||
|
81cf5b6852 | ||
|
6d6b07b9a9 | ||
|
4445be3302 | ||
|
d21cbc455a | ||
|
32a55c48be | ||
|
99bb0c7b85 | ||
|
46433109a6 | ||
|
679426abc1 | ||
|
1f589cc2da | ||
|
856a16c640 | ||
|
ebe0143a8a | ||
|
e40cf02baa | ||
|
7c74c7c444 | ||
|
9d6ff8e7d7 | ||
|
3957cdbde4 | ||
|
5f16156f01 | ||
|
3c5bf563a6 | ||
|
40f60cf4be | ||
|
ea409c4220 | ||
|
016e0ffd51 | ||
|
8c725826cb | ||
|
01cbed675b | ||
|
da4393043f | ||
|
11f055932a | ||
|
0b350d083e | ||
|
79b901b63f | ||
|
6c78b9335e | ||
|
5e1d9c3bdb | ||
|
dc5e76e1e9 | ||
|
7ae3e25fb4 | ||
|
338fd3edd1 | ||
|
60c1ed6bb1 | ||
|
932f483b7a | ||
|
fcbf9d65f1 | ||
|
3a8615dbe3 | ||
|
fd46780b89 | ||
|
699d65ff4a | ||
|
dfb3c58153 | ||
|
29cc5968c0 | ||
|
964aa1a833 | ||
|
c979e23084 | ||
|
6fecd5e217 | ||
|
a6d469a999 | ||
|
af5a2b6c92 | ||
|
326a789b01 | ||
|
0c3afffbac | ||
|
b6fa0413d4 | ||
|
d243f130a2 | ||
|
effc1f0a3b | ||
|
985e7341dc | ||
|
b4f64aaedd | ||
|
55d046d318 | ||
|
7c8db1b739 | ||
|
1179c86a06 | ||
|
833f5f1df7 | ||
|
2d58239c34 | ||
|
49b7047ac9 | ||
|
1ff1426b8b | ||
|
5ad93a777a | ||
|
a5e5e36083 | ||
|
8349cb4377 | ||
|
313a4d3827 | ||
|
f33162801c | ||
|
3786a0cb3f | ||
|
68a2adc38d | ||
|
fb4ce26dd3 | ||
|
7bfa4a54e0 | ||
|
4929efadeb | ||
|
f8bc0df74a | ||
|
4a04a55513 | ||
|
fe9cd73798 | ||
|
7996291d0f | ||
|
b8e5fb189c | ||
|
37518d06a6 | ||
|
f6d6352879 | ||
|
02138e9115 | ||
|
5da08c2a15 | ||
|
3c20eb7ca8 | ||
|
65567b9a19 | ||
|
5309dda94b | ||
|
02573e8d4e | ||
|
c509616db9 | ||
|
57f2d71eca | ||
|
fb2c0a42c1 | ||
|
c6f50b8071 | ||
|
54f4ce2dfe | ||
|
fcdf6cc4ed | ||
|
0f4e0eaf58 | ||
|
2fea47af1b | ||
|
25db7a5904 | ||
|
b5b0ec5ed1 | ||
|
b2e41a6421 | ||
|
a92712d158 | ||
|
fa59ca0bb1 | ||
|
22f7a956dc | ||
|
2086a72e8c | ||
|
84cfcb5150 | ||
|
5a2596e9de | ||
|
bf87aa723d | ||
|
4b744f300d | ||
|
8573b3f6d9 | ||
|
489c410b14 | ||
|
a4dcec0540 | ||
|
9da9d22a71 | ||
|
a59d32b29d | ||
|
7657a6e4da | ||
|
9f4f3c9475 | ||
|
8a48982ca5 | ||
|
0400d12e52 | ||
|
88d385ab0d | ||
|
7e985f5823 | ||
|
346ba3c8ef | ||
|
406fbb04a4 | ||
|
4407d8f561 | ||
|
f43364a71a | ||
|
f3242bf7db | ||
|
a88abbb20f | ||
|
db655d766f | ||
|
88d84caad9 | ||
|
fd71c3c013 | ||
|
90b0a40824 | ||
|
0d01ad0b22 | ||
|
f476239f3a | ||
|
555b8320a6 | ||
|
9e45b8ee5c | ||
|
d336e6188e | ||
|
97ee0d7f1d | ||
|
9ef5151fa4 | ||
|
4d4868377b | ||
|
dcb213fe8a | ||
|
972d74f3e2 | ||
|
9b85f2ed82 | ||
|
4f37fdeb67 | ||
|
76063e21cb | ||
|
6bd869b542 | ||
|
162a47fd26 | ||
|
481d6e88cc | ||
|
dce28370b5 | ||
|
2f635395bc | ||
|
bb9cacb71e | ||
|
5a76303f4d | ||
|
1379d2883f | ||
|
56fc96aafa | ||
|
fa9e0c7d54 | ||
|
8bd4ff9102 | ||
|
2ffe9ae885 | ||
|
fbf8671012 | ||
|
0aba35d9bd | ||
|
a2b05fc227 | ||
|
a1859c0333 | ||
|
ded3735973 | ||
|
612ff05983 | ||
|
056b8b9aac | ||
|
1eab3a0627 | ||
|
36947e8470 | ||
|
5a2f250e39 | ||
|
d3a4c50e76 | ||
|
db8e1d6ba8 | ||
|
d668c8666e | ||
|
d2df4ddf16 | ||
|
78e578c5e2 | ||
|
df1f20cb30 | ||
|
91ec56898a | ||
|
136e4328d7 | ||
|
bd9df7b10c | ||
|
942e51a36f | ||
|
b719d18a70 | ||
|
b350487fb9 | ||
|
388ea83e45 | ||
|
29719c0764 | ||
|
9339a2cdf5 | ||
|
98307c59e4 | ||
|
3262835f1d | ||
|
b9917059ed | ||
|
a9c0ae8f37 | ||
|
5c69119b38 | ||
|
9fded3d3a8 | ||
|
109913c9ca | ||
|
cefa87767a | ||
|
2adb002c28 | ||
|
f559b4892b | ||
|
c26ce4cd6b | ||
|
93da676e6b | ||
|
23d4ac6c02 | ||
|
9a2b2b0ca8 | ||
|
4f65b3b666 | ||
|
f240845927 | ||
|
ee4fd1bdbb | ||
|
72f3fddcb2 | ||
|
bc2e92a285 | ||
|
d3556d293d | ||
|
2eb75929aa | ||
|
d76d9bea0f | ||
|
edd9db186b | ||
|
747e35dd4b | ||
|
8fabca8a0d | ||
|
2540b4e28c | ||
|
c8fe64e83f | ||
|
545b716f24 | ||
|
330c642f00 | ||
|
0e64c620dc | ||
|
b422c15b86 | ||
|
694cc0f453 | ||
|
dd55c91000 | ||
|
612026f937 | ||
|
b8e512855d | ||
|
4e9eb36e40 | ||
|
43478b646e | ||
|
d3f721fcce | ||
|
8647c24f23 | ||
|
88160cb621 | ||
|
5e8584af79 | ||
|
eae863172d | ||
|
57267dc944 | ||
|
02f69c2a2c | ||
|
d1043bc97e | ||
|
f0d1111c47 | ||
|
e6471f3d54 | ||
|
f33f70d723 | ||
|
3957ec27e4 | ||
|
4050f41ce2 | ||
|
15f33145a7 | ||
|
cca6e41369 | ||
|
2ff093717c | ||
|
525eba5be1 | ||
|
426bf9c05e | ||
|
3497f9d0fc | ||
|
6ebe312651 | ||
|
45aaf50c40 | ||
|
6be12bd31c | ||
|
bae1777df6 | ||
|
250a83347c | ||
|
aef9fd8391 | ||
|
cb16582722 | ||
|
b2f2ee5453 | ||
|
9715e03971 | ||
|
aae881cec8 | ||
|
366b24bf02 | ||
|
58f6a26bff | ||
|
1a409407c9 | ||
|
4669d17cea | ||
|
8ae148ec90 | ||
|
a432e91996 | ||
|
7ae58badd9 | ||
|
e2e78713df | ||
|
a734690d0d | ||
|
9688c09002 | ||
|
01cdb18b46 | ||
|
063d782001 | ||
|
7369eaec4f | ||
|
532b35e9f3 | ||
|
27f33d1883 | ||
|
2e3fbb0fd3 | ||
|
1dcaaa7169 | ||
|
0a8f507f6f | ||
|
41e9efb8e5 | ||
|
034069320f | ||
|
fe6e1db689 | ||
|
20fd359fb1 | ||
|
8cdfb8a30b | ||
|
1f832d6511 | ||
|
3210bab4e3 | ||
|
d9991cce79 | ||
|
22c30f334d | ||
|
9ebe33a419 | ||
|
257fc749ee | ||
|
352789f79d | ||
|
ade5cb34fb | ||
|
42a697591d | ||
|
23fd7cb7cd | ||
|
8fc499582b | ||
|
ef9a999994 | ||
|
94aee83936 | ||
|
4435828ff7 | ||
|
fc2c53f840 | ||
|
0a4fd6be93 | ||
|
3575e1674c | ||
|
5de6ea4f11 | ||
|
b0ed187bb4 | ||
|
08b004f6a5 | ||
|
40edb2069a | ||
|
98eaf699bc | ||
|
64ef10a10c | ||
|
9280236743 | ||
|
bcff42c449 | ||
|
8f345174ab | ||
|
4cf12cfd15 | ||
|
472d07721f | ||
|
f6e21b6428 | ||
|
cbee948e09 | ||
|
4b0f8f3166 | ||
|
35ed5879bc | ||
|
42f55db3f4 | ||
|
58e0ecce1f | ||
|
0b7c6cd75f | ||
|
299ab8d7a0 | ||
|
2d5798e182 | ||
|
aa2d47cb11 | ||
|
1dee780d0b | ||
|
530afe2714 | ||
|
0948d32fe1 | ||
|
1f4b9ce082 | ||
|
84752798f3 | ||
|
66dc268efc | ||
|
40fea18a46 | ||
|
31ee65fc98 | ||
|
ca94e7971b | ||
|
8d6d88de5f | ||
|
1a3767e599 | ||
|
c12c9e2ac6 | ||
|
a6e0c9b3ab | ||
|
9219495081 | ||
|
42f3cfb155 | ||
|
8b8756cbdb | ||
|
978ee5a334 | ||
|
fba20712b2 | ||
|
3176c3dc8c | ||
|
c6f0a41559 | ||
|
910e261ad9 | ||
|
fd6ebae7c0 | ||
|
2eec79dd31 | ||
|
0e401fd18b | ||
|
add07be887 | ||
|
903cb02919 | ||
|
55ce5c36d8 | ||
|
c7392af6b9 | ||
|
453ce8f4ac | ||
|
ced51ade64 | ||
|
18cf86b75c | ||
|
b1c4311990 | ||
|
2a229dae3b | ||
|
f7ba5ebe45 | ||
|
444649c3b2 | ||
|
3bc97f2739 | ||
|
3433ec547e | ||
|
02d1583d6c | ||
|
ec6461ba42 | ||
|
f65a62d61f | ||
|
fcb7dae081 | ||
|
7077a22be8 | ||
|
f82c2683e2 | ||
|
199fc0d60c | ||
|
5d1af66c38 | ||
|
f7bcec0456 | ||
|
af4a1f3a69 | ||
|
27e8b234fc | ||
|
8634e730ff | ||
|
0955a9fda0 | ||
|
84a5c19e27 | ||
|
431eacad78 | ||
|
fe4d3c79d7 | ||
|
d30d80abd8 | ||
|
f7e057833b | ||
|
c0a6c2566a | ||
|
ed41f96ed2 | ||
|
48cf0c00f7 | ||
|
460b1485a8 | ||
|
d8b42b9d87 | ||
|
ed57ef6d5d | ||
|
d5c1122052 | ||
|
5ac48cd171 | ||
|
436b21ab51 | ||
|
742baebe94 | ||
|
e2b6d25aa8 | ||
|
fb225390c6 | ||
|
9b820dad2b | ||
|
5e6cd6f4b4 | ||
|
1b653eb554 | ||
|
bcbbf5616d | ||
|
1701562c42 | ||
|
91b86c6566 | ||
|
607b13cf7f | ||
|
a28475c6a0 | ||
|
17bdadea16 | ||
|
9a5db3e83f | ||
|
ac8a2f549b | ||
|
595c7734eb | ||
|
2fcacef6d4 | ||
|
e7c075edb7 | ||
|
12280c7321 | ||
|
2ed3bacd98 | ||
|
e6e63622e5 | ||
|
c5640ec13f | ||
|
741ad78602 | ||
|
bd53d1435d | ||
|
6eaea9221b | ||
|
f0d14bc440 | ||
|
844498ee46 | ||
|
b6468ec924 | ||
|
117e7e9310 | ||
|
bba5bf94b8 | ||
|
710254dc0f | ||
|
5a720c1a00 | ||
|
b61bf2a46b | ||
|
290114f3f2 | ||
|
3a59ec54ba | ||
|
066037f1a5 | ||
|
390f6eaca6 | ||
|
52be4901db | ||
|
a48260a998 | ||
|
fa232a4cbf | ||
|
4e6d012a7d | ||
|
4cf5f661c4 | ||
|
32f884e547 | ||
|
c992c3ed00 | ||
|
703931a5a1 | ||
|
55fefdd96d | ||
|
077c928b27 | ||
|
eef961926f | ||
|
3b26021221 | ||
|
e6ca239acd | ||
|
14f73dbb48 | ||
|
9bf9a1a1eb | ||
|
74ccbccf45 | ||
|
921f58e8c0 | ||
|
935bcaeb85 | ||
|
e6748dbc18 | ||
|
aa7a1f28ce | ||
|
282ab1d2b9 | ||
|
ab879f8db3 | ||
|
875028c7b0 | ||
|
2459aa70e0 | ||
|
94b33d1d92 | ||
|
063df54e94 | ||
|
74d584fdcc | ||
|
907a4580fc | ||
|
c9ab840b97 | ||
|
954986edee | ||
|
f471ef2683 | ||
|
919eacdec7 | ||
|
2f11b6c67c | ||
|
08a95d4f07 | ||
|
3abdbe6a58 | ||
|
3b6a1843c0 | ||
|
3fb66af0fe | ||
|
4fbd55c184 | ||
|
a4dbc26e70 | ||
|
769ae8af21 | ||
|
5f1befe443 | ||
|
72d6ceb259 | ||
|
ce2bd3260b | ||
|
08d2832198 | ||
|
c0270b9908 | ||
|
37ad9441f2 | ||
|
de9112cc8a | ||
|
8786bdbf5e | ||
|
756a96e92c | ||
|
62a17f722f | ||
|
8607f1000b | ||
|
c031e56284 | ||
|
fe6ba8ac0d | ||
|
3473fb995c | ||
|
1ce981c147 | ||
|
be2f08553b | ||
|
d4935a4968 | ||
|
90a3d8ad2b | ||
|
b70a4427e0 | ||
|
1523d62362 | ||
|
a06f384e1a | ||
|
233515474f | ||
|
b9933dd706 | ||
|
2798a0f56a | ||
|
01ffec0a0c | ||
|
92655b4417 | ||
|
4f275a5405 | ||
|
7f9166d1ae | ||
|
e3370bf73e | ||
|
7453c60052 | ||
|
5e52b47fc0 | ||
|
da36f4966e | ||
|
62295b55fc | ||
|
d64ab2f7ea | ||
|
f104ac0cab | ||
|
a30dd23ed8 | ||
|
68f60f5b8a | ||
|
fb161f3d24 | ||
|
de51bbffc0 | ||
|
cc65c694c0 | ||
|
348b26d6ec | ||
|
5ca6dd1ca0 | ||
|
03ea136905 | ||
|
7e6c871261 | ||
|
9299205379 | ||
|
3334f487d7 | ||
|
26c1677993 | ||
|
07798dae02 | ||
|
18371912e5 | ||
|
49223f98f6 | ||
|
3250ebae5c | ||
|
b789a3a066 | ||
|
c4fd46212e | ||
|
39bbd111fa | ||
|
bdd6a8df27 | ||
|
d8b0ff6fca | ||
|
158419f15f | ||
|
d34538a868 | ||
|
001b7bbef0 | ||
|
58f154b3c3 | ||
|
1e89a4357a | ||
|
dffe4d708f | ||
|
2f5376b864 | ||
|
ea0984bc7f | ||
|
b7738e7fb8 | ||
|
e2b99bafaf | ||
|
3eb63a6dd7 | ||
|
258c533ff0 | ||
|
4bcb96055b | ||
|
71283df6c5 | ||
|
e0b94a0487 | ||
|
81ffb53062 | ||
|
9314c56e5b | ||
|
4dc05e2e10 | ||
|
b6f77bbf8b | ||
|
e623635be5 | ||
|
62805434f1 | ||
|
2b634471dc | ||
|
53441b5554 | ||
|
cc0cc94dc5 | ||
|
7c615b5cff | ||
|
fd7de65c19 | ||
|
54602d8a6c | ||
|
e620c41e17 | ||
|
f26820ef75 | ||
|
1b83fddfe6 | ||
|
be404d0e55 | ||
|
5213084fb1 | ||
|
473c603451 | ||
|
21810b05aa | ||
|
9453ce4ec2 | ||
|
d38f56b9fe | ||
|
d3eac32216 | ||
|
04f6c14e86 | ||
|
732af7c334 | ||
|
fd0d188030 | ||
|
2c078307dc | ||
|
53e0400e0c | ||
|
01cc85f817 | ||
|
f1b14f41ae | ||
|
42398eee96 | ||
|
c3f5fee378 | ||
|
1e4455482c | ||
|
9662df3c74 | ||
|
f9a824ca2c | ||
|
a8ad2a6a22 | ||
|
d108cb109d | ||
|
1e478aa3d5 | ||
|
753f322053 | ||
|
232049422a | ||
|
fa0aaf431e | ||
|
0cb19d833c | ||
|
6b731486cb | ||
|
cd0eace631 | ||
|
11058bc05a | ||
|
e15c171640 | ||
|
7dfe7ddc3e | ||
|
33878bb480 | ||
|
8282c6e8dc | ||
|
d10b6dc227 | ||
|
ba42aa061b | ||
|
b4b1eb4bc0 | ||
|
775a31cecb | ||
|
65c3871b4a | ||
|
283466ae95 | ||
|
6a51be4806 | ||
|
78a71cfbab | ||
|
e6fd5885aa | ||
|
ef1f824cd8 | ||
|
2f52a87e2b | ||
|
72fd008dfc | ||
|
225eb76899 | ||
|
2e970f2003 | ||
|
0f28db0115 | ||
|
f7c6f8a399 | ||
|
23641b24a1 | ||
|
19a17ed3f3 | ||
|
d0f33969eb | ||
|
461b724d15 | ||
|
13a91fa0e7 | ||
|
d619b97ee4 | ||
|
13f21916f8 | ||
|
653a35500c | ||
|
c83fcda617 | ||
|
fe0b390a87 | ||
|
4e680a9a3f | ||
|
ff399a524c | ||
|
039aca14bf | ||
|
d0ebbc7170 | ||
|
4aa8ff3d8a | ||
|
d2d6fac778 | ||
|
a0a2e6bdca | ||
|
c10819b12e | ||
|
fe4b330479 | ||
|
00287ea89c | ||
|
88b79236e7 | ||
|
a2bd181911 | ||
|
1317f6532e | ||
|
87255e123a | ||
|
4fbdeb6366 | ||
|
45bcc4f33d | ||
|
b9502d35ee | ||
|
25efbb8bc2 | ||
|
72582c26f4 | ||
|
f7e005da46 | ||
|
bc1d4ace30 | ||
|
335b8ed0c9 | ||
|
c327d57872 | ||
|
aee027219a | ||
|
8b49b0363c | ||
|
a1f0e1c1c5 | ||
|
0d21174220 | ||
|
bf9c4e1e5e | ||
|
8e03b16243 | ||
|
6508c20a0d | ||
|
2cd86a95d9 | ||
|
44510901ac | ||
|
6e54988978 | ||
|
63db26afc8 | ||
|
aafe7c1308 |
102
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
name: Fernschreiber build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- '*'
|
||||
# to prevent secrets leaking,
|
||||
# we don't build on PRs
|
||||
#pull_request:
|
||||
# branches:
|
||||
# - master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'true'
|
||||
|
||||
- name: Prepare
|
||||
run: mkdir output
|
||||
|
||||
- name: Fetch TDLib
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: "Wunderfitz/td"
|
||||
file: "tdlib.zip"
|
||||
target: tdlib/tdlib.zip
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Decompress TDLib
|
||||
uses: TonyBogdanov/zip@1.0
|
||||
with:
|
||||
args: unzip -qq ./tdlib/tdlib.zip -d ./tdlib
|
||||
|
||||
- name: Set Secrets
|
||||
uses: DamianReeves/write-file-action@master
|
||||
with:
|
||||
path: ./src/tdlibsecrets.h
|
||||
contents: |
|
||||
#ifndef TDLIBSECRETS_H
|
||||
#define TDLIBSECRETS_H
|
||||
const char TDLIB_API_ID[] = "${{secrets.TDLIB_API_ID}}";
|
||||
const char TDLIB_API_HASH[] = "${{secrets.TDLIB_API_HASH}}";
|
||||
#endif // TDLIBSECRETS_H
|
||||
write-mode: overwrite
|
||||
|
||||
- name: Build armv7hl
|
||||
id: build_armv7hl
|
||||
uses: coderus/github-sfos-build@master
|
||||
with:
|
||||
release: 4.4.0.58
|
||||
|
||||
- name: Build i486
|
||||
id: build_i486
|
||||
uses: coderus/github-sfos-build@master
|
||||
with:
|
||||
release: 4.4.0.58
|
||||
arch: i486
|
||||
|
||||
- name: Build aarch64
|
||||
id: build_aarch64
|
||||
uses: coderus/github-sfos-build@master
|
||||
with:
|
||||
release: 4.4.0.58
|
||||
arch: aarch64
|
||||
|
||||
- name: Upload build result
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: rpm-build-result
|
||||
path: RPMS
|
||||
|
||||
- name: Create release
|
||||
if: contains(github.ref, 'v')
|
||||
run: |
|
||||
set -x
|
||||
assets=()
|
||||
for asset in RPMS/*.rpm; do
|
||||
assets+=("-a" "$asset")
|
||||
done
|
||||
tag_name="${GITHUB_REF##*/}"
|
||||
gh release create "$tag_name" "${assets[@]}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create prerelease
|
||||
if: contains(github.ref, 'pre')
|
||||
run: |
|
||||
set -x
|
||||
assets=()
|
||||
for asset in RPMS/*.rpm; do
|
||||
assets+=("-a" "$asset")
|
||||
done
|
||||
tag_name="${GITHUB_REF##*/}"
|
||||
gh release create "$tag_name" -p -n "This is a pre-release for testing purposes only. It may or may not be unstable." "${assets[@]}"
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
3
.gitignore
vendored
|
@ -53,3 +53,6 @@ compile_commands.json
|
|||
|
||||
# TDLib API Secrets
|
||||
tdlibsecrets.h
|
||||
|
||||
#Convinience scripts
|
||||
*.sh
|
||||
|
|
45
README.md
|
@ -1,6 +1,7 @@
|
|||
# Fernschreiber
|
||||
A Telegram client for Sailfish OS
|
||||
|
||||
[![Fernschreiber build](https://github.com/Wunderfitz/harbour-fernschreiber/actions/workflows/main.yml/badge.svg)](https://github.com/Wunderfitz/harbour-fernschreiber/actions/workflows/main.yml)
|
||||
## Authors
|
||||
Sebastian J. Wolf [sebastian@ygriega.de](mailto:sebastian@ygriega.de) and several contributors
|
||||
|
||||
|
@ -10,19 +11,27 @@ Fernschreiber wouldn't be the same without all the people helping in making it b
|
|||
|
||||
### Code (Features, Bugfixes, Optimizations etc.)
|
||||
- Chat list model, chat model, notifications, TDLib receiver, animated stickers, project dependencies, qml/c++ optimizations, chatPhoto, TDLibFile, code reviews, logging categories: [Slava Monich](https://github.com/monich)
|
||||
- Chat info page, performance improvements to chat page, location support, app initialization/registration with Telegram, project dependencies, emoji handling, qml/js optimizations, multi-message actions, i18n fixes, chat permission handling, code reviews, logging categories: [jgibbon](https://github.com/jgibbon)
|
||||
- Copy message to clipboard [Christian Stemmle](https://github.com/chstem)
|
||||
- Chat info page, performance improvements to chat page, location support, app initialization/registration with Telegram, project dependencies, emoji handling, qml/js optimizations, multi-message actions, i18n fixes, chat permission handling, code reviews, logging categories, bot support, github build: [jgibbon](https://github.com/jgibbon)
|
||||
- Copy message to clipboard: [Christian Stemmle](https://github.com/chstem)
|
||||
- Hide send message button if send-by-enter is switched on, focus text input on entering a chat: [santhoshmanikandan](https://github.com/santhoshmanikandan)
|
||||
- Integration of logout and sesison options to settings page, search results optimization, highlight unread conversations: [Peter G.](https://github.com/nephros)
|
||||
- Option to always append last message in notifications: [Johannes Bachmann](https://github.com/dscheinah)
|
||||
- Option to jump to quoted message, widescreen UI adjustments: [Mikhail Barashkov](https://github.com/mbarashkov)
|
||||
|
||||
This list might not be complete. In case I forgot something/somebody, please let me know or create a PR, thanks! :)
|
||||
|
||||
### Logo/Icon
|
||||
- Designed by [Matteo](https://github.com/iamnomeutente)
|
||||
- Designed by [Matteo](https://github.com/iamnomeutente), adjustments by [Slava Monich](https://github.com/monich)
|
||||
|
||||
### Translations
|
||||
- Chinese: [dashinfantry](https://github.com/dashinfantry)
|
||||
- Finnish: [jorm1s](https://github.com/jorm1s)
|
||||
- French: [Patrick Hervieux](https://github.com/pherjung), [Nicolas Bourdais](https://github.com/nbourdais)
|
||||
- Hungarian: [edp17](https://github.com/edp17)
|
||||
- Italian: [Matteo](https://github.com/iamnomeutente)
|
||||
- Polish: [atlochowski](https://github.com/atlochowski)
|
||||
- Russian: [Rustem Abzalov](https://github.com/arustg) and [Slava Monich](https://github.com/monich)
|
||||
- Slovak: [okruhliak](https://github.com/okruhliak)
|
||||
- Spanish: [carlosgonz](https://github.com/GNUuser)
|
||||
- Swedish: [Åke Engelbrektson](https://github.com/eson57)
|
||||
|
||||
|
@ -30,6 +39,7 @@ Fernschreiber wouldn't be the same without all the people helping in making it b
|
|||
Licensed under GNU GPLv3
|
||||
|
||||
## Build
|
||||
### Local build
|
||||
Simply clone this repository and ensure to have all [submodules](https://git-scm.com/docs/git-submodule) imported as well (e.g. by using `git submodule update --init`). Then use the project file `harbour-fernschreiber.pro` to import the sources in your SailfishOS IDE. To build and run Fernschreiber or an application which is based on Fernschreiber, you need to create the file `harbour-fernschreiber/src/tdlibsecrets.h` and enter the required constants in the following format:
|
||||
|
||||
```
|
||||
|
@ -42,13 +52,39 @@ const char TDLIB_API_HASH[] = "1234567890abcdef1234567890abcdef";
|
|||
|
||||
You get the Telegram API ID and hash as soon as you've registered your own application on [https://my.telegram.org](https://my.telegram.org).
|
||||
|
||||
Moreover, you need to have a compiled version of [TDLib](https://github.com/tdlib/td) in the sub-directory `tdlib`. This sub-directory must contain another sub-directory that fits to the target device architecture (e.g. armv7hl, i486). Within this directory, there needs to be a folder called `lib` that contains at least `libtdjson.so`. For armv7hl the relative path would consequently be `tdlib/armv7hl/lib`.
|
||||
Moreover, you need to have a compiled version of [TDLib 1.8.21](https://github.com/tdlib/td) or higher in the sub-directory `tdlib`. This sub-directory must contain another sub-directory that fits to the target device architecture (e.g. armv7hl, i486). Within this directory, there needs to be a folder called `lib` that contains at least `libtdjson.so`. For armv7hl the relative path would consequently be `tdlib/armv7hl/lib`.
|
||||
|
||||
You may just want to download the [tdlib.zip from our fork](https://github.com/Wunderfitz/td/releases) to just use the exact version of the latest official Fernschreiber release. To use it, you need to extract it into your local `tdlib/` folder as described above. If so, you're done and can compile Fernschreiber using the Sailfish SDK. If you want to build TDLib for yourself, please keep on reading.
|
||||
|
||||
In case you want to use the same codebase which was used to compile the library that is shipped with Fernschreiber, please [check out the fork](https://github.com/Wunderfitz/td), be sure to use the branch `fernschreiber` and compile these sources using the following commands (be sure to have the Sailfish OS build engine running):
|
||||
|
||||
- `alias sfdk=~/SailfishOS/bin/sfdk`
|
||||
- `sfdk config target=SailfishOS-4.4.0.58-armv7hl` (this compiles the sources on SFOS 4.4 and ARM - the target needs to be adjusted according to the running SDK engine and the platform)
|
||||
- `mkdir build`
|
||||
- `cd build`
|
||||
- `sfdk build-init`
|
||||
- `sfdk build-shell cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:PATH=../tdlib -DTD_ENABLE_LTO=ON ..` (in case of compilation issues, try removing the flag `-DTD_ENABLE_LTO=ON`)
|
||||
- `sfdk build-shell cmake --build . --target install`
|
||||
|
||||
You'll find the compiled library in the directory `td/tdlib`.
|
||||
|
||||
### Github Action
|
||||
Please read the "Local build" section anyway to understand what's going on before continuing. If you want to automatically build your fork on Github, you'll still need to get a Telegram API ID and hash. These are then [added as project secrets](https://docs.github.com/en/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository) named `TDLIB_API_ID` and `TDLIB_API_HASH`.
|
||||
|
||||
By default, only commits to the master branch will be built. You may [change that for your fork](https://docs.github.com/en/actions/quickstart), but please don't create a pull request to the official repository changing the github action without consulting the [Fernschreiber contributors](https://github.com/Wunderfitz/harbour-fernschreiber/issues/162) first.
|
||||
|
||||
If you push a tag containing the letter "v" (for example "v0.99.3"), a github release will be created allowing easy download of the resulting rpms. If the tag is named for example "pre-0.99.3", the resulting release is marked as a pre-release for testing purposes.
|
||||
|
||||
|
||||
## Debug
|
||||
Fernschreiber does only output a few TDLib messages by default. To get its own debug log messages, you can either run a debug build to see all of them or use the environment variable `QT_LOGGING_RULES` to specify/filter which messages you'd like to see.
|
||||
|
||||
Run `QT_LOGGING_RULES="fernschreiber.*=true" harbour-fernschreiber` to see all messages or replace the `*` with specific logging categories. You'll find the logging category inside the corresponding `.cpp` file for backend usage or you can use `JS` to only see frontend messages.
|
||||
|
||||
You can append ` &> fernschreiber.log` to the command to create a text file containing the debug messages.
|
||||
|
||||
**Please be aware that debug messages will most likely include personal information** including (but not limited to) chat content and user ids/names of yourself and all your chat partners. Do not share it publicly and, at your discretion, try to remove private info even from the parts you do share with a trusted person.
|
||||
|
||||
## Contribute
|
||||
|
||||
If you want to contribute bug fixes, improvements, new features etc. please create a pull request (PR). PRs are always welcome and will be reviewed as soon as possible, but may take some time. :)
|
||||
|
@ -60,5 +96,6 @@ This project uses
|
|||
- The Telegram Database Library (TDLib) - available on [GitHub.com](https://github.com/tdlib/td). Thanks for making it available under the conditions of the Boost Software License 1.0! Details about the license of TDLib in [its license file](https://github.com/tdlib/td/blob/master/LICENSE_1_0.txt).
|
||||
- Emoji parsing and artwork by [Twitter Emoji (Twemoji)](http://twitter.github.io/twemoji/), copyright 2018 Twitter, Inc and other contributors, Code licensed under the [MIT License](http://opensource.org/licenses/MIT), Graphics licensed under [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/)
|
||||
- Animated sticker parsing and animation by [rlottie](https://github.com/Samsung/rlottie), copyright 2020 Samsung Electronics Co., Ltd. and [other contributors](https://github.com/Samsung/rlottie/blob/master/AUTHORS), Code licensed under the [MIT License](https://github.com/Samsung/rlottie/blob/master/licenses/COPYING.MIT), some rlottie components [licensed under other licenses](https://github.com/Samsung/rlottie/blob/master/COPYING).
|
||||
- Reverse geocoding for location attachments by [OpenStreetMap Nominatim](https://wiki.openstreetmap.org/wiki/Nominatim).
|
||||
|
||||
Thanks to the maintainers of the used components and - again - all contributors to Fernschreiber!
|
||||
|
|
BIN
db/emojis.db
3288
doc/emojis.md
Normal file
|
@ -4,3 +4,8 @@ X-Nemo-Application-Type=silica-qt5
|
|||
Icon=harbour-fernschreiber
|
||||
Exec=harbour-fernschreiber
|
||||
Name=Fernschreiber
|
||||
|
||||
[X-Sailjail]
|
||||
Permissions=Audio;Documents;Downloads;Internet;Location;MediaIndexing;Microphone;Music;Pictures;PublicDir;RemovableMedia;UserDirs;Videos
|
||||
OrganizationName=de.ygriega
|
||||
ApplicationName=fernschreiber
|
||||
|
|
|
@ -16,12 +16,13 @@ CONFIG += sailfishapp sailfishapp_i18n
|
|||
|
||||
PKGCONFIG += nemonotifications-qt5 zlib
|
||||
|
||||
QT += core dbus sql
|
||||
QT += core dbus sql multimedia positioning
|
||||
|
||||
DEFINES += QT_STATICPLUGIN
|
||||
|
||||
SOURCES += src/harbour-fernschreiber.cpp \
|
||||
src/appsettings.cpp \
|
||||
src/chatpermissionfiltermodel.cpp \
|
||||
src/chatlistmodel.cpp \
|
||||
src/chatmodel.cpp \
|
||||
src/contactsmodel.cpp \
|
||||
|
@ -38,37 +39,89 @@ SOURCES += src/harbour-fernschreiber.cpp \
|
|||
src/tdlibfile.cpp \
|
||||
src/tdlibreceiver.cpp \
|
||||
src/tdlibwrapper.cpp \
|
||||
src/textfiltermodel.cpp \
|
||||
src/tgsplugin.cpp
|
||||
|
||||
DISTFILES += qml/harbour-fernschreiber.qml \
|
||||
qml/components/AudioPreview.qml \
|
||||
qml/components/BackgroundImage.qml \
|
||||
qml/components/ChatListViewItem.qml \
|
||||
qml/components/ContactSync.qml \
|
||||
qml/components/DocumentPreview.qml \
|
||||
qml/components/GamePreview.qml \
|
||||
qml/components/ImagePreview.qml \
|
||||
qml/components/InformationEditArea.qml \
|
||||
qml/components/InformationTextItem.qml \
|
||||
qml/components/InReplyToRow.qml \
|
||||
qml/components/InlineQuery.qml \
|
||||
qml/components/LocationPreview.qml \
|
||||
qml/components/MessageListViewItem.qml \
|
||||
qml/components/MessageListViewItemSimple.qml \
|
||||
qml/components/MessageOverlayFlickable.qml \
|
||||
qml/components/MessageViaLabel.qml \
|
||||
qml/components/MultilineEmojiLabel.qml \
|
||||
qml/components/PinnedMessageItem.qml \
|
||||
qml/components/PollPreview.qml \
|
||||
qml/components/PressEffect.qml \
|
||||
qml/components/ProfilePictureList.qml \
|
||||
qml/components/ReplyMarkupButtons.qml \
|
||||
qml/components/StickerPicker.qml \
|
||||
qml/components/PhotoTextsListItem.qml \
|
||||
qml/components/WebPagePreview.qml \
|
||||
qml/components/chatInformationPage/ChatInformationEditArea.qml \
|
||||
qml/components/StickerSetOverlay.qml \
|
||||
qml/components/TDLibImage.qml \
|
||||
qml/components/TDLibMinithumbnail.qml \
|
||||
qml/components/TDLibPhoto.qml \
|
||||
qml/components/TDLibThumbnail.qml \
|
||||
qml/components/VoiceNoteOverlay.qml \
|
||||
qml/components/chatInformationPage/ChatInformationPageContent.qml \
|
||||
qml/components/chatInformationPage/ChatInformationProfilePicture.qml \
|
||||
qml/components/chatInformationPage/ChatInformationProfilePictureList.qml \
|
||||
qml/components/chatInformationPage/ChatInformationTabItemBase.qml \
|
||||
qml/components/chatInformationPage/ChatInformationTabItemDebug.qml \
|
||||
qml/components/chatInformationPage/ChatInformationTabItemMembersGroups.qml \
|
||||
qml/components/chatInformationPage/ChatInformationTabItemSettings.qml \
|
||||
qml/components/chatInformationPage/ChatInformationTabView.qml \
|
||||
qml/components/chatInformationPage/ChatInformationTextItem.qml \
|
||||
qml/components/chatInformationPage/EditGroupChatPermissionsColumn.qml \
|
||||
qml/components/chatInformationPage/EditSuperGroupSlowModeColumn.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResult.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultAnimation.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultArticle.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultAudio.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultContact.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultDefaultBase.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultDocument.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultGame.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultLocation.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultPhoto.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultSticker.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultVenue.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultVideo.qml \
|
||||
qml/components/inlineQueryResults/InlineQueryResultVoiceNote.qml \
|
||||
qml/components/messageContent/MessageAnimatedEmoji.qml \
|
||||
qml/components/messageContent/MessageAnimation.qml \
|
||||
qml/components/messageContent/MessageAudio.qml \
|
||||
qml/components/messageContent/MessageContentBase.qml \
|
||||
qml/components/messageContent/MessageContentFileInfoBase.qml \
|
||||
qml/components/messageContent/MessageDocument.qml \
|
||||
qml/components/messageContent/MessageGame.qml \
|
||||
qml/components/messageContent/MessageLocation.qml \
|
||||
qml/components/messageContent/MessagePhoto.qml \
|
||||
qml/components/messageContent/MessagePoll.qml \
|
||||
qml/components/messageContent/MessageSticker.qml \
|
||||
qml/components/messageContent/MessageVenue.qml \
|
||||
qml/components/messageContent/MessageVideoNote.qml \
|
||||
qml/components/messageContent/MessageVideo.qml \
|
||||
qml/components/messageContent/MessageVoiceNote.qml \
|
||||
qml/components/messageContent/SponsoredMessage.qml \
|
||||
qml/components/messageContent/WebPagePreview.qml \
|
||||
qml/components/settingsPage/Accordion.qml \
|
||||
qml/components/settingsPage/AccordionItem.qml \
|
||||
qml/components/settingsPage/ResponsiveGrid.qml \
|
||||
qml/components/settingsPage/SettingsAppearance.qml \
|
||||
qml/components/settingsPage/SettingsBehavior.qml \
|
||||
qml/components/settingsPage/SettingsPrivacy.qml \
|
||||
qml/components/settingsPage/SettingsSession.qml \
|
||||
qml/components/settingsPage/SettingsStorage.qml \
|
||||
qml/components/settingsPage/SettingsUserProfile.qml \
|
||||
qml/js/debug.js \
|
||||
qml/js/functions.js \
|
||||
qml/pages/ChatInformationPage.qml \
|
||||
|
@ -82,11 +135,11 @@ DISTFILES += qml/harbour-fernschreiber.qml \
|
|||
qml/pages/AboutPage.qml \
|
||||
qml/pages/PollCreationPage.qml \
|
||||
qml/pages/PollResultsPage.qml \
|
||||
qml/pages/SearchChatsPage.qml \
|
||||
qml/pages/SettingsPage.qml \
|
||||
qml/pages/VideoPage.qml \
|
||||
rpm/harbour-fernschreiber.changes \
|
||||
rpm/harbour-fernschreiber.spec \
|
||||
rpm/harbour-fernschreiber.yaml \
|
||||
translations/*.ts \
|
||||
harbour-fernschreiber.desktop
|
||||
|
||||
|
@ -95,19 +148,28 @@ SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172 256x256
|
|||
TRANSLATIONS += translations/harbour-fernschreiber-de.ts \
|
||||
translations/harbour-fernschreiber-es.ts \
|
||||
translations/harbour-fernschreiber-fi.ts \
|
||||
translations/harbour-fernschreiber-fr.ts \
|
||||
translations/harbour-fernschreiber-hu.ts \
|
||||
translations/harbour-fernschreiber-it.ts \
|
||||
translations/harbour-fernschreiber-pl.ts \
|
||||
translations/harbour-fernschreiber-ru.ts \
|
||||
translations/harbour-fernschreiber-sv.ts \
|
||||
translations/harbour-fernschreiber-sk.ts \
|
||||
translations/harbour-fernschreiber-en.ts \
|
||||
translations/harbour-fernschreiber-zh_CN.ts
|
||||
|
||||
contains(QT_ARCH, arm) {
|
||||
equals(QT_ARCH, arm) {
|
||||
message(Building ARM)
|
||||
TARGET_ARCHITECTURE = armv7hl
|
||||
} else {
|
||||
}
|
||||
equals(QT_ARCH, i386) {
|
||||
message(Building i486)
|
||||
TARGET_ARCHITECTURE = i486
|
||||
}
|
||||
equals(QT_ARCH, arm64){
|
||||
message(Building aarch64)
|
||||
TARGET_ARCHITECTURE = aarch64
|
||||
}
|
||||
|
||||
INCLUDEPATH += $$PWD/tdlib/include
|
||||
DEPENDPATH += $$PWD/tdlib/include
|
||||
|
@ -149,6 +211,7 @@ INSTALLS += telegram 86.png 108.png 128.png 172.png 256.png \
|
|||
|
||||
HEADERS += \
|
||||
src/appsettings.h \
|
||||
src/chatpermissionfiltermodel.h \
|
||||
src/chatlistmodel.h \
|
||||
src/chatmodel.h \
|
||||
src/contactsmodel.h \
|
||||
|
@ -168,6 +231,7 @@ HEADERS += \
|
|||
src/tdlibreceiver.h \
|
||||
src/tdlibsecrets.h \
|
||||
src/tdlibwrapper.h \
|
||||
src/textfiltermodel.h \
|
||||
src/tgsplugin.h
|
||||
|
||||
# https://github.com/Samsung/rlottie.git
|
||||
|
|
Before Width: | Height: | Size: 8.3 KiB After Width: | Height: | Size: 9.8 KiB |
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 7.6 KiB |
|
@ -5,60 +5,241 @@
|
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="114.667"
|
||||
height="114.667"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="svg19">
|
||||
<metadata
|
||||
id="metadata23">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs9">
|
||||
<linearGradient
|
||||
id="linearGradient4649">
|
||||
<stop
|
||||
style="stop-color:#979797;stop-opacity:1"
|
||||
xml:space="preserve"
|
||||
width="114.66667"
|
||||
height="114.66667"
|
||||
viewBox="0 0 114.66667 114.66667"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
sodipodi:docname="background-black.svg"
|
||||
id="svg60"><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1015"
|
||||
id="namedview62"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.0581394"
|
||||
inkscape:cx="57.333336"
|
||||
inkscape:cy="57.333336"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g67" /><metadata
|
||||
id="metadata64"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs8"><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath18"><path
|
||||
d="M 0.301,43 C 0.301,42.364 0.3,1.723 0.3,1.723 v 0 C 0.3,0.938 0.938,0.3 1.723,0.3 v 0 H 43 c 23.584,0 42.7,19.117 42.7,42.7 v 0 C 85.7,66.583 66.584,85.7 43,85.7 v 0 C 19.417,85.7 0.301,66.583 0.301,43"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2" /></clipPath><linearGradient
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-72.476372,-72.476372,72.476372,-72.476372,73.193359,73.192871)"
|
||||
spreadMethod="pad"
|
||||
id="linearGradient30"><stop
|
||||
style="stop-opacity:1;stop-color:#727272;opacity:1"
|
||||
offset="0"
|
||||
id="stop4645" />
|
||||
<stop
|
||||
style="stop-color:#797979;stop-opacity:1"
|
||||
id="stop5" /><stop
|
||||
style="stop-opacity:1;stop-color:#898989;opacity:1"
|
||||
offset="0.959184"
|
||||
id="stop7" /><stop
|
||||
style="stop-opacity:1;stop-color:#898989;opacity:1"
|
||||
offset="1"
|
||||
id="stop4647" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#linearGradient4649"
|
||||
id="linearGradient4651"
|
||||
x1="0.81535178"
|
||||
y1="0.99882859"
|
||||
x2="71.914337"
|
||||
y2="74.307625"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<path
|
||||
d="M 0.301,43 0.3,1.723 C 0.3,0.938 0.938,0.3 1.723,0.3 H 43 C 66.584,0.3 85.7,19.417 85.7,43 85.7,66.583 66.584,85.7 43,85.7 19.417,85.7 0.301,66.583 0.301,43"
|
||||
transform="matrix(1.33333,0,0,-1.33333,0,114.667)"
|
||||
id="path11"
|
||||
style="fill:url(#linearGradient4651);fill-opacity:1" />
|
||||
<path
|
||||
d="m 100,57.117 c 0,-23.408 -19.043,-42.45 -42.45,-42.45 -23.409,0 -42.451,19.042 -42.451,42.45 v 42.45 h 42.45 C 80.957,99.567 100,80.525 100,57.117"
|
||||
id="path13"
|
||||
style="fill:#444444;fill-opacity:1" />
|
||||
<path
|
||||
d="m 81.517,53.646 c -0.0573,2.403947 3.578298,2.403947 3.521,0 0.0573,-2.403947 -3.578298,-2.403947 -3.521,0 m -8.73,0 c 0.09308,2.256331 3.433918,2.256331 3.527,0 0,-2.351999 -3.528,-2.351999 -3.528,0 m -8.723,0 c 0,2.347999 3.522,2.347999 3.522,0 0,-2.347999 -3.522,-2.347999 -3.522,0 m -8.727,0 c -0.101696,2.44622 3.621306,2.447277 3.521,10e-4 -0.09236,-2.252442 -3.427362,-2.253389 -3.521,-10e-4 m -8.728,0 c -0.05733,2.406646 3.58233,2.406646 3.525,0 -0.05466,-2.294686 -3.470338,-2.294686 -3.525,0 m -8.726,0 c 6.67e-4,2.350666 3.526667,2.349666 3.526,-10e-4 0,-2.350666 -3.526,-2.350666 -3.526,0 m -8.726,0 c -0.05801,2.406625 3.581643,2.407658 3.525,10e-4 -0.05466,-2.294686 -3.470338,-2.294686 -3.525,0 m -8.728,0 c 0,2.353332 3.53,2.353332 3.53,0 0,-0.973 -0.79,-1.763 -1.766,-1.763 -0.975,0 -1.764,0.79 -1.764,1.763"
|
||||
id="path15"
|
||||
style="fill:#000000;fill-opacity:1" />
|
||||
<path
|
||||
d="m 79.751,79.82 c -0.08052,4.780502 7.131515,4.780502 7.051,0 -0.109325,-4.589371 -6.940675,-4.589371 -7.05,0 m 0,-8.722 c 0.0022,1.946378 1.578625,3.524144 3.525,3.528 4.703331,0 4.703331,-7.055 0,-7.055 -1.946832,0.0022 -3.524347,1.580167 -3.526,3.527 m 0,-8.727 c 0.0017,1.946995 1.579006,3.525244 3.526,3.528 4.703998,0 4.703998,-7.056 0,-7.056 -1.946994,0.0028 -3.524348,1.581005 -3.526,3.528 M 71.025,44.92 c 0.0018,3.140416 3.799089,4.710649 6.018485,2.489364 C 79.262881,45.188079 77.689416,41.39211 74.549,41.393 c -1.946965,0.0011 -3.524552,1.580034 -3.524,3.527 m 0,-8.728 c -0.0013,4.699998 7.048667,4.701998 7.05,0.002 0.0013,-4.699998 -7.048667,-4.701998 -7.05,-0.002 m -8.727,34.906 c 0.0011,1.946833 1.578168,3.525243 3.525,3.528 4.624805,-0.07787 4.624805,-6.977129 0,-7.055 -1.946899,0.0017 -3.524449,1.580101 -3.525,3.527 m 0,-26.178 c 0,1.946804 1.578196,3.525 3.525,3.525 4.701331,0 4.701331,-7.052 0,-7.052 -1.947127,0.0011 -3.525,1.579872 -3.525,3.527 m -8.73,34.9 c -5.53e-4,1.948689 1.579311,3.528553 3.528,3.528 1.94947,0.0017 3.530553,-1.578529 3.53,-3.528 -0.0033,-1.946737 -1.583261,-3.522659 -3.53,-3.521 -1.946186,-0.0011 -3.525241,1.574816 -3.528,3.521 m 0,-8.722 c 0.0028,1.947319 1.580681,3.525246 3.528,3.528 1.9481,-0.0017 3.527244,-1.579902 3.53,-3.528 -0.0022,-1.948165 -1.581834,-3.52645 -3.53,-3.527 -1.947613,0.0011 -3.526345,1.579387 -3.528,3.527 m 0,-26.178 c 0.0017,1.947289 1.58071,3.525001 3.528,3.525 1.947842,5.53e-4 3.527792,-1.577159 3.53,-3.525 -0.109388,-4.594641 -6.948612,-4.594641 -7.058,0 m -8.723,-8.728 c -5.53e-4,1.948528 1.579472,3.528105 3.528,3.527 4.701331,0 4.701331,-7.052 0,-7.052 -1.947518,-5.52e-4 -3.526896,1.577482 -3.528,3.525 M 36.12,79.82 c -0.0017,1.948757 1.578243,3.529106 3.527,3.528 1.948435,0.0011 3.527766,-1.579567 3.525,-3.528 -5.52e-4,-1.945928 -1.579072,-3.522658 -3.525,-3.521 -1.946252,-0.0017 -3.525344,1.574748 -3.527,3.521 m 0,-34.9 c 0.0013,4.701331 7.053333,4.699331 7.052,-0.002 -0.0013,-4.701331 -7.053333,-4.699331 -7.052,0.002 m -8.726,-8.728 c -6.67e-4,4.701331 7.051333,4.702331 7.052,10e-4 6.67e-4,-4.701331 -7.051333,-4.702331 -7.052,-10e-4 M 18.667,79.82 c -0.0022,1.948204 1.576795,3.528554 3.525,3.528 4.699998,0 4.699998,-7.05 0,-7.05 -1.94609,-0.0011 -3.524448,1.57591 -3.525,3.522"
|
||||
id="path17"
|
||||
style="fill:#000000;fill-opacity:1" />
|
||||
</svg>
|
||||
id="stop9" /></linearGradient><linearGradient
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-72.476372,-72.476372,72.476372,-72.476372,73.193359,73.192871)"
|
||||
spreadMethod="pad"
|
||||
id="linearGradient30-529"><stop
|
||||
style="stop-opacity:1;stop-color:#727272;opacity:1"
|
||||
offset="0"
|
||||
id="stop74" /><stop
|
||||
style="stop-opacity:1;stop-color:#898989;opacity:1"
|
||||
offset="0.959184"
|
||||
id="stop76" /><stop
|
||||
style="stop-opacity:1;stop-color:#898989;opacity:1"
|
||||
offset="1"
|
||||
id="stop78" /></linearGradient><linearGradient
|
||||
x1="0"
|
||||
y1="0"
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-72.476372,-72.476372,72.476372,-72.476372,73.193359,73.192871)"
|
||||
spreadMethod="pad"
|
||||
id="linearGradient30-529-824"><stop
|
||||
style="stop-opacity:1;stop-color:#8d8d8d;opacity:1"
|
||||
offset="0"
|
||||
id="stop290" /><stop
|
||||
style="stop-opacity:1;stop-color:#767676;opacity:1"
|
||||
offset="0.959184"
|
||||
id="stop292" /><stop
|
||||
style="stop-opacity:1;stop-color:#767676;opacity:1"
|
||||
offset="1"
|
||||
id="stop294" /></linearGradient></defs><g
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="harbour-fernschreiber"
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,114.66667)"
|
||||
id="g67"><g
|
||||
id="g18"><g
|
||||
clip-path="url(#clipPath18)"
|
||||
id="g16"><path
|
||||
d="M 0.301,43 C 0.301,42.364 0.3,1.723 0.3,1.723 v 0 C 0.3,0.938 0.938,0.3 1.723,0.3 v 0 H 43 c 23.584,0 42.7,19.117 42.7,42.7 v 0 C 85.7,66.583 66.584,85.7 43,85.7 v 0 C 19.417,85.7 0.301,66.583 0.301,43"
|
||||
style="fill:url(#linearGradient30-529-824);stroke:none;opacity:1"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path14" /></g></g><g
|
||||
transform="translate(75,43.1621)"
|
||||
id="g20" /><path
|
||||
style="opacity:0.9;fill:#464646;fill-opacity:1;stroke-width:0.9930262"
|
||||
d="M 42.700457,74.178768 C 24.766404,74.178768 10.2285,60.954638 10.2285,44.643189 V 15.107611 5.2627488 c 5.978017,0 10.823985,4.255117 10.823985,9.6909432 h 21.647972 c 17.934054,0 32.471954,13.377056 32.471954,29.689497 0,16.311449 -14.5379,29.535579 -32.471954,29.535579 z"
|
||||
id="path10-3"
|
||||
inkscape:connector-curvature="0" /><g
|
||||
id="g46"
|
||||
transform="translate(15.3208,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.592,-1.322 1.323,-1.322 0.732,0 1.324,0.593 1.324,1.322 0,0.73 -0.592,1.322 -1.324,1.322 C 0.592,1.322 0,0.73 0,0"
|
||||
style="fill:#0b0b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path48"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g50"
|
||||
transform="translate(21.8672,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.591,-1.322 1.321,-1.322 0.732,0 1.323,0.593 1.323,1.322 0,0.73 -0.591,1.322 -1.323,1.322 C 0.591,1.322 0,0.73 0,0"
|
||||
style="fill:#0b0b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path52"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g54"
|
||||
transform="translate(28.4116,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.591,-1.322 1.323,-1.322 0.729,0 1.321,0.593 1.321,1.322 0,0.73 -0.592,1.322 -1.321,1.322 C 0.591,1.322 0,0.73 0,0"
|
||||
style="fill:#0b0b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path56"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g58"
|
||||
transform="translate(34.9561,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.592,-1.322 1.323,-1.322 0.73,0 1.321,0.593 1.321,1.322 0,0.73 -0.591,1.322 -1.321,1.322 C 0.592,1.322 0,0.73 0,0"
|
||||
style="fill:#0b0b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path60"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g62"
|
||||
transform="translate(41.502,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.593,-1.322 1.32,-1.322 0.732,0 1.322,0.593 1.322,1.322 0,0.73 -0.59,1.322 -1.322,1.322 C 0.593,1.322 0,0.73 0,0"
|
||||
style="fill:#0b0b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path64"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g66"
|
||||
transform="translate(48.0469,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.59,-1.322 1.32,-1.322 0.732,0 1.322,0.593 1.322,1.322 0,0.73 -0.59,1.322 -1.322,1.322 C 0.59,1.322 0,0.73 0,0"
|
||||
style="fill:#0b0b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path68"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g70"
|
||||
transform="translate(54.5898,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.594,-1.322 1.32,-1.322 0.735,0 1.326,0.593 1.326,1.322 0,0.73 -0.591,1.322 -1.326,1.322 C 0.594,1.322 0,0.73 0,0"
|
||||
style="fill:#0b0b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path72"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g74"
|
||||
transform="translate(61.1377,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.59,-1.322 1.319,-1.322 0.732,0 1.322,0.593 1.322,1.322 0,0.73 -0.59,1.322 -1.322,1.322 C 0.59,1.322 0,0.73 0,0"
|
||||
style="fill:#0b0b0b;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path76"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g78"
|
||||
transform="translate(14,26.1348)"><path
|
||||
d="m 0,0 c 0,-1.465 1.184,-2.646 2.644,-2.646 1.461,0 2.645,1.181 2.645,2.646 0,1.459 -1.184,2.641 -2.645,2.641 C 1.184,2.641 0,1.459 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path80"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g82"
|
||||
transform="translate(20.5444,58.856)"><path
|
||||
d="m 0,0 c 0,-1.462 1.185,-2.645 2.644,-2.645 1.461,0 2.645,1.183 2.645,2.645 0,1.459 -1.184,2.644 -2.645,2.644 C 1.185,2.644 0,1.459 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path84"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g86"
|
||||
transform="translate(27.0894,52.3101)"><path
|
||||
d="m 0,0 c 0,-1.461 1.185,-2.644 2.645,-2.644 1.461,0 2.644,1.183 2.644,2.644 0,1.46 -1.183,2.645 -2.644,2.645 C 1.185,2.645 0,1.46 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path88"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g90"
|
||||
transform="translate(27.0894,26.1348)"><path
|
||||
d="m 0,0 c 0,-1.465 1.185,-2.646 2.645,-2.646 1.461,0 2.644,1.181 2.644,2.646 0,1.459 -1.183,2.641 -2.644,2.641 C 1.185,2.641 0,1.459 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path92"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g94"
|
||||
transform="translate(33.6338,58.856)"><path
|
||||
d="M 0,0 C 0,-1.462 1.184,-2.645 2.646,-2.645 4.106,-2.645 5.29,-1.462 5.29,0 5.29,1.459 4.106,2.644 2.646,2.644 1.184,2.644 0,1.459 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path96"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g98"
|
||||
transform="translate(40.1758,52.3101)"><path
|
||||
d="m 0,0 c 0,-1.461 1.187,-2.644 2.646,-2.644 1.461,0 2.648,1.183 2.648,2.644 0,1.46 -1.187,2.645 -2.648,2.645 C 1.187,2.645 0,1.46 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path100"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g102"
|
||||
transform="translate(40.1758,32.6768)"><path
|
||||
d="m 0,0 c 0,-1.458 1.187,-2.646 2.646,-2.646 1.461,0 2.648,1.188 2.648,2.646 0,1.459 -1.187,2.645 -2.648,2.645 C 1.187,2.645 0,1.459 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path104"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g106"
|
||||
transform="translate(40.1758,26.1348)"><path
|
||||
d="m 0,0 c 0,-1.465 1.187,-2.646 2.646,-2.646 1.461,0 2.648,1.181 2.648,2.646 0,1.459 -1.187,2.641 -2.648,2.641 C 1.187,2.641 0,1.459 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path108"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g110"
|
||||
transform="translate(46.7236,52.3101)"><path
|
||||
d="m 0,0 c 0,-1.461 1.184,-2.644 2.644,-2.644 1.461,0 2.645,1.183 2.645,2.644 0,1.46 -1.184,2.645 -2.645,2.645 C 1.184,2.645 0,1.46 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path112"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g114"
|
||||
transform="translate(46.7236,32.6768)"><path
|
||||
d="m 0,0 c 0,-1.458 1.184,-2.646 2.644,-2.646 1.461,0 2.645,1.188 2.645,2.646 0,1.459 -1.184,2.645 -2.645,2.645 C 1.184,2.645 0,1.459 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path116"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g118"
|
||||
transform="translate(53.2686,58.856)"><path
|
||||
d="m 0,0 c 0,-1.462 1.183,-2.645 2.643,-2.645 1.461,0 2.645,1.183 2.645,2.645 0,1.459 -1.184,2.644 -2.645,2.644 C 1.183,2.644 0,1.459 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path120"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g122"
|
||||
transform="translate(53.2686,52.3101)"><path
|
||||
d="m 0,0 c 0,-1.461 1.183,-2.644 2.643,-2.644 1.461,0 2.645,1.183 2.645,2.644 0,1.46 -1.184,2.645 -2.645,2.645 C 1.183,2.645 0,1.46 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path124"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g126"
|
||||
transform="translate(59.8135,39.2217)"><path
|
||||
d="m 0,0 c 0,-1.459 1.187,-2.646 2.644,-2.646 1.461,0 2.644,1.187 2.644,2.646 0,1.459 -1.183,2.646 -2.644,2.646 C 1.187,2.646 0,1.459 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path128"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g130"
|
||||
transform="translate(59.8135,32.6768)"><path
|
||||
d="m 0,0 c 0,-1.458 1.187,-2.646 2.644,-2.646 1.461,0 2.644,1.188 2.644,2.646 0,1.459 -1.183,2.645 -2.644,2.645 C 1.187,2.645 0,1.459 0,0"
|
||||
style="fill:#040404;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
id="path132"
|
||||
inkscape:connector-curvature="0" /></g></g></svg>
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 13 KiB |
|
@ -5,60 +5,224 @@
|
|||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
id="svg19"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
height="114.667"
|
||||
width="114.667">
|
||||
<metadata
|
||||
id="metadata23">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs9">
|
||||
<linearGradient
|
||||
id="linearGradient4649">
|
||||
<stop
|
||||
id="stop4645"
|
||||
offset="0"
|
||||
style="stop-color:#686868;stop-opacity:1" />
|
||||
<stop
|
||||
id="stop4647"
|
||||
offset="1"
|
||||
style="stop-color:#868686;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xml:space="preserve"
|
||||
width="114.66667"
|
||||
height="114.66667"
|
||||
viewBox="0 0 114.66667 114.66667"
|
||||
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
|
||||
sodipodi:docname="background-white.svg"
|
||||
id="svg60"><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1015"
|
||||
id="namedview62"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.0581394"
|
||||
inkscape:cx="57.333336"
|
||||
inkscape:cy="57.333336"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g67" /><metadata
|
||||
id="metadata64"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs8"><clipPath
|
||||
id="clipPath18"
|
||||
clipPathUnits="userSpaceOnUse"><path
|
||||
id="path2"
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 0.301,43 C 0.301,42.364 0.3,1.723 0.3,1.723 v 0 C 0.3,0.938 0.938,0.3 1.723,0.3 v 0 H 43 c 23.584,0 42.7,19.117 42.7,42.7 v 0 C 85.7,66.583 66.584,85.7 43,85.7 v 0 C 19.417,85.7 0.301,66.583 0.301,43" /></clipPath><linearGradient
|
||||
id="linearGradient30"
|
||||
spreadMethod="pad"
|
||||
gradientTransform="matrix(-72.476372,-72.476372,72.476372,-72.476372,73.193359,73.192871)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="74.307625"
|
||||
x2="71.914337"
|
||||
y1="0.99882859"
|
||||
x1="0.81535178"
|
||||
id="linearGradient4651"
|
||||
xlink:href="#linearGradient4649" />
|
||||
</defs>
|
||||
<path
|
||||
style="fill:url(#linearGradient4651);fill-opacity:1"
|
||||
id="path11"
|
||||
transform="matrix(1.33333,0,0,-1.33333,0,114.667)"
|
||||
d="M 0.301,43 0.3,1.723 C 0.3,0.938 0.938,0.3 1.723,0.3 H 43 C 66.584,0.3 85.7,19.417 85.7,43 85.7,66.583 66.584,85.7 43,85.7 19.417,85.7 0.301,66.583 0.301,43" />
|
||||
<path
|
||||
style="fill:#bbbbbb;fill-opacity:1"
|
||||
id="path13"
|
||||
d="m 100,57.117 c 0,-23.408 -19.043,-42.45 -42.45,-42.45 -23.409,0 -42.451,19.042 -42.451,42.45 v 42.45 h 42.45 C 80.957,99.567 100,80.525 100,57.117" />
|
||||
<path
|
||||
style="fill:#f7f7f7;fill-opacity:1"
|
||||
id="path15"
|
||||
d="m 81.517,53.646 c -0.0573,2.403947 3.578298,2.403947 3.521,0 0.0573,-2.403947 -3.578298,-2.403947 -3.521,0 m -8.73,0 c 0.09308,2.256331 3.433918,2.256331 3.527,0 0,-2.351999 -3.528,-2.351999 -3.528,0 m -8.723,0 c 0,2.347999 3.522,2.347999 3.522,0 0,-2.347999 -3.522,-2.347999 -3.522,0 m -8.727,0 c -0.101696,2.44622 3.621306,2.447277 3.521,10e-4 -0.09236,-2.252442 -3.427362,-2.253389 -3.521,-10e-4 m -8.728,0 c -0.05733,2.406646 3.58233,2.406646 3.525,0 -0.05466,-2.294686 -3.470338,-2.294686 -3.525,0 m -8.726,0 c 6.67e-4,2.350666 3.526667,2.349666 3.526,-10e-4 0,-2.350666 -3.526,-2.350666 -3.526,0 m -8.726,0 c -0.05801,2.406625 3.581643,2.407658 3.525,10e-4 -0.05466,-2.294686 -3.470338,-2.294686 -3.525,0 m -8.728,0 c 0,2.353332 3.53,2.353332 3.53,0 0,-0.973 -0.79,-1.763 -1.766,-1.763 -0.975,0 -1.764,0.79 -1.764,1.763" />
|
||||
<path
|
||||
style="fill:#fcfcfc;fill-opacity:1"
|
||||
id="path17"
|
||||
d="m 79.751,79.82 c -0.08052,4.780502 7.131515,4.780502 7.051,0 -0.109325,-4.589371 -6.940675,-4.589371 -7.05,0 m 0,-8.722 c 0.0022,1.946378 1.578625,3.524144 3.525,3.528 4.703331,0 4.703331,-7.055 0,-7.055 -1.946832,0.0022 -3.524347,1.580167 -3.526,3.527 m 0,-8.727 c 0.0017,1.946995 1.579006,3.525244 3.526,3.528 4.703998,0 4.703998,-7.056 0,-7.056 -1.946994,0.0028 -3.524348,1.581005 -3.526,3.528 M 71.025,44.92 c 0.0018,3.140416 3.799089,4.710649 6.018485,2.489364 C 79.262881,45.188079 77.689416,41.39211 74.549,41.393 c -1.946965,0.0011 -3.524552,1.580034 -3.524,3.527 m 0,-8.728 c -0.0013,4.699998 7.048667,4.701998 7.05,0.002 0.0013,-4.699998 -7.048667,-4.701998 -7.05,-0.002 m -8.727,34.906 c 0.0011,1.946833 1.578168,3.525243 3.525,3.528 4.624805,-0.07787 4.624805,-6.977129 0,-7.055 -1.946899,0.0017 -3.524449,1.580101 -3.525,3.527 m 0,-26.178 c 0,1.946804 1.578196,3.525 3.525,3.525 4.701331,0 4.701331,-7.052 0,-7.052 -1.947127,0.0011 -3.525,1.579872 -3.525,3.527 m -8.73,34.9 c -5.53e-4,1.948689 1.579311,3.528553 3.528,3.528 1.94947,0.0017 3.530553,-1.578529 3.53,-3.528 -0.0033,-1.946737 -1.583261,-3.522659 -3.53,-3.521 -1.946186,-0.0011 -3.525241,1.574816 -3.528,3.521 m 0,-8.722 c 0.0028,1.947319 1.580681,3.525246 3.528,3.528 1.9481,-0.0017 3.527244,-1.579902 3.53,-3.528 -0.0022,-1.948165 -1.581834,-3.52645 -3.53,-3.527 -1.947613,0.0011 -3.526345,1.579387 -3.528,3.527 m 0,-26.178 c 0.0017,1.947289 1.58071,3.525001 3.528,3.525 1.947842,5.53e-4 3.527792,-1.577159 3.53,-3.525 -0.109388,-4.594641 -6.948612,-4.594641 -7.058,0 m -8.723,-8.728 c -5.53e-4,1.948528 1.579472,3.528105 3.528,3.527 4.701331,0 4.701331,-7.052 0,-7.052 -1.947518,-5.52e-4 -3.526896,1.577482 -3.528,3.525 M 36.12,79.82 c -0.0017,1.948757 1.578243,3.529106 3.527,3.528 1.948435,0.0011 3.527766,-1.579567 3.525,-3.528 -5.52e-4,-1.945928 -1.579072,-3.522658 -3.525,-3.521 -1.946252,-0.0017 -3.525344,1.574748 -3.527,3.521 m 0,-34.9 c 0.0013,4.701331 7.053333,4.699331 7.052,-0.002 -0.0013,-4.701331 -7.053333,-4.699331 -7.052,0.002 m -8.726,-8.728 c -6.67e-4,4.701331 7.051333,4.702331 7.052,10e-4 6.67e-4,-4.701331 -7.051333,-4.702331 -7.052,-10e-4 M 18.667,79.82 c -0.0022,1.948204 1.576795,3.528554 3.525,3.528 4.699998,0 4.699998,-7.05 0,-7.05 -1.94609,-0.0011 -3.524448,1.57591 -3.525,3.522" />
|
||||
</svg>
|
||||
y2="0"
|
||||
x2="1"
|
||||
y1="0"
|
||||
x1="0"><stop
|
||||
id="stop5"
|
||||
offset="0"
|
||||
style="stop-opacity:1;stop-color:#8d8d8d;opacity:1" /><stop
|
||||
id="stop7"
|
||||
offset="0.959184"
|
||||
style="stop-opacity:1;stop-color:#767676;opacity:1" /><stop
|
||||
id="stop9"
|
||||
offset="1"
|
||||
style="stop-opacity:1;stop-color:#767676;opacity:1" /></linearGradient><linearGradient
|
||||
id="linearGradient30-529"
|
||||
spreadMethod="pad"
|
||||
gradientTransform="matrix(-72.476372,-72.476372,72.476372,-72.476372,73.193359,73.192871)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="0"
|
||||
x2="1"
|
||||
y1="0"
|
||||
x1="0"><stop
|
||||
id="stop74"
|
||||
offset="0"
|
||||
style="stop-opacity:1;stop-color:#8d8d8d;opacity:1" /><stop
|
||||
id="stop76"
|
||||
offset="0.959184"
|
||||
style="stop-opacity:1;stop-color:#767676;opacity:1" /><stop
|
||||
id="stop78"
|
||||
offset="1"
|
||||
style="stop-opacity:1;stop-color:#767676;opacity:1" /></linearGradient></defs><g
|
||||
id="g67"
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,114.66667)"
|
||||
inkscape:label="harbour-fernschreiber"
|
||||
inkscape:groupmode="layer"><g
|
||||
id="g18"><g
|
||||
id="g16"
|
||||
clip-path="url(#clipPath18)"><path
|
||||
id="path14"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:url(#linearGradient30-529);stroke:none;opacity:1"
|
||||
d="M 0.301,43 C 0.301,42.364 0.3,1.723 0.3,1.723 v 0 C 0.3,0.938 0.938,0.3 1.723,0.3 v 0 H 43 c 23.584,0 42.7,19.117 42.7,42.7 v 0 C 85.7,66.583 66.584,85.7 43,85.7 v 0 C 19.417,85.7 0.301,66.583 0.301,43" /></g></g><g
|
||||
id="g20"
|
||||
transform="translate(75,43.1621)" /><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path10-3"
|
||||
d="M 42.700457,74.178768 C 24.766404,74.178768 10.2285,60.954638 10.2285,44.643189 V 15.107611 5.2627488 c 5.978017,0 10.823985,4.255117 10.823985,9.6909432 h 21.647972 c 17.934054,0 32.471954,13.377056 32.471954,29.689497 0,16.311449 -14.5379,29.535579 -32.471954,29.535579 z"
|
||||
style="opacity:0.9;fill:#b9b9b9;fill-opacity:1;stroke-width:0.9930262" /><g
|
||||
transform="translate(15.3208,45.7656)"
|
||||
id="g46"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path48"
|
||||
style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-0.729 0.592,-1.322 1.323,-1.322 0.732,0 1.324,0.593 1.324,1.322 0,0.73 -0.592,1.322 -1.324,1.322 C 0.592,1.322 0,0.73 0,0" /></g><g
|
||||
transform="translate(21.8672,45.7656)"
|
||||
id="g50"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path52"
|
||||
style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-0.729 0.591,-1.322 1.321,-1.322 0.732,0 1.323,0.593 1.323,1.322 0,0.73 -0.591,1.322 -1.323,1.322 C 0.591,1.322 0,0.73 0,0" /></g><g
|
||||
transform="translate(28.4116,45.7656)"
|
||||
id="g54"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path56"
|
||||
style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-0.729 0.591,-1.322 1.323,-1.322 0.729,0 1.321,0.593 1.321,1.322 0,0.73 -0.592,1.322 -1.321,1.322 C 0.591,1.322 0,0.73 0,0" /></g><g
|
||||
transform="translate(34.9561,45.7656)"
|
||||
id="g58"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path60"
|
||||
style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-0.729 0.592,-1.322 1.323,-1.322 0.73,0 1.321,0.593 1.321,1.322 0,0.73 -0.591,1.322 -1.321,1.322 C 0.592,1.322 0,0.73 0,0" /></g><g
|
||||
transform="translate(41.502,45.7656)"
|
||||
id="g62"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path64"
|
||||
style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-0.729 0.593,-1.322 1.32,-1.322 0.732,0 1.322,0.593 1.322,1.322 0,0.73 -0.59,1.322 -1.322,1.322 C 0.593,1.322 0,0.73 0,0" /></g><g
|
||||
transform="translate(48.0469,45.7656)"
|
||||
id="g66"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path68"
|
||||
style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-0.729 0.59,-1.322 1.32,-1.322 0.732,0 1.322,0.593 1.322,1.322 0,0.73 -0.59,1.322 -1.322,1.322 C 0.59,1.322 0,0.73 0,0" /></g><g
|
||||
transform="translate(54.5898,45.7656)"
|
||||
id="g70"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path72"
|
||||
style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-0.729 0.594,-1.322 1.32,-1.322 0.735,0 1.326,0.593 1.326,1.322 0,0.73 -0.591,1.322 -1.326,1.322 C 0.594,1.322 0,0.73 0,0" /></g><g
|
||||
transform="translate(61.1377,45.7656)"
|
||||
id="g74"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path76"
|
||||
style="fill:#f4f4f4;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-0.729 0.59,-1.322 1.319,-1.322 0.732,0 1.322,0.593 1.322,1.322 0,0.73 -0.59,1.322 -1.322,1.322 C 0.59,1.322 0,0.73 0,0" /></g><g
|
||||
transform="translate(14,26.1348)"
|
||||
id="g78"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path80"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.465 1.184,-2.646 2.644,-2.646 1.461,0 2.645,1.181 2.645,2.646 0,1.459 -1.184,2.641 -2.645,2.641 C 1.184,2.641 0,1.459 0,0" /></g><g
|
||||
transform="translate(20.5444,58.856)"
|
||||
id="g82"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path84"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.462 1.185,-2.645 2.644,-2.645 1.461,0 2.645,1.183 2.645,2.645 0,1.459 -1.184,2.644 -2.645,2.644 C 1.185,2.644 0,1.459 0,0" /></g><g
|
||||
transform="translate(27.0894,52.3101)"
|
||||
id="g86"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path88"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.461 1.185,-2.644 2.645,-2.644 1.461,0 2.644,1.183 2.644,2.644 0,1.46 -1.183,2.645 -2.644,2.645 C 1.185,2.645 0,1.46 0,0" /></g><g
|
||||
transform="translate(27.0894,26.1348)"
|
||||
id="g90"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path92"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.465 1.185,-2.646 2.645,-2.646 1.461,0 2.644,1.181 2.644,2.646 0,1.459 -1.183,2.641 -2.644,2.641 C 1.185,2.641 0,1.459 0,0" /></g><g
|
||||
transform="translate(33.6338,58.856)"
|
||||
id="g94"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path96"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="M 0,0 C 0,-1.462 1.184,-2.645 2.646,-2.645 4.106,-2.645 5.29,-1.462 5.29,0 5.29,1.459 4.106,2.644 2.646,2.644 1.184,2.644 0,1.459 0,0" /></g><g
|
||||
transform="translate(40.1758,52.3101)"
|
||||
id="g98"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path100"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.461 1.187,-2.644 2.646,-2.644 1.461,0 2.648,1.183 2.648,2.644 0,1.46 -1.187,2.645 -2.648,2.645 C 1.187,2.645 0,1.46 0,0" /></g><g
|
||||
transform="translate(40.1758,32.6768)"
|
||||
id="g102"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path104"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.458 1.187,-2.646 2.646,-2.646 1.461,0 2.648,1.188 2.648,2.646 0,1.459 -1.187,2.645 -2.648,2.645 C 1.187,2.645 0,1.459 0,0" /></g><g
|
||||
transform="translate(40.1758,26.1348)"
|
||||
id="g106"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path108"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.465 1.187,-2.646 2.646,-2.646 1.461,0 2.648,1.181 2.648,2.646 0,1.459 -1.187,2.641 -2.648,2.641 C 1.187,2.641 0,1.459 0,0" /></g><g
|
||||
transform="translate(46.7236,52.3101)"
|
||||
id="g110"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path112"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.461 1.184,-2.644 2.644,-2.644 1.461,0 2.645,1.183 2.645,2.644 0,1.46 -1.184,2.645 -2.645,2.645 C 1.184,2.645 0,1.46 0,0" /></g><g
|
||||
transform="translate(46.7236,32.6768)"
|
||||
id="g114"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path116"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.458 1.184,-2.646 2.644,-2.646 1.461,0 2.645,1.188 2.645,2.646 0,1.459 -1.184,2.645 -2.645,2.645 C 1.184,2.645 0,1.459 0,0" /></g><g
|
||||
transform="translate(53.2686,58.856)"
|
||||
id="g118"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path120"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.462 1.183,-2.645 2.643,-2.645 1.461,0 2.645,1.183 2.645,2.645 0,1.459 -1.184,2.644 -2.645,2.644 C 1.183,2.644 0,1.459 0,0" /></g><g
|
||||
transform="translate(53.2686,52.3101)"
|
||||
id="g122"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path124"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.461 1.183,-2.644 2.643,-2.644 1.461,0 2.645,1.183 2.645,2.644 0,1.46 -1.184,2.645 -2.645,2.645 C 1.183,2.645 0,1.46 0,0" /></g><g
|
||||
transform="translate(59.8135,39.2217)"
|
||||
id="g126"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path128"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.459 1.187,-2.646 2.644,-2.646 1.461,0 2.644,1.187 2.644,2.646 0,1.459 -1.183,2.646 -2.644,2.646 C 1.187,2.646 0,1.459 0,0" /></g><g
|
||||
transform="translate(59.8135,32.6768)"
|
||||
id="g130"><path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path132"
|
||||
style="fill:#fbfbfb;fill-opacity:1;fill-rule:nonzero;stroke:none;opacity:1"
|
||||
d="m 0,0 c 0,-1.458 1.187,-2.646 2.644,-2.646 1.461,0 2.644,1.188 2.644,2.646 0,1.459 -1.183,2.645 -2.644,2.645 C 1.187,2.645 0,1.459 0,0" /></g></g></svg>
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 22 KiB |
|
@ -1,66 +1,204 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg19"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
height="114.667"
|
||||
width="114.667">
|
||||
<metadata
|
||||
id="metadata23">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs9">
|
||||
xml:space="preserve"
|
||||
width="114.66667"
|
||||
height="114.66667"
|
||||
viewBox="0 0 114.66667 114.66667"
|
||||
inkscape:version="0.92.4 (unknown)"
|
||||
sodipodi:docname="harbour-fernschreiber-3.svg">
|
||||
<defs>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath18">
|
||||
<path
|
||||
d="M 0.301,43 C 0.301,42.364 0.3,1.723 0.3,1.723 v 0 C 0.3,0.938 0.938,0.3 1.723,0.3 v 0 H 43 c 23.584,0 42.7,19.117 42.7,42.7 v 0 C 85.7,66.583 66.584,85.7 43,85.7 v 0 C 19.417,85.7 0.301,66.583 0.301,43"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path2" />
|
||||
</clipPath>
|
||||
<linearGradient
|
||||
id="a"
|
||||
spreadMethod="pad"
|
||||
gradientTransform="rotate(-135 51.755 21.438) scale(102.49707)"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
y2="0"
|
||||
x2="1"
|
||||
x1="0"
|
||||
y1="0"
|
||||
x1="0">
|
||||
x2="1"
|
||||
y2="0"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(-72.476372,-72.476372,72.476372,-72.476372,73.193359,73.192871)"
|
||||
spreadMethod="pad"
|
||||
id="linearGradient30">
|
||||
<stop
|
||||
id="stop2"
|
||||
stop-color="#ec7221"
|
||||
offset="0" />
|
||||
style="stop-opacity:1;stop-color:#ec7221"
|
||||
offset="0"
|
||||
id="stop5" />
|
||||
<stop
|
||||
id="stop4"
|
||||
stop-color="#e7454c"
|
||||
offset=".959" />
|
||||
style="stop-opacity:1;stop-color:#e7454c"
|
||||
offset="0.959184"
|
||||
id="stop7" />
|
||||
<stop
|
||||
id="stop6"
|
||||
stop-color="#e7454c"
|
||||
offset="1" />
|
||||
style="stop-opacity:1;stop-color:#e7454c"
|
||||
offset="1"
|
||||
id="stop9" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="harbour-fernschreiber"
|
||||
transform="matrix(1.3333333,0,0,-1.3333333,0,114.66667)"
|
||||
id="g67">
|
||||
<g
|
||||
id="g18">
|
||||
<g
|
||||
clip-path="url(#clipPath18)"
|
||||
id="g16">
|
||||
<path
|
||||
id="path11"
|
||||
transform="matrix(1.33333 0 0 -1.33333 0 114.667)"
|
||||
fill="url(#a)"
|
||||
d="M.301 43L.3 1.723C.3.938.938.3 1.723.3H43C66.584.3 85.7 19.417 85.7 43c0 23.583-19.116 42.7-42.7 42.7C19.417 85.7.301 66.583.301 43" />
|
||||
d="M 0.301,43 C 0.301,42.364 0.3,1.723 0.3,1.723 v 0 C 0.3,0.938 0.938,0.3 1.723,0.3 v 0 H 43 c 23.584,0 42.7,19.117 42.7,42.7 v 0 C 85.7,66.583 66.584,85.7 43,85.7 v 0 C 19.417,85.7 0.301,66.583 0.301,43"
|
||||
style="fill:url(#linearGradient30);stroke:none"
|
||||
inkscape:connector-curvature="0"
|
||||
id="path14" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(75,43.1621)"
|
||||
id="g20" />
|
||||
<path
|
||||
id="path13"
|
||||
fill="#fcba02"
|
||||
d="M100 57.117c0-23.408-19.043-42.45-42.45-42.45-23.409 0-42.451 19.042-42.451 42.45v42.45h42.45c23.408 0 42.451-19.042 42.451-42.45" />
|
||||
<path
|
||||
style="fill:#fffda9"
|
||||
id="path15"
|
||||
d="m 81.517,53.646 c -0.0573,2.403947 3.578298,2.403947 3.521,0 0.0573,-2.403947 -3.578298,-2.403947 -3.521,0 m -8.73,0 c 0.09308,2.256331 3.433918,2.256331 3.527,0 0,-2.351999 -3.528,-2.351999 -3.528,0 m -8.723,0 c 0,2.347999 3.522,2.347999 3.522,0 0,-2.347999 -3.522,-2.347999 -3.522,0 m -8.727,0 c -0.101696,2.44622 3.621306,2.447277 3.521,10e-4 -0.09236,-2.252442 -3.427362,-2.253389 -3.521,-10e-4 m -8.728,0 c -0.05733,2.406646 3.58233,2.406646 3.525,0 -0.05466,-2.294686 -3.470338,-2.294686 -3.525,0 m -8.726,0 c 6.67e-4,2.350666 3.526667,2.349666 3.526,-10e-4 0,-2.350666 -3.526,-2.350666 -3.526,0 m -8.726,0 c -0.05801,2.406625 3.581643,2.407658 3.525,10e-4 -0.05466,-2.294686 -3.470338,-2.294686 -3.525,0 m -8.728,0 c 0,2.353332 3.53,2.353332 3.53,0 0,-0.973 -0.79,-1.763 -1.766,-1.763 -0.975,0 -1.764,0.79 -1.764,1.763" />
|
||||
<path
|
||||
style="fill:#fffee3"
|
||||
id="path17"
|
||||
d="m 79.751,79.82 c -0.08052,4.780502 7.131515,4.780502 7.051,0 -0.109325,-4.589371 -6.940675,-4.589371 -7.05,0 m 0,-8.722 c 0.0022,1.946378 1.578625,3.524144 3.525,3.528 4.703331,0 4.703331,-7.055 0,-7.055 -1.946832,0.0022 -3.524347,1.580167 -3.526,3.527 m 0,-8.727 c 0.0017,1.946995 1.579006,3.525244 3.526,3.528 4.703998,0 4.703998,-7.056 0,-7.056 -1.946994,0.0028 -3.524348,1.581005 -3.526,3.528 M 71.025,44.92 c 0.0018,3.140416 3.799089,4.710649 6.018485,2.489364 C 79.262881,45.188079 77.689416,41.39211 74.549,41.393 c -1.946965,0.0011 -3.524552,1.580034 -3.524,3.527 m 0,-8.728 c -0.0013,4.699998 7.048667,4.701998 7.05,0.002 0.0013,-4.699998 -7.048667,-4.701998 -7.05,-0.002 m -8.727,34.906 c 0.0011,1.946833 1.578168,3.525243 3.525,3.528 4.624805,-0.07787 4.624805,-6.977129 0,-7.055 -1.946899,0.0017 -3.524449,1.580101 -3.525,3.527 m 0,-26.178 c 0,1.946804 1.578196,3.525 3.525,3.525 4.701331,0 4.701331,-7.052 0,-7.052 -1.947127,0.0011 -3.525,1.579872 -3.525,3.527 m -8.73,34.9 c -5.53e-4,1.948689 1.579311,3.528553 3.528,3.528 1.94947,0.0017 3.530553,-1.578529 3.53,-3.528 -0.0033,-1.946737 -1.583261,-3.522659 -3.53,-3.521 -1.946186,-0.0011 -3.525241,1.574816 -3.528,3.521 m 0,-8.722 c 0.0028,1.947319 1.580681,3.525246 3.528,3.528 1.9481,-0.0017 3.527244,-1.579902 3.53,-3.528 -0.0022,-1.948165 -1.581834,-3.52645 -3.53,-3.527 -1.947613,0.0011 -3.526345,1.579387 -3.528,3.527 m 0,-26.178 c 0.0017,1.947289 1.58071,3.525001 3.528,3.525 1.947842,5.53e-4 3.527792,-1.577159 3.53,-3.525 -0.109388,-4.594641 -6.948612,-4.594641 -7.058,0 m -8.723,-8.728 c -5.53e-4,1.948528 1.579472,3.528105 3.528,3.527 4.701331,0 4.701331,-7.052 0,-7.052 -1.947518,-5.52e-4 -3.526896,1.577482 -3.528,3.525 M 36.12,79.82 c -0.0017,1.948757 1.578243,3.529106 3.527,3.528 1.948435,0.0011 3.527766,-1.579567 3.525,-3.528 -5.52e-4,-1.945928 -1.579072,-3.522658 -3.525,-3.521 -1.946252,-0.0017 -3.525344,1.574748 -3.527,3.521 m 0,-34.9 c 0.0013,4.701331 7.053333,4.699331 7.052,-0.002 -0.0013,-4.701331 -7.053333,-4.699331 -7.052,0.002 m -8.726,-8.728 c -6.67e-4,4.701331 7.051333,4.702331 7.052,10e-4 6.67e-4,-4.701331 -7.051333,-4.702331 -7.052,-10e-4 M 18.667,79.82 c -0.0022,1.948204 1.576795,3.528554 3.525,3.528 4.699998,0 4.699998,-7.05 0,-7.05 -1.94609,-0.0011 -3.524448,1.57591 -3.525,3.522" />
|
||||
style="opacity:0.9;fill:#fcba02;fill-opacity:1;stroke-width:0.9930262"
|
||||
d="M 42.700457,74.178768 C 24.766404,74.178768 10.2285,60.954638 10.2285,44.643189 V 15.107611 5.2627488 c 5.978017,0 10.823985,4.255117 10.823985,9.6909432 h 21.647972 c 17.934054,0 32.471954,13.377056 32.471954,29.689497 0,16.311449 -14.5379,29.535579 -32.471954,29.535579 z"
|
||||
id="path10-3"
|
||||
inkscape:connector-curvature="0" /><g
|
||||
id="g46"
|
||||
transform="translate(15.3208,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.592,-1.322 1.323,-1.322 0.732,0 1.324,0.593 1.324,1.322 0,0.73 -0.592,1.322 -1.324,1.322 C 0.592,1.322 0,0.73 0,0"
|
||||
style="fill:#fffda9;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path48"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g50"
|
||||
transform="translate(21.8672,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.591,-1.322 1.321,-1.322 0.732,0 1.323,0.593 1.323,1.322 0,0.73 -0.591,1.322 -1.323,1.322 C 0.591,1.322 0,0.73 0,0"
|
||||
style="fill:#fffda9;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path52"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g54"
|
||||
transform="translate(28.4116,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.591,-1.322 1.323,-1.322 0.729,0 1.321,0.593 1.321,1.322 0,0.73 -0.592,1.322 -1.321,1.322 C 0.591,1.322 0,0.73 0,0"
|
||||
style="fill:#fffda9;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path56"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g58"
|
||||
transform="translate(34.9561,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.592,-1.322 1.323,-1.322 0.73,0 1.321,0.593 1.321,1.322 0,0.73 -0.591,1.322 -1.321,1.322 C 0.592,1.322 0,0.73 0,0"
|
||||
style="fill:#fffda9;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path60"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g62"
|
||||
transform="translate(41.502,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.593,-1.322 1.32,-1.322 0.732,0 1.322,0.593 1.322,1.322 0,0.73 -0.59,1.322 -1.322,1.322 C 0.593,1.322 0,0.73 0,0"
|
||||
style="fill:#fffda9;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path64"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g66"
|
||||
transform="translate(48.0469,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.59,-1.322 1.32,-1.322 0.732,0 1.322,0.593 1.322,1.322 0,0.73 -0.59,1.322 -1.322,1.322 C 0.59,1.322 0,0.73 0,0"
|
||||
style="fill:#fffda9;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path68"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g70"
|
||||
transform="translate(54.5898,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.594,-1.322 1.32,-1.322 0.735,0 1.326,0.593 1.326,1.322 0,0.73 -0.591,1.322 -1.326,1.322 C 0.594,1.322 0,0.73 0,0"
|
||||
style="fill:#fffda9;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path72"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g74"
|
||||
transform="translate(61.1377,45.7656)"><path
|
||||
d="m 0,0 c 0,-0.729 0.59,-1.322 1.319,-1.322 0.732,0 1.322,0.593 1.322,1.322 0,0.73 -0.59,1.322 -1.322,1.322 C 0.59,1.322 0,0.73 0,0"
|
||||
style="fill:#fffda9;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path76"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g78"
|
||||
transform="translate(14,26.1348)"><path
|
||||
d="m 0,0 c 0,-1.465 1.184,-2.646 2.644,-2.646 1.461,0 2.645,1.181 2.645,2.646 0,1.459 -1.184,2.641 -2.645,2.641 C 1.184,2.641 0,1.459 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path80"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g82"
|
||||
transform="translate(20.5444,58.856)"><path
|
||||
d="m 0,0 c 0,-1.462 1.185,-2.645 2.644,-2.645 1.461,0 2.645,1.183 2.645,2.645 0,1.459 -1.184,2.644 -2.645,2.644 C 1.185,2.644 0,1.459 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path84"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g86"
|
||||
transform="translate(27.0894,52.3101)"><path
|
||||
d="m 0,0 c 0,-1.461 1.185,-2.644 2.645,-2.644 1.461,0 2.644,1.183 2.644,2.644 0,1.46 -1.183,2.645 -2.644,2.645 C 1.185,2.645 0,1.46 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path88"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g90"
|
||||
transform="translate(27.0894,26.1348)"><path
|
||||
d="m 0,0 c 0,-1.465 1.185,-2.646 2.645,-2.646 1.461,0 2.644,1.181 2.644,2.646 0,1.459 -1.183,2.641 -2.644,2.641 C 1.185,2.641 0,1.459 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path92"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g94"
|
||||
transform="translate(33.6338,58.856)"><path
|
||||
d="M 0,0 C 0,-1.462 1.184,-2.645 2.646,-2.645 4.106,-2.645 5.29,-1.462 5.29,0 5.29,1.459 4.106,2.644 2.646,2.644 1.184,2.644 0,1.459 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path96"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g98"
|
||||
transform="translate(40.1758,52.3101)"><path
|
||||
d="m 0,0 c 0,-1.461 1.187,-2.644 2.646,-2.644 1.461,0 2.648,1.183 2.648,2.644 0,1.46 -1.187,2.645 -2.648,2.645 C 1.187,2.645 0,1.46 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path100"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g102"
|
||||
transform="translate(40.1758,32.6768)"><path
|
||||
d="m 0,0 c 0,-1.458 1.187,-2.646 2.646,-2.646 1.461,0 2.648,1.188 2.648,2.646 0,1.459 -1.187,2.645 -2.648,2.645 C 1.187,2.645 0,1.459 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path104"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g106"
|
||||
transform="translate(40.1758,26.1348)"><path
|
||||
d="m 0,0 c 0,-1.465 1.187,-2.646 2.646,-2.646 1.461,0 2.648,1.181 2.648,2.646 0,1.459 -1.187,2.641 -2.648,2.641 C 1.187,2.641 0,1.459 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path108"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g110"
|
||||
transform="translate(46.7236,52.3101)"><path
|
||||
d="m 0,0 c 0,-1.461 1.184,-2.644 2.644,-2.644 1.461,0 2.645,1.183 2.645,2.644 0,1.46 -1.184,2.645 -2.645,2.645 C 1.184,2.645 0,1.46 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path112"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g114"
|
||||
transform="translate(46.7236,32.6768)"><path
|
||||
d="m 0,0 c 0,-1.458 1.184,-2.646 2.644,-2.646 1.461,0 2.645,1.188 2.645,2.646 0,1.459 -1.184,2.645 -2.645,2.645 C 1.184,2.645 0,1.459 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path116"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g118"
|
||||
transform="translate(53.2686,58.856)"><path
|
||||
d="m 0,0 c 0,-1.462 1.183,-2.645 2.643,-2.645 1.461,0 2.645,1.183 2.645,2.645 0,1.459 -1.184,2.644 -2.645,2.644 C 1.183,2.644 0,1.459 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path120"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g122"
|
||||
transform="translate(53.2686,52.3101)"><path
|
||||
d="m 0,0 c 0,-1.461 1.183,-2.644 2.643,-2.644 1.461,0 2.645,1.183 2.645,2.644 0,1.46 -1.184,2.645 -2.645,2.645 C 1.183,2.645 0,1.46 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path124"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g126"
|
||||
transform="translate(59.8135,39.2217)"><path
|
||||
d="m 0,0 c 0,-1.459 1.187,-2.646 2.644,-2.646 1.461,0 2.644,1.187 2.644,2.646 0,1.459 -1.183,2.646 -2.644,2.646 C 1.187,2.646 0,1.459 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path128"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g130"
|
||||
transform="translate(59.8135,32.6768)"><path
|
||||
d="m 0,0 c 0,-1.458 1.187,-2.646 2.644,-2.646 1.461,0 2.644,1.188 2.644,2.646 0,1.459 -1.183,2.645 -2.644,2.645 C 1.187,2.645 0,1.459 0,0"
|
||||
style="fill:#fffee3;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path132"
|
||||
inkscape:connector-curvature="0" /></g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 9.7 KiB |
39
images/icon-m-copy-to-folder.svg
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
style="enable-background:new 0 0 64 64;"
|
||||
viewBox="0 0 64 64"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Layer_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata17"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs15">
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</defs>
|
||||
|
||||
<path
|
||||
style="fill:#ffffff"
|
||||
d="m 37.855477,15.759299 c -1.73926,0.0029 -4.47725,1.553014 -6.64098,2.8829 -1.6826,1.034172 -3.75291,1.108852 -5.69886,1.124912 h -8.64063 c -1.034,0 -1.875,0.841 -1.875,1.875 v 8.070312 l 2,1.359376 v -9.304688 h 8.51563 c 2.75742,-0.06081 4.84074,-0.2051 6.5836,-1.513027 2.1377,-1.604239 4.80361,-2.501457 7.17616,-2.486973 h 18.51758 c 0.666,0 1.20703,0.541031 1.20703,1.207031 v 31.542969 c 0,0.689 -0.561,1.25 -1.25,1.25 h -39.5 c -0.689,0 -1.25,-0.561 -1.25,-1.25 V 42.08547 l -2,1.359375 v 7.072266 c 0,1.792 1.458,3.25 3.25,3.25 h 39.5 c 1.792,0 3.25,-1.458 3.25,-3.25 V 18.974142 c 0,-1.769 -1.43803,-3.207984 -3.20703,-3.208984 h -18.51758 c -0.4765,0 -0.94899,-0.01047 -1.41992,-0.0059 z"
|
||||
id="path6-9" /><path
|
||||
id="path11-6"
|
||||
d="m 12.995027,29.476688 10.626,7.222 -10.626,7.222 v -14.444 m -2,-1.778 v 18 c 0,1.1 0.744,1.494 1.654,0.876 l 12.875,-8.752 c 0.455,-0.309 0.682,-0.717 0.682,-1.124 0,-0.408 -0.227,-0.815 -0.682,-1.124 l -12.875,-8.751 c -0.91,-0.619 -1.654,-0.225 -1.654,0.875 z"
|
||||
style="fill:#ffffff" /><path
|
||||
id="path5-0"
|
||||
d="m 15.000437,21.683979 v -6.5 c 0,-1.832003 1.6,-3.500003 3.357,-3.500003 h 10.636 c 1.967,0 3.809,0.854 4.848,2.238003 l 3.457,2.756 c -2.99546,1.819905 -4.21018,2.916329 -6.43718,3.672261 -5.13259,1.742208 -10.47736,1.018549 -15.86082,1.333739 z"
|
||||
style="opacity:0.6;fill:#ffffff" /><path
|
||||
id="path9-3-6"
|
||||
d="m 3.3670166,11.247132 c -0.004,1.278302 0.0179,17.502612 0.0179,17.502612 v 0.0059 0.0059 c 0.0626,4.141039 2.28159,6.407836 4.41211,7.382812 2.13052,0.974976 4.2070304,0.853516 4.2070304,0.853516"
|
||||
style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none" /></svg>
|
After Width: | Height: | Size: 2.4 KiB |
35
images/icon-s-eye.svg
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
style="enable-background:new 0 0 32 32;"
|
||||
viewBox="0 0 32 32"
|
||||
height="32"
|
||||
width="32"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Layer_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata19"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs17" />
|
||||
|
||||
<circle
|
||||
r="4"
|
||||
cy="16"
|
||||
cx="16"
|
||||
id="path861-7"
|
||||
style="opacity:0.6;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /><path
|
||||
id="path826-6"
|
||||
d="m 16.013202,10.0161 c -5.135781,-0.0066 -9.7712792,2.35462 -11.74455,5.983307 1.9732708,3.628688 6.608769,5.991032 11.74455,5.984494 5.107193,-0.0065 9.706497,-2.355358 11.682549,-5.954838 h 0.03565 c -0.0054,-0.01005 -0.01159,-0.01962 -0.01705,-0.02966 0.0055,-0.01002 0.01164,-0.01961 0.01705,-0.02966 h -0.03565 c -1.976079,-3.599428 -6.575398,-5.947148 -11.682549,-5.95365 z"
|
||||
style="opacity:1;vector-effect:none;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /><circle
|
||||
r="2"
|
||||
cy="16"
|
||||
cx="16"
|
||||
id="path861"
|
||||
style="opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /></svg>
|
After Width: | Height: | Size: 1.9 KiB |
28
images/icon-s-link.svg
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
style="enable-background:new 0 0 32 32;"
|
||||
viewBox="0 0 32 32"
|
||||
height="32"
|
||||
width="32"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Layer_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata19"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs17" />
|
||||
|
||||
<path
|
||||
id="rect853-3-7"
|
||||
d="m 5.2218178,19.08774 c -2.1185651,2.118565 -2.1185651,5.573984 -4e-7,7.692548 2.1185648,2.118565 5.5739836,2.118565 7.6925486,0 l 4.866883,-4.866883 c 2.118565,-2.118565 2.118565,-5.573984 0,-7.692549 -2.118564,-2.118564 -5.573983,-2.118564 -7.692548,0 z m 1.4142135,1.414213 4.8668837,-4.866883 c 1.359552,-1.359552 3.504569,-1.359552 4.864121,0 1.359553,1.359553 1.359552,3.504569 0,4.864121 l -4.866884,4.866883 c -1.359552,1.359553 -3.5045682,1.359554 -4.864121,10e-7 -1.3595521,-1.359552 -1.3595521,-3.504569 3e-7,-4.864122 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:0.6;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><path
|
||||
id="rect853-6"
|
||||
d="m 17.290288,17.295275 c -0.604056,-0.141842 -1.179293,-0.451814 -1.657396,-0.929916 -1.359554,-1.359552 -1.358171,-3.503188 0.0014,-4.86274 l -1.7e-5,-4e-6 4.866884,-4.8668837 c 1.359553,-1.3595528 3.503187,-1.3609338 4.86274,-0.00138 1.359553,1.3595528 1.359553,3.5045687 1e-6,4.8641217 l -4.866884,4.866883 c -0.354012,0.354012 -0.76128,0.615843 -1.19407,0.785494 0.09971,0.686342 0.114666,1.379464 -0.04531,2.08658 0.973641,-0.21685 1.898514,-0.702806 2.653575,-1.457867 l 4.866884,-4.866884 c 2.118565,-2.118565 2.118564,-5.5739835 0,-7.6925482 -2.118565,-2.1185648 -5.572602,-2.1171831 -7.691168,0.00138 l -4.866865,4.8668902 c -2.118564,2.118564 -2.119946,5.572602 -0.0014,7.691167 0.825683,0.825683 1.854427,1.329567 2.927951,1.511652 0.245536,-0.61844 0.301651,-1.33063 0.143675,-1.995945 z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /></svg>
|
After Width: | Height: | Size: 4.5 KiB |
27
images/icon-s-pin.svg
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xml:space="preserve"
|
||||
style="enable-background:new 0 0 32 32;"
|
||||
viewBox="0 0 32 32"
|
||||
height="32px"
|
||||
width="32px"
|
||||
y="0px"
|
||||
x="0px"
|
||||
id="Layer_1"
|
||||
version="1.1"><metadata
|
||||
id="metadata17"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs3" /> Updated upstream
|
||||
id="defs15" /><path
|
||||
id="path4567-6-9-2-9-0-3"
|
||||
d="m 18.070362,15.595073 11.557261,13.3774 c 1.011409,0.983239 0.324995,1.686796 -0.658223,0.67537 L 15.619387,18.059831 Z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.99999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /><path
|
||||
id="rect814-5-6"
|
||||
d="M 10.644531,1.8125 C 10.384078,1.8161365 10.13532,1.9212454 9.9511719,2.1054688 L 2.1210938,9.9355469 c -0.3903681,0.3905301 -0.3903681,1.0235321 0,1.4140621 l 4.4667968,4.46875 0.78125,8.173829 c 0.079282,0.842901 1.1046782,1.212138 1.703125,0.613281 l 7.7734374,-7.775391 7.775391,-7.7734374 c 0.598857,-0.5984471 0.22962,-1.623844 -0.613282,-1.703125 L 15.832031,6.5722656 11.365234,2.1054688 C 11.174385,1.9145467 10.91446,1.8088858 10.644531,1.8125 Z"
|
||||
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#ffffff;fill-opacity:0.6;fill-rule:nonzero;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /></svg>
|
After Width: | Height: | Size: 3.8 KiB |
|
@ -1,422 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import QtMultimedia 5.6
|
||||
import "../js/functions.js" as Functions
|
||||
import "../js/debug.js" as Debug
|
||||
|
||||
|
||||
Item {
|
||||
id: audioMessageComponent
|
||||
|
||||
property ListItem messageListItem
|
||||
property MessageOverlayFlickable overlayFlickable
|
||||
property var rawMessage: messageListItem ? messageListItem.myMessage : overlayFlickable.overlayMessage
|
||||
|
||||
property var audioData: ( rawMessage.content['@type'] === "messageVoiceNote" ) ? rawMessage.content.voice_note : ( ( rawMessage.content['@type'] === "messageAudio" ) ? rawMessage.content.audio : "");
|
||||
property string audioUrl;
|
||||
property int previewFileId;
|
||||
property int audioFileId;
|
||||
property bool onScreen: messageListItem ? messageListItem.page.status === PageStatus.Active : true
|
||||
property string audioType : "voiceNote";
|
||||
property bool highlighted;
|
||||
signal clicked();
|
||||
|
||||
width: parent.width
|
||||
height: width / 2
|
||||
|
||||
function getTimeString(rawSeconds) {
|
||||
var minutes = Math.floor( rawSeconds / 60 );
|
||||
var seconds = rawSeconds - ( minutes * 60 );
|
||||
|
||||
if ( minutes < 10 ) {
|
||||
minutes = "0" + minutes;
|
||||
}
|
||||
if ( seconds < 10 ) {
|
||||
seconds = "0" + seconds;
|
||||
}
|
||||
return minutes + ":" + seconds;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
updateAudioThumbnail();
|
||||
}
|
||||
|
||||
function updateAudioThumbnail() {
|
||||
if (audioData) {
|
||||
audioType = ( audioData['@type'] === "voiceNote" ) ? "voice" : "audio";
|
||||
audioFileId = audioData[audioType].id;
|
||||
if (typeof audioData.album_cover_thumbnail !== "undefined") {
|
||||
previewFileId = audioData.album_cover_thumbnail.photo.id;
|
||||
if (audioData.album_cover_thumbnail.photo.local.is_downloading_completed) {
|
||||
placeholderImage.source = audioData.album_cover_thumbnail.photo.local.path;
|
||||
} else {
|
||||
tdLibWrapper.downloadFile(previewFileId);
|
||||
}
|
||||
} else {
|
||||
placeholderImage.source = "image://theme/icon-l-music?white";
|
||||
placeholderImage.width = Theme.itemSizeLarge
|
||||
placeholderImage.height = Theme.itemSizeLarge
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handlePlay() {
|
||||
if (audioData[audioType].local.is_downloading_completed) {
|
||||
audioUrl = audioData[audioType].local.path;
|
||||
audioComponentLoader.active = true;
|
||||
} else {
|
||||
audioDownloadBusyIndicator.running = true;
|
||||
tdLibWrapper.downloadFile(audioFileId);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onFileUpdated: {
|
||||
if (typeof audioData === "object") {
|
||||
if (fileInformation.local.is_downloading_completed) {
|
||||
if (fileId === previewFileId) {
|
||||
audioData.thumbnail.photo = fileInformation;
|
||||
placeholderImage.source = fileInformation.local.path;
|
||||
}
|
||||
if (fileId === audioFileId) {
|
||||
audioDownloadBusyIndicator.running = false;
|
||||
audioData[audioType] = fileInformation;
|
||||
audioUrl = fileInformation.local.path;
|
||||
if (onScreen) {
|
||||
audioComponentLoader.active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fileId === audioFileId) {
|
||||
downloadingProgressBar.maximumValue = fileInformation.size;
|
||||
downloadingProgressBar.value = fileInformation.local.downloaded_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: placeholderImage
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
anchors.centerIn: parent
|
||||
asynchronous: true
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
visible: status === Image.Ready ? true : false
|
||||
layer.enabled: audioMessageComponent.highlighted
|
||||
layer.effect: PressEffect { source: singleImage }
|
||||
}
|
||||
|
||||
BackgroundImage {
|
||||
visible: placeholderImage.status !== Image.Ready
|
||||
layer.enabled: audioMessageComponent.highlighted
|
||||
layer.effect: PressEffect { source: singleImage }
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: placeholderBackground
|
||||
color: "black"
|
||||
opacity: 0.3
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
visible: playButton.visible
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
height: downloadingProgressBar.height + audioControlRow.height
|
||||
anchors.centerIn: parent
|
||||
Row {
|
||||
id: audioControlRow
|
||||
width: parent.width
|
||||
height: Theme.iconSizeLarge
|
||||
Item {
|
||||
height: Theme.iconSizeLarge
|
||||
width: parent.width
|
||||
IconButton {
|
||||
id: playButton
|
||||
anchors.centerIn: parent
|
||||
width: Theme.iconSizeLarge
|
||||
height: Theme.iconSizeLarge
|
||||
icon {
|
||||
source: "image://theme/icon-l-play?white"
|
||||
asynchronous: true
|
||||
}
|
||||
highlighted: audioMessageComponent.highlighted || down
|
||||
visible: placeholderImage.status === Image.Ready ? true : false
|
||||
onClicked: {
|
||||
handlePlay();
|
||||
}
|
||||
}
|
||||
BusyIndicator {
|
||||
id: audioDownloadBusyIndicator
|
||||
running: false
|
||||
visible: running
|
||||
anchors.centerIn: parent
|
||||
size: BusyIndicatorSize.Large
|
||||
}
|
||||
}
|
||||
}
|
||||
ProgressBar {
|
||||
id: downloadingProgressBar
|
||||
minimumValue: 0
|
||||
maximumValue: 100
|
||||
value: 0
|
||||
visible: audioDownloadBusyIndicator.visible
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Rectangle {
|
||||
id: audioErrorShade
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: "lightgrey"
|
||||
visible: placeholderImage.status === Image.Error ? true : false
|
||||
opacity: 0.3
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: errorTextOverlay
|
||||
color: "black"
|
||||
opacity: 0.8
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
visible: false
|
||||
}
|
||||
|
||||
Text {
|
||||
id: errorText
|
||||
visible: false
|
||||
width: parent.width
|
||||
color: Theme.primaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
wrapMode: Text.Wrap
|
||||
text: ""
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: audioComponentLoader
|
||||
active: false
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
sourceComponent: audioComponent
|
||||
}
|
||||
|
||||
Component {
|
||||
id: audioComponent
|
||||
|
||||
Item {
|
||||
width: parent ? parent.width : 0
|
||||
height: parent ? parent.height : 0
|
||||
|
||||
Connections {
|
||||
target: messageAudio
|
||||
onPlaying: {
|
||||
playButton.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: audioMessageComponent
|
||||
onClicked: {
|
||||
if (messageAudio.playbackState === MediaPlayer.PlayingState) {
|
||||
messageAudio.pause();
|
||||
timeLeftItem.visible = true;
|
||||
} else {
|
||||
messageAudio.play();
|
||||
timeLeftTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Audio {
|
||||
id: messageAudio
|
||||
|
||||
Component.onCompleted: {
|
||||
if (messageAudio.error === MediaPlayer.NoError) {
|
||||
messageAudio.play();
|
||||
timeLeftTimer.start();
|
||||
} else {
|
||||
errorText.text = qsTr("Error loading audio! " + messageAudio.errorString)
|
||||
errorTextOverlay.visible = true;
|
||||
errorText.visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
onStatusChanged: {
|
||||
if (status == MediaPlayer.NoMedia) {
|
||||
Debug.log("No Media");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
if (status == MediaPlayer.Loading) {
|
||||
Debug.log("Loading");
|
||||
audioBusyIndicator.visible = true;
|
||||
}
|
||||
if (status == MediaPlayer.Loaded) {
|
||||
Debug.log("Loaded");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
if (status == MediaPlayer.Buffering) {
|
||||
Debug.log("Buffering");
|
||||
audioBusyIndicator.visible = true;
|
||||
}
|
||||
if (status == MediaPlayer.Stalled) {
|
||||
Debug.log("Stalled");
|
||||
audioBusyIndicator.visible = true;
|
||||
}
|
||||
if (status == MediaPlayer.Buffered) {
|
||||
Debug.log("Buffered");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
if (status == MediaPlayer.EndOfMedia) {
|
||||
Debug.log("End of Media");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
if (status == MediaPlayer.InvalidMedia) {
|
||||
Debug.log("Invalid Media");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
if (status == MediaPlayer.UnknownStatus) {
|
||||
Debug.log("Unknown Status");
|
||||
audioBusyIndicator.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
source: audioUrl
|
||||
|
||||
onStopped: {
|
||||
playButton.visible = true;
|
||||
audioComponentLoader.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: audioBusyIndicator
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: false
|
||||
running: visible
|
||||
size: BusyIndicatorSize.Medium
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timeLeftTimer
|
||||
repeat: false
|
||||
interval: 2000
|
||||
onTriggered: {
|
||||
timeLeftItem.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: timeLeftItem
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
opacity: visible ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
|
||||
Rectangle {
|
||||
id: positionTextOverlay
|
||||
color: "black"
|
||||
opacity: 0.3
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: pausedRow.visible
|
||||
}
|
||||
|
||||
Row {
|
||||
id: pausedRow
|
||||
width: parent.width
|
||||
height: parent.height - ( messageAudioSlider.visible ? messageAudioSlider.height : 0 ) - ( positionText.visible ? positionText.height : 0 )
|
||||
visible: audioComponentLoader.active && messageAudio.playbackState === MediaPlayer.PausedState
|
||||
Item {
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
IconButton {
|
||||
id: pausedPlayButton
|
||||
anchors.centerIn: parent
|
||||
width: Theme.iconSizeLarge
|
||||
height: Theme.iconSizeLarge
|
||||
highlighted: videoMessageComponent.highlighted || down
|
||||
icon {
|
||||
asynchronous: true
|
||||
source: "image://theme/icon-l-play?white"
|
||||
}
|
||||
onClicked: {
|
||||
messageAudio.play();
|
||||
timeLeftTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: messageAudioSlider
|
||||
width: parent.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: positionText.top
|
||||
minimumValue: 0
|
||||
maximumValue: messageAudio.duration ? messageAudio.duration : 0
|
||||
stepSize: 1
|
||||
value: messageAudio.position
|
||||
enabled: messageAudio.seekable
|
||||
visible: (messageAudio.duration > 0)
|
||||
highlighted: videoMessageComponent.highlighted || down
|
||||
onReleased: {
|
||||
messageAudio.seek(Math.floor(value));
|
||||
messageAudio.play();
|
||||
timeLeftTimer.start();
|
||||
}
|
||||
valueText: getTimeString(Math.round((messageAudio.duration - messageAudioSlider.value) / 1000))
|
||||
}
|
||||
|
||||
Text {
|
||||
id: positionText
|
||||
visible: messageAudio.duration === 0
|
||||
color: Theme.primaryColor
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
bottomMargin: Theme.paddingSmall
|
||||
horizontalCenter: positionTextOverlay.horizontalCenter
|
||||
}
|
||||
wrapMode: Text.Wrap
|
||||
text: ( messageAudio.duration - messageAudio.position ) > 0 ? getTimeString(Math.round((messageAudio.duration - messageAudio.position) / 1000)) : "-:-"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -9,30 +9,72 @@ PhotoTextsListItem {
|
|||
id: listItem
|
||||
pictureThumbnail {
|
||||
photoData: photo_small || ({})
|
||||
highlighted: listItem.highlighted && !listItem.menuOpen
|
||||
}
|
||||
property int ownUserId
|
||||
property bool showDraft: !!draft_message_text && draft_message_date > last_message_date
|
||||
property string previewText: showDraft ? draft_message_text : last_message_text
|
||||
|
||||
// chat title
|
||||
primaryText.text: title ? Emoji.emojify(title + ( display.notification_settings.mute_for > 0 ? " 🔇" : "" ), Theme.fontSizeMedium) : qsTr("Unknown")
|
||||
primaryText.text: title ? Emoji.emojify(title, Theme.fontSizeMedium) : qsTr("Unknown")
|
||||
// last user
|
||||
prologSecondaryText.text: is_channel ? "" : ( last_message_sender_id ? ( last_message_sender_id !== ownUserId ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(last_message_sender_id)), primaryText.font.pixelSize) : qsTr("You") ) : "" )
|
||||
prologSecondaryText.text: showDraft ? "<i>"+qsTr("Draft")+"</i>" : (is_channel ? "" : ( last_message_sender_id ? ( last_message_sender_id !== ownUserId ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(last_message_sender_id)), Theme.fontSizeExtraSmall) : qsTr("You") ) : "" ))
|
||||
// last message
|
||||
secondaryText.text: last_message_text ? Emoji.emojify(Functions.enhanceHtmlEntities(last_message_text), Theme.fontSizeExtraSmall) : "<i>" + qsTr("No message in this chat.") + "</i>"
|
||||
secondaryText.text: previewText ? Emoji.emojify(Functions.enhanceHtmlEntities(previewText), Theme.fontSizeExtraSmall) : "<i>" + qsTr("No message in this chat.") + "</i>"
|
||||
// message date
|
||||
tertiaryText.text: ( last_message_date ? ( last_message_date.length === 0 ? "" : Functions.getDateTimeElapsed(last_message_date) + Emoji.emojify(last_message_status, tertiaryText.font.pixelSize) ) : "" )
|
||||
tertiaryText.text: showDraft ? Functions.getDateTimeElapsed(draft_message_date) : ( last_message_date ? ( last_message_date.length === 0 ? "" : Functions.getDateTimeElapsed(last_message_date) + Emoji.emojify(last_message_status, tertiaryText.font.pixelSize) ) : "" )
|
||||
unreadCount: unread_count
|
||||
unreadReactionCount: unread_reaction_count
|
||||
unreadMentionCount: unread_mention_count
|
||||
isSecret: ( chat_type === TelegramAPI.ChatTypeSecret )
|
||||
isMarkedAsUnread: is_marked_as_unread
|
||||
isPinned: is_pinned
|
||||
isMuted: display.notification_settings.mute_for > 0
|
||||
|
||||
openMenuOnPressAndHold: true//chat_id != overviewPage.ownUserId
|
||||
menu: ContextMenu {
|
||||
|
||||
onPressAndHold: {
|
||||
contextMenuLoader.active = true;
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: contextMenuLoader
|
||||
active: false
|
||||
asynchronous: true
|
||||
onStatusChanged: {
|
||||
if(status === Loader.Ready) {
|
||||
listItem.menu = item;
|
||||
listItem.openMenu();
|
||||
}
|
||||
}
|
||||
sourceComponent: Component {
|
||||
ContextMenu {
|
||||
MenuItem {
|
||||
visible: unread_count > 0
|
||||
visible: unread_count > 0 || unread_reaction_count > 0 || unread_mention_count > 0
|
||||
onClicked: {
|
||||
tdLibWrapper.viewMessage(chat_id, display.last_message.id, true);
|
||||
tdLibWrapper.readAllChatMentions(chat_id);
|
||||
tdLibWrapper.readAllChatReactions(chat_id);
|
||||
tdLibWrapper.toggleChatIsMarkedAsUnread(chat_id, false);
|
||||
}
|
||||
text: qsTr("Mark all messages as read")
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
visible: unread_count === 0 && unread_reaction_count === 0 && unread_mention_count === 0
|
||||
onClicked: {
|
||||
tdLibWrapper.toggleChatIsMarkedAsUnread(chat_id, !is_marked_as_unread);
|
||||
}
|
||||
text: is_marked_as_unread ? qsTr("Mark chat as read") : qsTr("Mark chat as unread")
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
onClicked: {
|
||||
tdLibWrapper.toggleChatIsPinned(chat_id, !is_pinned);
|
||||
}
|
||||
text: is_pinned ? qsTr("Unpin chat") : qsTr("Pin chat")
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
visible: chat_id != listItem.ownUserId
|
||||
onClicked: {
|
||||
|
@ -45,7 +87,7 @@ PhotoTextsListItem {
|
|||
newNotificationSettings.use_default_mute_for = false;
|
||||
tdLibWrapper.setChatNotificationSettings(chat_id, newNotificationSettings);
|
||||
}
|
||||
text: display.notification_settings.mute_for > 0 ? qsTr("Unmute Chat") : qsTr("Mute Chat")
|
||||
text: display.notification_settings.mute_for > 0 ? qsTr("Unmute chat") : qsTr("Mute chat")
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
|
@ -59,5 +101,7 @@ PhotoTextsListItem {
|
|||
text: model.display.type['@type'] === "chatTypePrivate" ? qsTr("User Info") : qsTr("Group Info")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
44
qml/components/ContactSync.qml
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright (C) 2021 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.0
|
||||
//import org.nemomobile.contacts 1.0
|
||||
|
||||
Item {
|
||||
|
||||
// signal syncError();
|
||||
|
||||
// function synchronize() {
|
||||
// if (peopleModel.count === 0) {
|
||||
// appNotification.show(qsTr("Could not synchronize your contacts with Telegram."));
|
||||
// syncError();
|
||||
// } else {
|
||||
// contactsModel.startImportingContacts();
|
||||
// for (var i = 0; i < peopleModel.count; i++ ) {
|
||||
// contactsModel.importContact(peopleModel.get(i));
|
||||
// }
|
||||
// contactsModel.stopImportingContacts();
|
||||
// }
|
||||
// }
|
||||
|
||||
// PeopleModel {
|
||||
// id: peopleModel
|
||||
// requiredProperty: PeopleModel.PhoneNumberRequired
|
||||
// }
|
||||
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
Item {
|
||||
|
||||
id: documentPreviewItem
|
||||
width: parent.width
|
||||
height: Theme.itemSizeLarge
|
||||
|
||||
property ListItem messageListItem
|
||||
property MessageOverlayFlickable overlayFlickable
|
||||
property var rawMessage: messageListItem ? messageListItem.myMessage : overlayFlickable.overlayMessage
|
||||
|
||||
property var documentData: rawMessage.content.document
|
||||
property bool openRequested: false;
|
||||
property bool highlighted;
|
||||
|
||||
Component.onCompleted: {
|
||||
updateDocument();
|
||||
}
|
||||
|
||||
function updateDocument() {
|
||||
if (documentData) {
|
||||
if (documentData.document.local.is_downloading_completed) {
|
||||
downloadDocumentButton.visible = false;
|
||||
openDocumentButton.visible = true;
|
||||
} else {
|
||||
openDocumentButton.visible = false;
|
||||
downloadDocumentButton.visible = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onFileUpdated: {
|
||||
if (documentData) {
|
||||
if (!fileInformation.remote.is_uploading_active && fileId === documentData.document.id && fileInformation.local.is_downloading_completed) {
|
||||
downloadingProgressBar.visible = false;
|
||||
documentData.document = fileInformation;
|
||||
downloadDocumentButton.visible = false;
|
||||
openDocumentButton.visible = true;
|
||||
if (documentPreviewItem.openRequested) {
|
||||
documentPreviewItem.openRequested = false;
|
||||
tdLibWrapper.openFileOnDevice(documentData.document.local.path);
|
||||
}
|
||||
}
|
||||
if (fileId === documentData.document.id) {
|
||||
downloadingProgressBar.maximumValue = fileInformation.size;
|
||||
downloadingProgressBar.value = fileInformation.local.downloaded_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: downloadDocumentButton
|
||||
preferredWidth: Theme.buttonWidthMedium
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Download Document")
|
||||
visible: false
|
||||
highlighted: videoMessageComponent.highlighted || down
|
||||
onClicked: {
|
||||
downloadDocumentButton.visible = false;
|
||||
downloadingProgressBar.visible = true;
|
||||
tdLibWrapper.downloadFile(documentData.document.id);
|
||||
}
|
||||
}
|
||||
|
||||
ProgressBar {
|
||||
id: downloadingProgressBar
|
||||
minimumValue: 0
|
||||
maximumValue: 100
|
||||
value: 0
|
||||
visible: false
|
||||
width: parent.width
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Button {
|
||||
id: openDocumentButton
|
||||
preferredWidth: Theme.buttonWidthMedium
|
||||
anchors.centerIn: parent
|
||||
text: qsTr("Open Document")
|
||||
visible: false
|
||||
highlighted: videoMessageComponent.highlighted || down
|
||||
onClicked: {
|
||||
documentPreviewItem.openRequested = true;
|
||||
tdLibWrapper.openFileOnDevice(documentData.document.local.path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
|
||||
Item {
|
||||
id: imagePreviewItem
|
||||
|
||||
property ListItem messageListItem
|
||||
property MessageOverlayFlickable overlayFlickable
|
||||
property var rawMessage: messageListItem ? messageListItem.myMessage : overlayFlickable.overlayMessage
|
||||
property var photoData: rawMessage.content.photo
|
||||
readonly property int defaultHeight: Math.round(width * 2 / 3)
|
||||
property bool highlighted
|
||||
|
||||
width: parent.width
|
||||
height: singleImage.visible ? Math.min(defaultHeight, singleImage.bestHeight + Theme.paddingSmall) : defaultHeight
|
||||
|
||||
function clicked() {
|
||||
pageStack.push(Qt.resolvedUrl("../pages/ImagePage.qml"), {
|
||||
"photoData" : imagePreviewItem.photoData,
|
||||
"pictureFileInformation" : imageFile.fileInformation
|
||||
})
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (photoData) {
|
||||
// Check first which size fits best...
|
||||
var photo
|
||||
for (var i = 0; i < photoData.sizes.length; i++) {
|
||||
photo = photoData.sizes[i].photo
|
||||
if (photoData.sizes[i].width >= imagePreviewItem.width) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (photo) {
|
||||
imageFile.fileInformation = photo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TDLibFile {
|
||||
id: imageFile
|
||||
tdlib: tdLibWrapper
|
||||
autoLoad: true
|
||||
}
|
||||
|
||||
Image {
|
||||
id: singleImage
|
||||
width: parent.width - Theme.paddingSmall
|
||||
height: parent.height - Theme.paddingSmall
|
||||
readonly property int bestHeight: (status === Image.Ready) ? Math.round(implicitHeight * width / implicitWidth) : 0
|
||||
anchors.centerIn: parent
|
||||
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
autoTransform: true
|
||||
asynchronous: true
|
||||
source: imageFile.isDownloadingCompleted ? imageFile.path : ""
|
||||
visible: status === Image.Ready
|
||||
opacity: visible ? 1 : 0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
layer.enabled: imagePreviewItem.highlighted
|
||||
layer.effect: PressEffect { source: singleImage }
|
||||
}
|
||||
|
||||
BackgroundImage {
|
||||
visible: singleImage.status !== Image.Ready
|
||||
}
|
||||
}
|
|
@ -31,13 +31,21 @@ Row {
|
|||
property string myUserId;
|
||||
property var inReplyToMessage;
|
||||
property bool editable: false;
|
||||
property bool inReplyToMessageDeleted: false;
|
||||
|
||||
signal clearRequested()
|
||||
|
||||
onInReplyToMessageChanged: {
|
||||
if (inReplyToMessage) {
|
||||
inReplyToUserText.text = (inReplyToRow.inReplyToMessage.sender_user_id !== inReplyToRow.myUserId) ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(inReplyToRow.inReplyToMessage.sender_user_id)), inReplyToUserText.font.pixelSize) : qsTr("You");
|
||||
inReplyToMessageText.text = Emoji.emojify(Functions.getMessageText(inReplyToRow.inReplyToMessage, true, inReplyToRow.inReplyToMessage.sender_user_id === inReplyToRow.myUserId, false), inReplyToMessageText.font.pixelSize);
|
||||
inReplyToUserText.text = (inReplyToMessage.sender_id["@type"] === "messageSenderChat" ? page.chatInformation.title : (inReplyToRow.inReplyToMessage.sender_id.user_id !== inReplyToRow.myUserId) ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(inReplyToRow.inReplyToMessage.sender_id.user_id)), inReplyToUserText.font.pixelSize) : qsTr("You"));
|
||||
inReplyToMessageText.text = Emoji.emojify(Functions.getMessageText(inReplyToRow.inReplyToMessage, true, inReplyToRow.myUserId, false), inReplyToMessageText.font.pixelSize);
|
||||
}
|
||||
}
|
||||
|
||||
onInReplyToMessageDeletedChanged: {
|
||||
if (inReplyToMessageDeleted) {
|
||||
inReplyToUserText.text = qsTr("Unknown")
|
||||
inReplyToMessageText.text = "<i>" + qsTr("This message was deleted") + "</i>";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,6 +85,10 @@ Row {
|
|||
textFormat: Text.StyledText
|
||||
truncationMode: TruncationMode.Fade
|
||||
maximumLineCount: 1
|
||||
linkColor: Theme.highlightColor
|
||||
onLinkActivated: {
|
||||
Functions.handleLink(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
|
@ -27,6 +28,7 @@ Column {
|
|||
property string emptyPlaceholderText
|
||||
property string text
|
||||
property bool multiLine
|
||||
property bool headerLeftAligned
|
||||
|
||||
property bool isEditing
|
||||
property Item editItem: multiLine ? editAreaTextArea : editAreaTextField
|
||||
|
@ -41,6 +43,7 @@ Column {
|
|||
id: editAreaHeader
|
||||
height: parent.visible && text !== "" ? Theme.itemSizeExtraSmall : 0
|
||||
x: 0
|
||||
horizontalAlignment: headerLeftAligned ? Text.AlignLeft : Text.AlignRight
|
||||
}
|
||||
Row {
|
||||
id: editAreaTextRow
|
||||
|
@ -50,20 +53,24 @@ Column {
|
|||
id: editAreaTextArea
|
||||
visible: editAreaColumn.isEditing && editAreaColumn.multiLine
|
||||
width: parent.width - editAreaButton.width
|
||||
textLeftMargin: 0
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
}
|
||||
TextField {
|
||||
id: editAreaTextField
|
||||
visible: editAreaColumn.isEditing && !editAreaColumn.multiLine
|
||||
width: parent.width - editAreaButton.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
textLeftMargin: 0
|
||||
EnterKey.onClicked: {
|
||||
editAreaColumn.isEditing = false;
|
||||
editAreaColumn.saveButtonClicked(editAreaColumn.editItem.text);
|
||||
}
|
||||
EnterKey.iconSource: editAreaButton.icon.source
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
}
|
||||
ChatInformationTextItem {
|
||||
InformationTextItem {
|
||||
id: editAreaTextItem
|
||||
visible: !editAreaColumn.isEditing
|
||||
anchors.verticalCenter: parent.verticalCenter
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
|
@ -16,11 +16,12 @@
|
|||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
import "../../js/functions.js" as Functions
|
||||
import "../js/twemoji.js" as Emoji
|
||||
import "../js/functions.js" as Functions
|
||||
|
||||
Column {
|
||||
id: textItem
|
||||
|
@ -47,7 +48,7 @@ Column {
|
|||
id: labelComponent
|
||||
Label {
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
textFormat: Text.StyledText
|
||||
color: Theme.primaryColor
|
||||
text: Emoji.emojify( Functions.replaceUrlsWithLinks(textItem.text).replace(/\n/g, "<br>"), Theme.fontSizeExtraSmall)
|
399
qml/components/InlineQuery.qml
Normal file
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "../js/debug.js" as Debug
|
||||
import "../js/twemoji.js" as Emoji
|
||||
import "../js/functions.js" as Functions
|
||||
|
||||
Loader {
|
||||
id: inlineQueryLoader
|
||||
active: userName.length > 1
|
||||
asynchronous: true
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
bottom: active ? parent.bottom : parent.top
|
||||
}
|
||||
property bool hasOverlay: active && userNameIsValid && status === Loader.Ready && item.overlay && item.overlay.status === Loader.Ready
|
||||
property bool hasButton: active && userNameIsValid && status === Loader.Ready && item.button && item.button.status === Loader.Ready
|
||||
|
||||
property int buttonPadding: hasButton ? item.button.height + Theme.paddingSmall : 0
|
||||
Behavior on buttonPadding { NumberAnimation { duration: 200} }
|
||||
|
||||
property string chatId
|
||||
property string userName
|
||||
property bool userNameIsValid: userName !== "" && inlineBotInformation && userName.toLowerCase() === inlineBotInformation.usernames.editable_username.toLowerCase()
|
||||
property string query
|
||||
property int currentOffset: 0
|
||||
property string responseExtra: chatId+"|"+userName+"|"+query+"|"+currentOffset
|
||||
|
||||
property bool queued: false
|
||||
property TextArea textField
|
||||
property bool isLoading
|
||||
property var inlineBotInformation: null
|
||||
onIsLoadingChanged: {
|
||||
requestTimeout.start();
|
||||
}
|
||||
|
||||
onStatusChanged: {
|
||||
inlineBotInformation = null;
|
||||
if(status === Loader.Ready && userName !== "") {
|
||||
isLoading = true; inlineQueryLoader.chatId
|
||||
tdLibWrapper.searchPublicChat(userName, false);
|
||||
}
|
||||
}
|
||||
|
||||
onUserNameChanged: {
|
||||
inlineBotInformation = null;
|
||||
|
||||
if(status === Loader.Ready && userName !== "") {
|
||||
isLoading = true;
|
||||
tdLibWrapper.searchPublicChat(userName, false);
|
||||
}
|
||||
}
|
||||
|
||||
onQueryChanged: {
|
||||
if(userName.length > 0) {
|
||||
isLoading = true;
|
||||
requestTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
function handleQuery(name, query, offset) {
|
||||
if(!name) {
|
||||
inlineQueryLoader.userName = "";
|
||||
inlineQueryLoader.query = "";
|
||||
return;
|
||||
}
|
||||
if(inlineQueryLoader.userName !== name) {
|
||||
inlineQueryLoader.userName = name
|
||||
}
|
||||
if(inlineQueryLoader.query !== query) {
|
||||
inlineQueryLoader.query = query
|
||||
}
|
||||
inlineQueryLoader.currentOffset = offset || 0
|
||||
}
|
||||
|
||||
function request() {
|
||||
if(!inlineBotInformation || !userNameIsValid) {
|
||||
queued = true;
|
||||
} else {
|
||||
queued = false;
|
||||
var location = null;
|
||||
if(inlineBotInformation.type.need_location && fernschreiberUtils.supportsGeoLocation()) {
|
||||
fernschreiberUtils.startGeoLocationUpdates();
|
||||
if(!attachmentPreviewRow.locationData.latitude) {
|
||||
queued = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
tdLibWrapper.getInlineQueryResults(inlineBotInformation.id, chatId, location, query, inlineQueryLoader.currentOffset, inlineQueryLoader.responseExtra);
|
||||
isLoading = true;
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: requestTimeout
|
||||
interval: 5000
|
||||
onTriggered: {
|
||||
inlineQueryLoader.isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: requestTimer
|
||||
interval: 1000
|
||||
onTriggered: {
|
||||
request();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: fernschreiberUtils
|
||||
onNewPositionInformation: {
|
||||
attachmentPreviewRow.locationData = positionInformation;
|
||||
if (inlineQueryLoader.queued) {
|
||||
inlineQueryLoader.queued = false;
|
||||
inlineQueryLoader.request()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: textField
|
||||
onTextChanged: {
|
||||
if(textField.text.charAt(0) === '@') {
|
||||
var queryMatch = textField.text.match(/^@([a-zA-Z0-9_]+)\s(.*)/);
|
||||
if(queryMatch) {
|
||||
inlineQueryLoader.handleQuery(queryMatch[1], queryMatch[2]);
|
||||
} else {
|
||||
inlineQueryLoader.handleQuery();
|
||||
}
|
||||
} else {
|
||||
inlineQueryLoader.handleQuery();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sourceComponent: Component {
|
||||
Item {
|
||||
id: inlineQueryComponent
|
||||
anchors.fill: parent
|
||||
property alias overlay: resultsOverlay
|
||||
property alias button: switchToPmLoader
|
||||
property string nextOffset
|
||||
property string inlineQueryId
|
||||
property string switchPmText
|
||||
property string switchPmParameter
|
||||
property ListModel resultModel: ListModel {
|
||||
dynamicRoles: true
|
||||
}
|
||||
property string inlineQueryPlaceholder: inlineBotInformation ? inlineBotInformation.type.inline_query_placeholder : ""
|
||||
property bool showInlineQueryPlaceholder: !!inlineQueryPlaceholder && query === ""
|
||||
property string useDelegateSize: "default"
|
||||
property var dimensions: ({
|
||||
"default": [[Screen.width, Screen.height / 2], [Theme.itemSizeLarge, Theme.itemSizeLarge]], // whole line (portrait half)
|
||||
"inlineQueryResultAnimation": [[Screen.width / 3, Screen.height / 6], [Screen.width / 3, Screen.height / 6]],
|
||||
"inlineQueryResultVideo": [[Screen.width / 2, Screen.height / 4], [Theme.itemSizeLarge, Theme.itemSizeLarge]],
|
||||
"inlineQueryResultSticker": [[Screen.width / 3, Screen.height / 6], [Screen.width / 3, Screen.height / 6]],
|
||||
"inlineQueryResultPhoto": [[Screen.width/2, Screen.height / 3], [Theme.itemSizeExtraLarge, Theme.itemSizeExtraLarge]],
|
||||
})
|
||||
property int delegateWidth: chatPage.isPortrait ? dimensions[useDelegateSize][0][0] : dimensions[useDelegateSize][0][1]
|
||||
property int delegateHeight: chatPage.isPortrait ? dimensions[useDelegateSize][1][0] : dimensions[useDelegateSize][1][1]
|
||||
|
||||
function setDelegateSizes() {
|
||||
var sizeKey = "default";
|
||||
var modelCount = resultModel.count;
|
||||
if(modelCount > 0) {
|
||||
var firstType = resultModel.get(0)["@type"];
|
||||
if(firstType && dimensions[firstType]) {
|
||||
var startIndex = inlineQueryLoader.currentOffset === 0 ? 1 : inlineQueryLoader.currentOffset;
|
||||
var same = true;
|
||||
for(var i = startIndex; i < modelCount; i += 1) {
|
||||
if(resultModel.get(i)["@type"] !== firstType) {
|
||||
same = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(same) {
|
||||
sizeKey = firstType;
|
||||
}
|
||||
}
|
||||
}
|
||||
useDelegateSize = sizeKey;
|
||||
}
|
||||
|
||||
function loadMore() {
|
||||
if(nextOffset && inlineQueryLoader.userNameIsValid) {
|
||||
inlineQueryLoader.currentOffset = nextOffset;
|
||||
inlineQueryLoader.request();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
|
||||
onChatReceived: {
|
||||
if(chat["@extra"] === "searchPublicChat:"+inlineQueryLoader.userName) {
|
||||
requestTimeout.stop();
|
||||
inlineQueryLoader.isLoading = false;
|
||||
var inlineBotInformation = tdLibWrapper.getUserInformation(chat.type.user_id);
|
||||
if(inlineBotInformation && inlineBotInformation.type["@type"] === "userTypeBot" && inlineBotInformation.type.is_inline) {
|
||||
inlineQueryLoader.inlineBotInformation = inlineBotInformation;
|
||||
requestTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
onInlineQueryResults: {
|
||||
if(extra === inlineQueryLoader.responseExtra) {
|
||||
requestTimeout.stop();
|
||||
inlineQueryLoader.isLoading = false;
|
||||
inlineQueryComponent.inlineQueryId = inlineQueryId
|
||||
inlineQueryComponent.nextOffset = nextOffset
|
||||
inlineQueryComponent.switchPmText = switchPmText
|
||||
inlineQueryComponent.switchPmParameter = switchPmParameter
|
||||
|
||||
if(inlineQueryLoader.currentOffset === 0) {
|
||||
inlineQueryComponent.resultModel.clear()
|
||||
}
|
||||
for(var i = 0; i < results.length; i++) {
|
||||
inlineQueryComponent.resultModel.append(results[i]);
|
||||
}
|
||||
|
||||
if(inlineQueryLoader.currentOffset === 0 || inlineQueryLoader.useDelegateSize !== "default") {
|
||||
inlineQueryComponent.setDelegateSizes()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// switch to pm Button
|
||||
Loader {
|
||||
id: switchToPmLoader
|
||||
asynchronous: true
|
||||
active: inlineQueryComponent.switchPmText.length > 0
|
||||
opacity: status === Loader.Ready ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
height: Theme.itemSizeSmall
|
||||
anchors {
|
||||
top: parent.bottom
|
||||
topMargin: Theme.paddingSmall
|
||||
left: parent.left
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
right: parent.right
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
sourceComponent: Component {
|
||||
MouseArea {
|
||||
id: customButton
|
||||
onClicked: {
|
||||
tdLibWrapper.createPrivateChat(inlineQueryLoader.inlineBotInformation.id, "openAndSendStartToBot:"+(inlineQueryComponent.switchPmParameter.length > 0 ? " "+inlineQueryComponent.switchPmParameter:""));
|
||||
}
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: Theme.paddingSmall
|
||||
color: parent.pressed ? Theme.highlightBackgroundColor : Theme.rgba(Theme.DarkOnLight ? Qt.lighter(Theme.primaryColor) : Qt.darker(Theme.primaryColor), Theme.opacityFaint)
|
||||
Label {
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: Theme.paddingLarge
|
||||
rightMargin: Theme.paddingLarge
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
fontSizeMode: Text.Fit;
|
||||
minimumPixelSize: Theme.fontSizeTiny;
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
|
||||
color: customButton.pressed ? Theme.highlightColor : Theme.primaryColor
|
||||
text: Emoji.emojify(inlineQueryComponent.switchPmText, font.pixelSize)// + "we are gonna make this a bit longer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// results grid overlay
|
||||
Loader {
|
||||
id: resultsOverlay
|
||||
asynchronous: true
|
||||
active: inlineQueryComponent.resultModel.count > 0
|
||||
anchors.fill: parent
|
||||
opacity: !!item ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
property var supportedResultTypes: [
|
||||
"inlineQueryResultAnimation",
|
||||
"inlineQueryResultArticle",
|
||||
"inlineQueryResultAudio",
|
||||
"inlineQueryResultContact",
|
||||
"inlineQueryResultDocument",
|
||||
"inlineQueryResultGame",
|
||||
"inlineQueryResultLocation",
|
||||
"inlineQueryResultPhoto",
|
||||
"inlineQueryResultSticker",
|
||||
"inlineQueryResultVenue",
|
||||
"inlineQueryResultVideo",
|
||||
"inlineQueryResultVoiceNote",
|
||||
]
|
||||
sourceComponent: Component {
|
||||
Item {
|
||||
Rectangle {
|
||||
id: messageContentBackground
|
||||
color: Theme.overlayBackgroundColor
|
||||
opacity: 0.7
|
||||
anchors.fill: parent
|
||||
}
|
||||
Timer {
|
||||
id: autoLoadMoreTimer
|
||||
interval: 400
|
||||
onTriggered: {
|
||||
if (inlineQueryComponent.nextOffset && resultView.height > resultView.contentHeight - Theme.itemSizeHuge) {
|
||||
inlineQueryComponent.loadMore();
|
||||
}
|
||||
}
|
||||
}
|
||||
SilicaGridView {
|
||||
id: resultView
|
||||
anchors.fill: parent
|
||||
cellWidth: inlineQueryComponent.delegateWidth
|
||||
cellHeight: inlineQueryComponent.delegateHeight
|
||||
|
||||
signal requestPlayback(url playbackSource)
|
||||
clip: true
|
||||
model: inlineQueryComponent.resultModel
|
||||
delegate: Loader {
|
||||
id: queryResultDelegate
|
||||
height: resultView.cellHeight
|
||||
width: resultView.cellWidth
|
||||
source: "inlineQueryResults/" + (resultsOverlay.supportedResultTypes.indexOf(model["@type"]) > -1 ? (model["@type"].charAt(0).toUpperCase() + model["@type"].substring(1)) : "InlineQueryResultDefaultBase") +".qml"
|
||||
}
|
||||
footer: Component {
|
||||
Item {
|
||||
width: resultView.width
|
||||
visible: height > 0
|
||||
height: inlineQueryComponent.nextOffset ? Theme.itemSizeLarge : 0
|
||||
Behavior on height { NumberAnimation { duration: 500 } }
|
||||
}
|
||||
}
|
||||
|
||||
onContentYChanged: {
|
||||
if(!inlineQueryLoader.isLoading && inlineQueryComponent.nextOffset && contentHeight - contentY - height < Theme.itemSizeHuge) {
|
||||
inlineQueryComponent.loadMore();
|
||||
}
|
||||
}
|
||||
|
||||
ScrollDecorator { flickable: resultView }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// textarea placeholder
|
||||
Loader {
|
||||
asynchronous: true
|
||||
active: inlineQueryComponent.showInlineQueryPlaceholder
|
||||
sourceComponent: Component {
|
||||
Label {
|
||||
text: Emoji.emojify(inlineQueryComponent.inlineQueryPlaceholder, font.pixelSize);
|
||||
parent: textField
|
||||
anchors.fill: parent
|
||||
anchors.leftMargin: textMetrics.boundingRect.width + Theme.paddingSmall
|
||||
font: textField.font
|
||||
color: Theme.secondaryColor
|
||||
|
||||
truncationMode: TruncationMode.Fade
|
||||
TextMetrics {
|
||||
id: textMetrics
|
||||
font: textField.font
|
||||
text: textField.text
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import QtGraphicalEffects 1.0
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
Item {
|
||||
|
||||
id: imagePreviewItem
|
||||
|
||||
property ListItem messageListItem
|
||||
property MessageOverlayFlickable overlayFlickable
|
||||
property var rawMessage: messageListItem ? messageListItem.myMessage : overlayFlickable.overlayMessage
|
||||
property bool highlighted
|
||||
|
||||
property var locationData : ( rawMessage.content['@type'] === "messageLocation" ) ? rawMessage.content.location : ( ( rawMessage.content['@type'] === "messageVenue" ) ? rawMessage.content.venue.location : "" )
|
||||
|
||||
property string chatId: rawMessage.chat_id
|
||||
property var pictureFileInformation;
|
||||
width: parent.width
|
||||
height: width / 2
|
||||
|
||||
Component.onCompleted: {
|
||||
updatePicture();
|
||||
}
|
||||
function clicked(){
|
||||
if(!processLauncher.launchProgram('harbour-pure-maps', ["geo:"+locationData.latitude+","+locationData.longitude])) {
|
||||
imageNotification.show(qsTr("Install Pure Maps to inspect this location."));
|
||||
}
|
||||
}
|
||||
function updatePicture() {
|
||||
imagePreviewItem.pictureFileInformation = null;
|
||||
if (locationData) {
|
||||
tdLibWrapper.getMapThumbnailFile(chatId, locationData.latitude, locationData.longitude, Math.round(imagePreviewItem.width), Math.round(imagePreviewItem.height));
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onFileUpdated: {
|
||||
// we do not have a way of knowing if this is the correct file, so we have to guess the first new one should be right.
|
||||
if(!imagePreviewItem.pictureFileInformation) {
|
||||
imagePreviewItem.pictureFileInformation = fileInformation;
|
||||
tdLibWrapper.downloadFile(imagePreviewItem.pictureFileInformation.id);
|
||||
} else if(imagePreviewItem.pictureFileInformation && fileInformation.id === imagePreviewItem.pictureFileInformation.id) {
|
||||
imagePreviewItem.pictureFileInformation = fileInformation;
|
||||
singleImage.source = fileInformation.local.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AppNotification {
|
||||
id: imageNotification
|
||||
}
|
||||
|
||||
Image {
|
||||
id: singleImage
|
||||
width: parent.width - Theme.paddingSmall
|
||||
height: parent.height - Theme.paddingSmall
|
||||
anchors.centerIn: parent
|
||||
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
autoTransform: true
|
||||
asynchronous: true
|
||||
visible: status === Image.Ready
|
||||
opacity: status === Image.Ready ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
|
||||
layer.enabled: imagePreviewItem.highlighted
|
||||
layer.effect: PressEffect { source: singleImage }
|
||||
Item {
|
||||
anchors.centerIn: parent
|
||||
width: markerImage.width
|
||||
height: markerImage.height * 1.75 // 0.875 (vertical pin point) * 2
|
||||
Image {
|
||||
id: markerImage
|
||||
source: 'image://theme/icon-m-location'
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
anchors.fill: markerImage
|
||||
horizontalOffset: 3
|
||||
verticalOffset: 3
|
||||
radius: 8.0
|
||||
samples: 17
|
||||
color: Theme.colorScheme ? Theme.lightPrimaryColor : Theme.darkPrimaryColor
|
||||
source: markerImage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BackgroundImage {
|
||||
visible: singleImage.status !== Image.Ready
|
||||
}
|
||||
|
||||
}
|
|
@ -18,53 +18,200 @@
|
|||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "./messageContent"
|
||||
import "../js/twemoji.js" as Emoji
|
||||
import "../js/functions.js" as Functions
|
||||
import "../js/debug.js" as Debug
|
||||
|
||||
ListItem {
|
||||
id: messageListItem
|
||||
contentHeight: messageBackground.height + Theme.paddingMedium
|
||||
contentHeight: messageBackground.height + Theme.paddingMedium + ( reactionsColumn.visible ? reactionsColumn.height : 0 )
|
||||
Behavior on contentHeight { NumberAnimation { duration: 200 } }
|
||||
property var chatId
|
||||
property var messageId
|
||||
property int messageIndex
|
||||
property int messageViewCount
|
||||
property var myMessage
|
||||
readonly property var userInformation: tdLibWrapper.getUserInformation(myMessage.sender_user_id)
|
||||
property var reactions
|
||||
property bool canReplyToMessage
|
||||
readonly property bool isAnonymous: myMessage.sender_id["@type"] === "messageSenderChat"
|
||||
readonly property var userInformation: tdLibWrapper.getUserInformation(myMessage.sender_id.user_id)
|
||||
property QtObject precalculatedValues: ListView.view.precalculatedValues
|
||||
readonly property color textColor: isOwnMessage ? Theme.highlightColor : Theme.primaryColor
|
||||
readonly property int textAlign: isOwnMessage ? Text.AlignRight : Text.AlignLeft
|
||||
readonly property int textAlign: Text.AlignLeft
|
||||
readonly property Page page: precalculatedValues.page
|
||||
readonly property bool isSelected: messageListItem.precalculatedValues.pageIsSelecting && page.selectedMessages.some(function(existingMessage) {
|
||||
return existingMessage.id === messageId
|
||||
});
|
||||
readonly property bool isOwnMessage: page.myUserId === myMessage.sender_user_id
|
||||
property string extraContentComponentName
|
||||
readonly property bool isOwnMessage: page.myUserId === myMessage.sender_id.user_id
|
||||
readonly property bool canDeleteMessage: myMessage.can_be_deleted_for_all_users || (myMessage.can_be_deleted_only_for_self && myMessage.chat_id === page.myUserId)
|
||||
property bool hasContentComponent
|
||||
property bool additionalOptionsOpened
|
||||
property bool wasNavigatedTo: false
|
||||
|
||||
highlighted: (down || isSelected) && !menuOpen
|
||||
readonly property var additionalItemsModel: (extraContentLoader.item && ("extraContextMenuItems" in extraContentLoader.item)) ?
|
||||
extraContentLoader.item.extraContextMenuItems : 0
|
||||
readonly property int numberOfExtraOptionsOtherThanDeleteMessage:
|
||||
(showCopyMessageToClipboardMenuItem ? 0 : 1) +
|
||||
(showForwardMessageMenuItem ? 0 : 1) +
|
||||
(page.canPinMessages() ? 1 : 0) +
|
||||
(additionalItemsModel ? additionalItemsModel.length : 0)
|
||||
readonly property bool deleteMessageIsOnlyExtraOption: canDeleteMessage && !numberOfExtraOptionsOtherThanDeleteMessage
|
||||
|
||||
readonly property int maxContextMenuItemCount: page.isPortrait ? 5 : 4
|
||||
readonly property int baseContextMenuItemCount: (canReplyToMessage ? 1 : 0) +
|
||||
(myMessage.can_be_edited ? 1 : 0) + 2 /* "Select Message" and "More Options..." */
|
||||
readonly property bool showCopyMessageToClipboardMenuItem: (baseContextMenuItemCount + 1) <= maxContextMenuItemCount
|
||||
readonly property bool showForwardMessageMenuItem: (baseContextMenuItemCount + 2) <= maxContextMenuItemCount
|
||||
// And don't count "More Options..." for "Delete Message" if "Delete Message" is the only extra option
|
||||
readonly property bool haveSpaceForDeleteMessageMenuItem: (baseContextMenuItemCount + 3 - (deleteMessageIsOnlyExtraOption ? 1 : 0)) <= maxContextMenuItemCount
|
||||
property var chatReactions
|
||||
property var messageReactions
|
||||
|
||||
highlighted: (down || isSelected || additionalOptionsOpened || wasNavigatedTo) && !menuOpen
|
||||
openMenuOnPressAndHold: !messageListItem.precalculatedValues.pageIsSelecting
|
||||
|
||||
signal replyToMessage()
|
||||
signal editMessage()
|
||||
signal forwardMessage()
|
||||
|
||||
function deleteMessage() {
|
||||
var chatId = page.chatInformation.id
|
||||
var messageId = myMessage.id
|
||||
Remorse.itemAction(messageListItem, qsTr("Message deleted"), function() {
|
||||
tdLibWrapper.deleteMessages(chatId, [ messageId ]);
|
||||
})
|
||||
}
|
||||
|
||||
function copyMessageToClipboard() {
|
||||
Clipboard.text = Functions.getMessageText(myMessage, true, userInformation.id, true)
|
||||
}
|
||||
|
||||
function openContextMenu() {
|
||||
messageOptionsDrawer.open = false
|
||||
if (menu) {
|
||||
openMenu()
|
||||
} else {
|
||||
contextMenuLoader.active = true
|
||||
}
|
||||
}
|
||||
|
||||
function getInteractionText(viewCount, reactions, size, highlightColor) {
|
||||
var interactionText = "";
|
||||
if (viewCount > 0) {
|
||||
interactionText = Emoji.emojify("👁️ ", size) + Functions.getShortenedCount(viewCount);
|
||||
}
|
||||
for (var i = 0; i < reactions.length; i++) {
|
||||
var reaction = reactions[i]
|
||||
var reactionText = reaction.reaction ? reaction.reaction : (reaction.type && reaction.type.emoji) ? reaction.type.emoji : ""
|
||||
if (reactionText) {
|
||||
interactionText += ( " " + Emoji.emojify(reactionText, size) );
|
||||
if (!chatPage.isPrivateChat) {
|
||||
var count = Functions.getShortenedCount(reaction.total_count)
|
||||
interactionText += " "
|
||||
interactionText += (reaction.is_chosen ? ( "<font color='" + highlightColor + "'><b>" + count + "</b></font>" ) : count)
|
||||
}
|
||||
}
|
||||
}
|
||||
return interactionText;
|
||||
}
|
||||
|
||||
function openReactions() {
|
||||
if (messageListItem.chatReactions) {
|
||||
Debug.log("Using chat reactions")
|
||||
messageListItem.messageReactions = chatReactions
|
||||
showItemCompletelyTimer.requestedIndex = index;
|
||||
showItemCompletelyTimer.start();
|
||||
} else {
|
||||
Debug.log("Obtaining message reactions")
|
||||
tdLibWrapper.getMessageAvailableReactions(messageListItem.chatId, messageListItem.messageId);
|
||||
}
|
||||
selectReactionBubble.visible = false;
|
||||
}
|
||||
|
||||
function getContentWidthMultiplier() {
|
||||
return Functions.isWidescreen(appWindow) ? 0.4 : 1.0
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (messageListItem.precalculatedValues.pageIsSelecting) {
|
||||
page.toggleMessageSelection(myMessage);
|
||||
} else {
|
||||
if (messageOptionsDrawer.sourceItem !== messageListItem) {
|
||||
messageOptionsDrawer.open = false
|
||||
}
|
||||
// Allow extra context to react to click
|
||||
var extraContent = extraContentLoader.item
|
||||
if (extraContent && ("clicked" in extraContent) && (typeof extraContent.clicked === "function") &&
|
||||
mouseX >= extraContentLoader.x && mouseY >= extraContentLoader.y &&
|
||||
mouseX < (extraContentLoader.x + extraContentLoader.width) &&
|
||||
mouseY < (extraContentLoader.y + extraContentLoader.height)) {
|
||||
if (extraContent && extraContentLoader.contains(mapToItem(extraContentLoader, mouse.x, mouse.y))) {
|
||||
extraContent.clicked()
|
||||
} else if (webPagePreviewLoader.item) {
|
||||
webPagePreviewLoader.item.clicked()
|
||||
}
|
||||
|
||||
if (messageListItem.messageReactions) {
|
||||
messageListItem.messageReactions = null;
|
||||
selectReactionBubble.visible = false;
|
||||
} else {
|
||||
selectReactionBubble.visible = !selectReactionBubble.visible;
|
||||
elementSelected(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPressAndHold: {
|
||||
if(messageListItem.precalculatedValues.pageIsSelecting) {
|
||||
page.selectedMessages = [];
|
||||
page.state = ""
|
||||
onDoubleClicked: {
|
||||
if (messageListItem.chatReactions) {
|
||||
Debug.log("Using chat reactions")
|
||||
messageListItem.messageReactions = chatReactions
|
||||
showItemCompletelyTimer.requestedIndex = index;
|
||||
showItemCompletelyTimer.start();
|
||||
} else {
|
||||
contextMenuLoader.active = true;
|
||||
Debug.log("Obtaining message reactions")
|
||||
tdLibWrapper.getMessageAvailableReactions(messageListItem.chatId, messageListItem.messageId);
|
||||
}
|
||||
}
|
||||
|
||||
onPressAndHold: {
|
||||
if (openMenuOnPressAndHold) {
|
||||
openContextMenu()
|
||||
} else {
|
||||
page.selectedMessages = []
|
||||
page.state = ""
|
||||
}
|
||||
}
|
||||
|
||||
onMenuOpenChanged: {
|
||||
// When opening/closing the context menu, we no longer scroll automatically
|
||||
chatView.manuallyScrolledToBottom = false;
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: additionalOptionsOpened ? messageOptionsDrawer : null
|
||||
onOpenChanged: {
|
||||
if (!messageOptionsDrawer.open) {
|
||||
additionalOptionsOpened = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: chatPage
|
||||
onResetElements: {
|
||||
messageListItem.messageReactions = null;
|
||||
selectReactionBubble.visible = false;
|
||||
}
|
||||
onElementSelected: {
|
||||
if (elementIndex !== index) {
|
||||
selectReactionBubble.visible = false;
|
||||
}
|
||||
}
|
||||
onNavigatedTo: {
|
||||
if (targetIndex === index) {
|
||||
messageListItem.wasNavigatedTo = true;
|
||||
restoreNormalityTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: contextMenuLoader
|
||||
active: false
|
||||
|
@ -77,59 +224,50 @@ ListItem {
|
|||
}
|
||||
sourceComponent: Component {
|
||||
ContextMenu {
|
||||
Repeater {
|
||||
model: (extraContentLoader.item && ("extraContextMenuItems" in extraContentLoader.item)) ?
|
||||
extraContentLoader.item.extraContextMenuItems : 0
|
||||
delegate: MenuItem {
|
||||
visible: modelData.visible
|
||||
text: modelData.name
|
||||
onClicked: modelData.action()
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
onClicked: {
|
||||
newMessageInReplyToRow.inReplyToMessage = myMessage;
|
||||
newMessageTextField.focus = true;
|
||||
}
|
||||
visible: canReplyToMessage
|
||||
onClicked: replyToMessage()
|
||||
text: qsTr("Reply to Message")
|
||||
}
|
||||
MenuItem {
|
||||
onClicked: {
|
||||
newMessageColumn.editMessageId = messageId;
|
||||
newMessageTextField.text = Functions.getMessageText(myMessage, false, false, true);
|
||||
newMessageTextField.focus = true;
|
||||
}
|
||||
visible: typeof myMessage.can_be_edited !== "undefined" && myMessage.can_be_edited
|
||||
onClicked: editMessage()
|
||||
text: qsTr("Edit Message")
|
||||
visible: myMessage.can_be_edited
|
||||
}
|
||||
MenuItem {
|
||||
onClicked: {
|
||||
Clipboard.text = Functions.getMessageText(myMessage, true, false, true);
|
||||
}
|
||||
text: qsTr("Copy Message to Clipboard")
|
||||
}
|
||||
MenuItem {
|
||||
onClicked: {
|
||||
page.toggleMessageSelection(myMessage);
|
||||
}
|
||||
onClicked: page.toggleMessageSelection(myMessage)
|
||||
text: qsTr("Select Message")
|
||||
}
|
||||
MenuItem {
|
||||
onClicked: {
|
||||
tdLibWrapper.pinMessage(page.chatInformation.id, messageId)
|
||||
}
|
||||
text: qsTr("Pin Message")
|
||||
visible: canPinMessages()
|
||||
visible: showCopyMessageToClipboardMenuItem
|
||||
onClicked: copyMessageToClipboard()
|
||||
text: qsTr("Copy Message to Clipboard")
|
||||
}
|
||||
MenuItem {
|
||||
onClicked: {
|
||||
var chatId = page.chatInformation.id;
|
||||
var messageId = messageListItem.messageId;
|
||||
Remorse.itemAction(messageListItem, qsTr("Message deleted"), function() { tdLibWrapper.deleteMessages(chatId, [ messageId]); })
|
||||
visible: showForwardMessageMenuItem
|
||||
onClicked: forwardMessage()
|
||||
text: qsTr("Forward Message")
|
||||
}
|
||||
MenuItem {
|
||||
visible: canDeleteMessage && haveSpaceForDeleteMessageMenuItem
|
||||
onClicked: deleteMessage()
|
||||
text: qsTr("Delete Message")
|
||||
visible: myMessage.can_be_deleted_for_all_users || (myMessage.can_be_deleted_only_for_self && myMessage.chat_id === page.myUserId)
|
||||
}
|
||||
MenuItem {
|
||||
visible: (numberOfExtraOptionsOtherThanDeleteMessage > 0) ||
|
||||
(deleteMessageIsOnlyExtraOption && !haveSpaceForDeleteMessageMenuItem)
|
||||
onClicked: {
|
||||
messageOptionsDrawer.myMessage = myMessage;
|
||||
messageOptionsDrawer.userInformation = userInformation;
|
||||
messageOptionsDrawer.sourceItem = messageListItem
|
||||
messageOptionsDrawer.additionalItemsModel = additionalItemsModel
|
||||
messageOptionsDrawer.showCopyMessageToClipboardMenuItem = !showCopyMessageToClipboardMenuItem
|
||||
messageOptionsDrawer.showForwardMessageMenuItem = !showForwardMessageMenuItem
|
||||
messageOptionsDrawer.showDeleteMessageMenuItem = canDeleteMessage && !haveSpaceForDeleteMessageMenuItem
|
||||
messageListItem.additionalOptionsOpened = true;
|
||||
messageOptionsDrawer.open = true;
|
||||
}
|
||||
text: qsTr("More Options...")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,44 +276,103 @@ ListItem {
|
|||
Connections {
|
||||
target: chatModel
|
||||
onMessagesReceived: {
|
||||
messageBackground.isUnread = index > chatModel.getLastReadMessageIndex();
|
||||
messageBackground.isUnread = index > chatModel.getLastReadMessageIndex() && myMessage['@type'] !== "sponsoredMessage";
|
||||
}
|
||||
onMessagesIncrementalUpdate: {
|
||||
messageBackground.isUnread = index > chatModel.getLastReadMessageIndex();
|
||||
messageBackground.isUnread = index > chatModel.getLastReadMessageIndex() && myMessage['@type'] !== "sponsoredMessage";
|
||||
}
|
||||
onNewMessageReceived: {
|
||||
messageBackground.isUnread = index > chatModel.getLastReadMessageIndex();
|
||||
messageBackground.isUnread = index > chatModel.getLastReadMessageIndex() && myMessage['@type'] !== "sponsoredMessage";
|
||||
}
|
||||
onUnreadCountUpdated: {
|
||||
messageBackground.isUnread = index > chatModel.getLastReadMessageIndex();
|
||||
messageBackground.isUnread = index > chatModel.getLastReadMessageIndex() && myMessage['@type'] !== "sponsoredMessage";
|
||||
}
|
||||
onLastReadSentMessageUpdated: {
|
||||
Debug.log("[ChatModel] Messages in this chat were read, new last read: ", lastReadSentIndex, ", updating description for index ", index, ", status: ", (index <= lastReadSentIndex));
|
||||
messageDateText.text = getMessageStatusText(myMessage, index, lastReadSentIndex, messageDateText.useElapsed);
|
||||
}
|
||||
onMessageUpdated: {
|
||||
if (index === modelIndex) {
|
||||
Debug.log("[ChatModel] This message was updated, index ", index, ", updating content...");
|
||||
messageDateText.text = getMessageStatusText(myMessage, index, chatView.lastReadSentIndex, messageDateText.useElapsed);
|
||||
messageText.text = Emoji.emojify(Functions.getMessageText(myMessage, false, messageListItem.isOwnMessage. false), messageText.font.pixelSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onReceivedMessage: {
|
||||
if (messageId === myMessage.reply_to_message_id.toString()) {
|
||||
if (messageId === myMessage.reply_to_message_id) {
|
||||
messageInReplyToLoader.inReplyToMessage = message;
|
||||
}
|
||||
}
|
||||
onMessageNotFound: {
|
||||
if (messageId === myMessage.reply_to_message_id) {
|
||||
messageInReplyToLoader.inReplyToMessageDeleted = true;
|
||||
}
|
||||
}
|
||||
onAvailableReactionsReceived: {
|
||||
if (messageListItem.messageId === messageId &&
|
||||
pageStack.currentPage === chatPage) {
|
||||
Debug.log("Available reactions for this message: " + reactions);
|
||||
messageListItem.messageReactions = reactions;
|
||||
showItemCompletelyTimer.requestedIndex = index;
|
||||
showItemCompletelyTimer.start();
|
||||
} else {
|
||||
messageListItem.messageReactions = null;
|
||||
}
|
||||
}
|
||||
onReactionsUpdated: {
|
||||
chatReactions = tdLibWrapper.getChatReactions(page.chatInformation.id);
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: showItemCompletelyTimer
|
||||
|
||||
property int requestedIndex: (chatView.count - 1)
|
||||
|
||||
repeat: false
|
||||
running: false
|
||||
interval: 200
|
||||
triggeredOnStart: false
|
||||
onTriggered: {
|
||||
Debug.log("Show item completely timer triggered, requested index: " + requestedIndex + ", current index: " + index)
|
||||
if (requestedIndex === index) {
|
||||
var p = chatView.contentItem.mapFromItem(reactionsColumn, 0, 0)
|
||||
if (chatView.contentY > p.y || p.y + reactionsColumn.height > chatView.contentY + chatView.height) {
|
||||
Debug.log("Moving reactions for item at", requestedIndex, "info the view")
|
||||
chatView.highlightMoveDuration = -1
|
||||
chatView.highlightResizeDuration = -1
|
||||
chatView.scrollToIndex(requestedIndex, height <= chatView.height ? ListView.Contain : ListView.End)
|
||||
chatView.highlightMoveDuration = 0
|
||||
chatView.highlightResizeDuration = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: restoreNormalityTimer
|
||||
|
||||
repeat: false
|
||||
running: false
|
||||
interval: 1000
|
||||
triggeredOnStart: false
|
||||
onTriggered: {
|
||||
Debug.log("Restore normality for index " + index);
|
||||
messageListItem.wasNavigatedTo = false;
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
delegateComponentLoadingTimer.start();
|
||||
if (myMessage.reply_to_message_id) {
|
||||
tdLibWrapper.getMessage(myMessage.reply_in_chat_id ? myMessage.reply_in_chat_id : page.chatInformation.id,
|
||||
myMessage.reply_to_message_id)
|
||||
}
|
||||
}
|
||||
|
||||
if (myMessage.reply_to_message_id !== 0) {
|
||||
tdLibWrapper.getMessage(page.chatInformation.id, myMessage.reply_to_message_id);
|
||||
onMyMessageChanged: {
|
||||
Debug.log("[ChatModel] This message was updated, index", messageIndex, ", updating content...");
|
||||
messageDateText.text = getMessageStatusText(myMessage, messageIndex, chatView.lastReadSentIndex, messageDateText.useElapsed);
|
||||
messageText.text = Emoji.emojify(Functions.getMessageText(myMessage, false, page.myUserId, false), Theme.fontSizeSmall);
|
||||
if (webPagePreviewLoader.item) {
|
||||
webPagePreviewLoader.item.webPageData = myMessage.content.web_page;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,10 +382,10 @@ ListItem {
|
|||
repeat: false
|
||||
running: false
|
||||
onTriggered: {
|
||||
if (typeof myMessage.content !== "undefined") {
|
||||
if (messageListItem.extraContentComponentName !== "") {
|
||||
if (messageListItem.hasContentComponent) {
|
||||
var type = myMessage.content["@type"];
|
||||
extraContentLoader.setSource(
|
||||
"../components/" +messageListItem.extraContentComponentName +".qml",
|
||||
"../components/messageContent/" + type.charAt(0).toUpperCase() + type.substring(1) + ".qml",
|
||||
{
|
||||
messageListItem: messageListItem
|
||||
})
|
||||
|
@ -199,13 +396,15 @@ ListItem {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: messageTextRow
|
||||
spacing: Theme.paddingSmall
|
||||
width: precalculatedValues.entryWidth
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenter: Functions.isWidescreen(appWindow) ? undefined : parent.horizontalCenter
|
||||
anchors.left: Functions.isWidescreen(appWindow) ? parent.left : undefined
|
||||
y: Theme.paddingSmall
|
||||
anchors.leftMargin: Functions.isWidescreen(appWindow) ? Theme.paddingMedium : undefined
|
||||
|
||||
Loader {
|
||||
id: profileThumbnailLoader
|
||||
|
@ -218,16 +417,16 @@ ListItem {
|
|||
sourceComponent: Component {
|
||||
ProfileThumbnail {
|
||||
id: messagePictureThumbnail
|
||||
photoData: (typeof messageListItem.userInformation.profile_photo !== "undefined") ? messageListItem.userInformation.profile_photo.small : ({})
|
||||
photoData: messageListItem.isAnonymous ? ((typeof page.chatInformation.photo !== "undefined") ? page.chatInformation.photo.small : {}) : ((typeof messageListItem.userInformation.profile_photo !== "undefined") ? messageListItem.userInformation.profile_photo.small : ({}))
|
||||
replacementStringHint: userText.text
|
||||
width: Theme.itemSizeSmall
|
||||
height: Theme.itemSizeSmall
|
||||
visible: precalculatedValues.showUserInfo
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: !messageListItem.precalculatedValues.pageIsSelecting
|
||||
enabled: !(messageListItem.precalculatedValues.pageIsSelecting || messageListItem.isAnonymous)
|
||||
onClicked: {
|
||||
tdLibWrapper.createPrivateChat(messageListItem.userInformation.id);
|
||||
tdLibWrapper.createPrivateChat(messageListItem.userInformation.id, "openDirectly");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -245,16 +444,16 @@ ListItem {
|
|||
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: messageListItem.isOwnMessage ? precalculatedValues.pageMarginDouble : 0
|
||||
leftMargin: page.isPrivateChat ? (messageListItem.isOwnMessage ? precalculatedValues.pageMarginDouble : 0) : 0 //левый марджин для собственных сообщений в приватных чатах. В остальных на полную ширину
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
height: messageTextColumn.height + precalculatedValues.paddingMediumDouble
|
||||
width: precalculatedValues.backgroundWidth
|
||||
property bool isUnread: index > chatModel.getLastReadMessageIndex()
|
||||
color: isUnread ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||
property bool isUnread: index > chatModel.getLastReadMessageIndex() && myMessage['@type'] !== "sponsoredMessage"
|
||||
color: Theme.colorScheme === Theme.LightOnDark ? (isOwnMessage ? Theme.highlightBackgroundColor : (isUnread ? Theme.secondaryHighlightColor : Theme.secondaryColor)) : (isOwnMessage ? Theme.highlightBackgroundColor : (isUnread ? Theme.backgroundGlowColor : Theme.overlayBackgroundColor))
|
||||
radius: parent.width / 50
|
||||
opacity: isUnread ? 0.5 : 0.2
|
||||
visible: appSettings.showStickersAsImages || myMessage.content['@type'] !== "messageSticker"
|
||||
visible: appSettings.showStickersAsImages || (myMessage.content['@type'] !== "messageSticker" && myMessage.content['@type'] !== "messageAnimatedEmoji")
|
||||
Behavior on color { ColorAnimation { duration: 200 } }
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
}
|
||||
|
@ -272,7 +471,7 @@ ListItem {
|
|||
id: userText
|
||||
|
||||
width: parent.width
|
||||
text: messageListItem.isOwnMessage ? qsTr("You") : Emoji.emojify(Functions.getUserName(messageListItem.userInformation), font.pixelSize)
|
||||
text: messageListItem.isOwnMessage ? qsTr("You") : Emoji.emojify( myMessage['@type'] === "sponsoredMessage" ? tdLibWrapper.getChat(myMessage.sponsor_chat_id).title : ( messageListItem.isAnonymous ? page.chatInformation.title : Functions.getUserName(messageListItem.userInformation) ), font.pixelSize)
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
font.weight: Font.ExtraBold
|
||||
color: messageListItem.textColor
|
||||
|
@ -280,23 +479,28 @@ ListItem {
|
|||
truncationMode: TruncationMode.Fade
|
||||
textFormat: Text.StyledText
|
||||
horizontalAlignment: messageListItem.textAlign
|
||||
visible: precalculatedValues.showUserInfo
|
||||
visible: messageListItem.isOwnMessage ? false : (precalculatedValues.showUserInfo || myMessage['@type'] === "sponsoredMessage")
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: !messageListItem.precalculatedValues.pageIsSelecting
|
||||
enabled: !(messageListItem.precalculatedValues.pageIsSelecting || messageListItem.isAnonymous)
|
||||
onClicked: {
|
||||
tdLibWrapper.createPrivateChat(messageListItem.userInformation.id);
|
||||
tdLibWrapper.createPrivateChat(messageListItem.userInformation.id, "openDirectly");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageViaLabel {
|
||||
message: myMessage
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: messageInReplyToLoader
|
||||
active: myMessage.reply_to_message_id !== 0
|
||||
active: typeof myMessage.reply_to_message_id !== "undefined" && myMessage.reply_to_message_id !== 0
|
||||
width: parent.width
|
||||
// text height ~= 1,28*font.pixelSize
|
||||
height: active ? precalculatedValues.messageInReplyToHeight : 0
|
||||
property var inReplyToMessage;
|
||||
property bool inReplyToMessageDeleted: false;
|
||||
sourceComponent: Component {
|
||||
Item {
|
||||
width: messageInReplyToRow.width
|
||||
|
@ -304,14 +508,31 @@ ListItem {
|
|||
InReplyToRow {
|
||||
id: messageInReplyToRow
|
||||
myUserId: page.myUserId
|
||||
visible: true
|
||||
layer.enabled: messageInReplyToMouseArea.pressed && !messageListItem.highlighted && !messageListItem.menuOpen
|
||||
layer.effect: PressEffect { source: messageInReplyToRow }
|
||||
inReplyToMessage: messageInReplyToLoader.inReplyToMessage
|
||||
inReplyToMessageDeleted: messageInReplyToLoader.inReplyToMessageDeleted
|
||||
}
|
||||
MouseArea {
|
||||
id: messageInReplyToMouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
messageOverlayLoader.overlayMessage = messageInReplyToRow.inReplyToMessage;
|
||||
messageOverlayLoader.active = true;
|
||||
if (precalculatedValues.pageIsSelecting) {
|
||||
page.toggleMessageSelection(myMessage)
|
||||
} else {
|
||||
messageOptionsDrawer.open = false
|
||||
if(appSettings.goToQuotedMessage) {
|
||||
chatPage.showMessage(messageInReplyToRow.inReplyToMessage.id, true)
|
||||
} else {
|
||||
messageOverlayLoader.active = true
|
||||
messageOverlayLoader.overlayMessage = messageInReplyToRow.inReplyToMessage
|
||||
}
|
||||
}
|
||||
}
|
||||
onPressAndHold: {
|
||||
if (openMenuOnPressAndHold) {
|
||||
openContextMenu()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -331,11 +552,12 @@ ListItem {
|
|||
width: parent.width
|
||||
|
||||
Component.onCompleted: {
|
||||
if (myMessage.forward_info.origin["@type"] === "messageForwardOriginChannel") {
|
||||
var originType = myMessage.forward_info.origin["@type"]
|
||||
if (originType === "messageOriginChannel" || originType === "messageForwardOriginChannel") {
|
||||
var otherChatInformation = tdLibWrapper.getChat(myMessage.forward_info.origin.chat_id);
|
||||
forwardedThumbnail.photoData = (typeof otherChatInformation.photo !== "undefined") ? otherChatInformation.photo.small : {};
|
||||
forwardedChannelText.text = Emoji.emojify(otherChatInformation.title, Theme.fontSizeExtraSmall);
|
||||
} else if (myMessage.forward_info.origin["@type"] === "messageForwardOriginUser") {
|
||||
} else if (originType === "messageOriginUser" || originType === "messageForwardOriginUser") {
|
||||
var otherUserInformation = tdLibWrapper.getUserInformation(myMessage.forward_info.origin.sender_user_id);
|
||||
forwardedThumbnail.photoData = (typeof otherUserInformation.profile_photo !== "undefined") ? otherUserInformation.profile_photo.small : {};
|
||||
forwardedChannelText.text = Emoji.emojify(Functions.getUserName(otherUserInformation), Theme.fontSizeExtraSmall);
|
||||
|
@ -381,35 +603,46 @@ ListItem {
|
|||
Text {
|
||||
id: messageText
|
||||
width: parent.width
|
||||
text: Emoji.emojify(Functions.getMessageText(myMessage, false, messageListItem.isOwnMessage, false), font.pixelSize)
|
||||
text: Emoji.emojify(Functions.getMessageText(myMessage, false, page.myUserId, false), Theme.fontSizeMedium)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: messageListItem.textColor
|
||||
wrapMode: Text.Wrap
|
||||
textFormat: Text.StyledText
|
||||
onLinkActivated: {
|
||||
Functions.handleLink(link);
|
||||
var chatCommand = Functions.handleLink(link);
|
||||
if(chatCommand) {
|
||||
tdLibWrapper.sendTextMessage(chatInformation.id, chatCommand);
|
||||
}
|
||||
}
|
||||
horizontalAlignment: messageListItem.textAlign
|
||||
linkColor: Theme.highlightColor
|
||||
visible: (text !== "")
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: sponsoredMessageButtonLoader
|
||||
active: myMessage['@type'] === "sponsoredMessage"
|
||||
asynchronous: true
|
||||
width: parent.width
|
||||
height: (status === Loader.Ready) ? item.implicitHeight : myMessage['@type'] === "sponsoredMessage" ? Theme.itemSizeMedium : 0
|
||||
|
||||
sourceComponent: Component {
|
||||
SponsoredMessage {
|
||||
sponsoredMessageData: myMessage
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: webPagePreviewLoader
|
||||
active: false
|
||||
asynchronous: true
|
||||
width: parent.width
|
||||
height: typeof myMessage.content.web_page !== "undefined" ? precalculatedValues.webPagePreviewHeight : 0
|
||||
width: parent.width * getContentWidthMultiplier()
|
||||
height: (status === Loader.Ready) ? item.implicitHeight : myMessage.content.web_page ? precalculatedValues.webPagePreviewHeight : 0
|
||||
|
||||
sourceComponent: Component {
|
||||
id: webPagePreviewComponent
|
||||
WebPagePreview {
|
||||
id: webPagePreview
|
||||
|
||||
onImplicitHeightChanged: {
|
||||
webPagePreviewLoader.height = webPagePreview.implicitHeight;
|
||||
}
|
||||
|
||||
webPageData: myMessage.content.web_page
|
||||
width: parent.width
|
||||
highlighted: messageListItem.highlighted
|
||||
|
@ -419,9 +652,9 @@ ListItem {
|
|||
|
||||
Loader {
|
||||
id: extraContentLoader
|
||||
width: parent.width
|
||||
width: parent.width * getContentWidthMultiplier()
|
||||
asynchronous: true
|
||||
height: item ? item.height : (messageListItem.extraContentComponentName !== "" ? chatView.getContentComponentHeight(messageListItem.extraContentComponentName, myMessage.content, width) : 0)
|
||||
height: item ? item.height : (messageListItem.hasContentComponent ? chatView.getContentComponentHeight(model.content_type, myMessage.content, width) : 0)
|
||||
}
|
||||
|
||||
Binding {
|
||||
|
@ -431,6 +664,15 @@ ListItem {
|
|||
value: messageListItem.highlighted
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: replyMarkupLoader
|
||||
width: parent.width
|
||||
height: active ? (myMessage.reply_markup.rows.length * (Theme.itemSizeSmall + Theme.paddingSmall) - Theme.paddingSmall) : 0
|
||||
asynchronous: true
|
||||
active: !!myMessage.reply_markup && myMessage.reply_markup.rows
|
||||
source: Qt.resolvedUrl("ReplyMarkupButtons.qml")
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: messageDateUpdater
|
||||
interval: 60000
|
||||
|
@ -441,7 +683,6 @@ ListItem {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
Text {
|
||||
width: parent.width
|
||||
|
||||
|
@ -462,6 +703,24 @@ ListItem {
|
|||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: interactionLoader
|
||||
width: parent.width
|
||||
asynchronous: true
|
||||
active: ( chatPage.isChannel && messageViewCount > 0 ) || reactions.length > 0
|
||||
height: ( ( chatPage.isChannel && messageViewCount > 0 ) || reactions.length > 0 ) ? ( Theme.fontSizeExtraSmall + Theme.paddingSmall ) : 0
|
||||
sourceComponent: Component {
|
||||
Label {
|
||||
text: getInteractionText(messageViewCount, reactions, font.pixelSize, Theme.highlightColor)
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: messageListItem.isOwnMessage ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||
horizontalAlignment: messageListItem.textAlign
|
||||
textFormat: Text.StyledText
|
||||
maximumLineCount: 1
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -469,3 +728,60 @@ ListItem {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
Column {
|
||||
id: reactionsColumn
|
||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||
anchors.top: messageTextRow.bottom
|
||||
anchors.topMargin: Theme.paddingSmall
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: messageListItem.messageReactions ? ( messageListItem.messageReactions.length > 0 ? true : false ) : false
|
||||
opacity: messageListItem.messageReactions ? ( messageListItem.messageReactions.length > 0 ? 1 : 0 ) : 0
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
spacing: Theme.paddingMedium
|
||||
|
||||
Flickable {
|
||||
width: parent.width
|
||||
height: reactionsResultRow.height + Theme.paddingSmall
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
contentWidth: reactionsResultRow.width
|
||||
clip: true
|
||||
Row {
|
||||
id: reactionsResultRow
|
||||
spacing: Theme.paddingMedium
|
||||
Repeater {
|
||||
model: messageListItem.messageReactions
|
||||
|
||||
Item {
|
||||
height: singleReactionRow.height
|
||||
width: singleReactionRow.width
|
||||
|
||||
Row {
|
||||
id: singleReactionRow
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
Image {
|
||||
id: emojiPicture
|
||||
source: Emoji.getEmojiPath(modelData)
|
||||
width: status === Image.Ready ? Theme.fontSizeLarge : 0
|
||||
height: Theme.fontSizeLarge
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
tdLibWrapper.setMessageReaction(messageListItem.chatId, messageListItem.messageId, modelData);
|
||||
messageListItem.messageReactions = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -20,12 +20,15 @@ import QtQuick 2.6
|
|||
import Sailfish.Silica 1.0
|
||||
import "../js/twemoji.js" as Emoji
|
||||
import "../js/functions.js" as Functions
|
||||
import "../js/debug.js" as Debug
|
||||
|
||||
Item {
|
||||
id: messageListItem
|
||||
property var myMessage: display
|
||||
property var userInformation: tdLibWrapper.getUserInformation(myMessage.sender_user_id)
|
||||
property bool isOwnMessage: chatPage.myUserId === myMessage.sender_user_id
|
||||
property bool senderIsUser: myMessage.sender_id["@type"] === "messageSenderUser"
|
||||
property var userInformation: senderIsUser ? tdLibWrapper.getUserInformation(myMessage.sender_id.user_id) : null
|
||||
property bool isOwnMessage: senderIsUser && chatPage.myUserId === myMessage.sender_id.user_id
|
||||
property var linkedMessage
|
||||
height: backgroundRectangle.height + Theme.paddingMedium
|
||||
|
||||
Rectangle {
|
||||
|
@ -33,7 +36,7 @@ Item {
|
|||
anchors.centerIn: parent
|
||||
height: messageText.height + Theme.paddingMedium * 2
|
||||
width: Math.min(messageText.implicitWidth, messageText.contentWidth) + Theme.paddingMedium * 2
|
||||
color: Theme.rgba(Theme.secondaryColor, 0.1)
|
||||
color: Theme.colorScheme === Theme.LightOnDark ? Theme.rgba(Theme.secondaryColor, 0.1) : Theme.rgba(Theme.overlayBackgroundColor, 0.1)
|
||||
radius: parent.width / 50
|
||||
}
|
||||
Text {
|
||||
|
@ -43,11 +46,43 @@ Item {
|
|||
color: Theme.highlightColor
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
text: "<a style=\"text-decoration: none; font-weight: bold; color:"+Theme.primaryColor+"\" href=\"userId://" + messageListItem.userInformation.id + "\">" + (!messageListItem.isOwnMessage ? Emoji.emojify(Functions.getUserName(messageListItem.userInformation), font.pixelSize) : qsTr("You")) + "</a> " + Emoji.emojify(Functions.getMessageText(messageListItem.myMessage, false, messageListItem.isOwnMessage, false), font.pixelSize)
|
||||
property string messageContentText: Functions.getMessageText(messageListItem.myMessage, false, chatPage.myUserId, false)
|
||||
text: (messageListItem.senderIsUser
|
||||
? "<a style=\"text-decoration: none; font-weight: bold; color:"+Theme.primaryColor+"\" href=\"userId://" + messageListItem.userInformation.id + "\">" + (!messageListItem.isOwnMessage ? Emoji.emojify(Functions.getUserName(messageListItem.userInformation), font.pixelSize) : qsTr("You")) + "</a> "
|
||||
: "<a style=\"text-decoration: none; font-weight: bold; color:"+Theme.secondaryHighlightColor+"\">" + Emoji.emojify(chatPage.chatInformation.title || "") + "</a> ")
|
||||
+ Emoji.emojify(messageContentText, font.pixelSize)
|
||||
textFormat: Text.RichText
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
onLinkActivated: {
|
||||
if(link === "linkedmessage" && linkedMessage) {
|
||||
messageOverlayLoader.overlayMessage = linkedMessage;
|
||||
messageOverlayLoader.active = true;
|
||||
} else {
|
||||
Functions.handleLink(link);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
id: gameScoreInfoLoader
|
||||
active: myMessage.content["@type"] === "messageGameScore"
|
||||
asynchronous: true
|
||||
sourceComponent: Component {
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onReceivedMessage: {
|
||||
if(chatId === chatPage.chatInformation.id && messageId === myMessage.content.game_message_id) {
|
||||
messageListItem.linkedMessage = message;
|
||||
messageText.messageContentText = messageListItem.isOwnMessage ?
|
||||
qsTr("scored %Ln points in %2", "myself", myMessage.content.score).arg("<a href=\"linkedmessage\" style=\"text-decoration: none; color:"+Theme.primaryColor+"\">"+message.content.game.title+"</a>") :
|
||||
|
||||
qsTr("scored %Ln points in %2", "", myMessage.content.score).arg("<a href=\"linkedmessage\" style=\"text-decoration: none; color:"+Theme.primaryColor+"\" >"+message.content.game.title+"</a>");
|
||||
}
|
||||
}
|
||||
Component.onCompleted: {
|
||||
tdLibWrapper.getMessage(chatPage.chatInformation.id, myMessage.content.game_message_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "../components"
|
||||
import "./messageContent"
|
||||
import "../js/functions.js" as Functions
|
||||
import "../js/twemoji.js" as Emoji
|
||||
import "../js/debug.js" as Debug
|
||||
|
||||
Flickable {
|
||||
id: messageOverlayFlickable
|
||||
|
@ -31,19 +32,21 @@ Flickable {
|
|||
|
||||
property var overlayMessage;
|
||||
property bool showHeader: true
|
||||
readonly property var userInformation: tdLibWrapper.getUserInformation(overlayMessage.sender_user_id);
|
||||
readonly property bool isOwnMessage: tdLibWrapper.getUserInformation().id === overlayMessage.sender_user_id;
|
||||
readonly property string extraContentComponentName: (typeof overlayMessage.content !== "undefined" && typeof chatView.contentComponentNames[overlayMessage.content['@type']] !== "undefined" )
|
||||
? chatView.contentComponentNames[overlayMessage.content['@type']] : ""
|
||||
readonly property var userInformation: tdLibWrapper.getUserInformation(overlayMessage.sender_id.user_id);
|
||||
readonly property bool isOwnMessage: tdLibWrapper.getUserInformation().id === overlayMessage.sender_id.user_id;
|
||||
readonly property bool isAnonymous: overlayMessage.sender_id["@type"] === "messageSenderChat"
|
||||
property bool hasContentComponent: overlayMessage.content && chatView.delegateMessagesContent.indexOf(overlayMessage.content['@type']) > -1
|
||||
signal requestClose;
|
||||
|
||||
function getOriginalAuthor(forwardInformation, fontSize) {
|
||||
switch (forwardInformation.origin["@type"]) {
|
||||
case "messageOriginChannel":
|
||||
case "messageForwardOriginChannel":
|
||||
var otherChatInformation = tdLibWrapper.getChat(forwardInformation.origin.chat_id);
|
||||
return Emoji.emojify(otherChatInformation.title, fontSize);
|
||||
case "messageOriginUser":
|
||||
case "messageForwardOriginUser":
|
||||
var otherUserInformation = tdLibWrapper.getUserInformation(forwardInformation.origin.sender_user_id);
|
||||
var otherUserInformation = tdLibWrapper.getUserInformation(forwardInformation.origin.sender_id.user_id);
|
||||
return Emoji.emojify(Functions.getUserName(otherUserInformation), fontSize);
|
||||
default:
|
||||
return Emoji.emojify(forwardInformation.origin.sender_name, fontSize);
|
||||
|
@ -60,21 +63,18 @@ Flickable {
|
|||
repeat: false
|
||||
running: false
|
||||
onTriggered: {
|
||||
if (typeof overlayMessage.content !== "undefined") {
|
||||
if (messageOverlayFlickable.extraContentComponentName !== "") {
|
||||
if (messageOverlayFlickable.hasContentComponent) {
|
||||
var type = overlayMessage.content["@type"];
|
||||
overlayExtraContentLoader.setSource(
|
||||
"../components/" + messageOverlayFlickable.extraContentComponentName + ".qml",
|
||||
"../components/messageContent/" + type.charAt(0).toUpperCase() + type.substring(1) + ".qml",
|
||||
{
|
||||
overlayFlickable: messageOverlayFlickable
|
||||
})
|
||||
} else {
|
||||
if (typeof overlayMessage.content.web_page !== "undefined") {
|
||||
} else if(overlayMessage.content && overlayMessage.content.web_page) {
|
||||
overlayWebPagePreviewLoader.active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: messageContentBackground
|
||||
|
@ -104,7 +104,7 @@ Flickable {
|
|||
spacing: Theme.paddingMedium
|
||||
ProfileThumbnail {
|
||||
id: overlayMessagePictureThumbnail
|
||||
photoData: (typeof messageOverlayFlickable.userInformation.profile_photo !== "undefined") ? messageOverlayFlickable.userInformation.profile_photo.small : ({})
|
||||
photoData: messageOverlayFlickable.isAnonymous ? ((typeof chatPage.chatInformation.photo !== "undefined") ? chatPage.chatInformation.photo.small : {}) : ((typeof messageOverlayFlickable.userInformation.profile_photo !== "undefined") ? messageOverlayFlickable.userInformation.profile_photo.small : ({}))
|
||||
replacementStringHint: overlayMessageUserText.text
|
||||
width: Theme.itemSizeLarge
|
||||
height: Theme.itemSizeLarge
|
||||
|
@ -114,7 +114,7 @@ Flickable {
|
|||
|
||||
width: parent.width - overlayMessagePictureThumbnail.width
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: messageOverlayFlickable.isOwnMessage ? qsTr("You") : Emoji.emojify(Functions.getUserName(messageOverlayFlickable.userInformation), font.pixelSize)
|
||||
text: messageOverlayFlickable.isOwnMessage ? qsTr("You") : Emoji.emojify(messageOverlayFlickable.isAnonymous ? chatPage.chatInformation.title : Functions.getUserName(messageOverlayFlickable.userInformation), font.pixelSize)
|
||||
font.pixelSize: Theme.fontSizeExtraLarge
|
||||
font.weight: Font.ExtraBold
|
||||
maximumLineCount: 1
|
||||
|
@ -123,6 +123,10 @@ Flickable {
|
|||
}
|
||||
}
|
||||
|
||||
MessageViaLabel {
|
||||
message: overlayMessage
|
||||
}
|
||||
|
||||
Text {
|
||||
id: overlayForwardedInfoText
|
||||
width: parent.width
|
||||
|
@ -138,7 +142,7 @@ Flickable {
|
|||
Text {
|
||||
id: overlayMessageText
|
||||
width: parent.width
|
||||
text: Emoji.emojify(Functions.getMessageText(overlayMessage, false, messageOverlayFlickable.isOwnMessage, false), font.pixelSize)
|
||||
text: Emoji.emojify(Functions.getMessageText(overlayMessage, false, tdLibWrapper.getUserInformation().id, false), font.pixelSize)
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
color: Theme.primaryColor
|
||||
wrapMode: Text.Wrap
|
||||
|
@ -178,6 +182,16 @@ Flickable {
|
|||
asynchronous: true
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: replyMarkupLoader
|
||||
property var myMessage: overlayMessage
|
||||
width: parent.width
|
||||
height: active ? (overlayMessage.reply_markup.rows.length * (Theme.itemSizeSmall + Theme.paddingSmall) - Theme.paddingSmall) : 0
|
||||
asynchronous: true
|
||||
active: !!overlayMessage.reply_markup && myMessage.reply_markup.rows
|
||||
source: Qt.resolvedUrl("ReplyMarkupButtons.qml")
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: messageDateUpdater
|
||||
interval: 60000
|
||||
|
|
49
qml/components/MessageViaLabel.qml
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "../js/functions.js" as Functions
|
||||
import "../js/twemoji.js" as Emoji
|
||||
|
||||
|
||||
Loader {
|
||||
id: botUserLoader
|
||||
active: !!message.via_bot_user_id
|
||||
width: parent.width
|
||||
asynchronous: true
|
||||
sourceComponent: Label {
|
||||
property var botUserInformation: tdLibWrapper.getUserInformation(message.via_bot_user_id)
|
||||
color: Theme.secondaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
text: qsTr("via %1", "message posted via bot user").arg("<a style=\"text-decoration: none; font-weight: bold; color:"+Theme.primaryColor+"\" href=\"userId://" + message.via_bot_user_id + "\">@" + Emoji.emojify(botUserInformation.usernames.editable_username, font.pixelSize)+"</a>")
|
||||
textFormat: Text.RichText
|
||||
truncationMode: TruncationMode.Fade
|
||||
onLinkActivated: {
|
||||
if(link === "userId://" + message.via_bot_user_id && botUserInformation.type.is_inline) {
|
||||
newMessageTextField.text = "@"+botUserInformation.usernames.editable_username+" "
|
||||
newMessageTextField.cursorPosition = newMessageTextField.text.length
|
||||
lostFocusTimer.start();
|
||||
}
|
||||
else {
|
||||
Functions.handleLink(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
property var message
|
||||
}
|
78
qml/components/MultilineEmojiLabel.qml
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
Copyright (C) 2020 Slava Monich and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.0
|
||||
import Sailfish.Silica 1.0
|
||||
import "../js/twemoji.js" as Emoji
|
||||
|
||||
// Combination of maximumLineCount and TruncationMode.Elide (or Fade) breaks
|
||||
// Emoji image alignment, pushing the image down. This one aligns the image
|
||||
// correctly on its line.
|
||||
Label {
|
||||
property string rawText
|
||||
property int maxLineCount
|
||||
|
||||
wrapMode: Text.Wrap
|
||||
textFormat: Text.StyledText
|
||||
truncationMode: TruncationMode.Elide
|
||||
|
||||
// lineCount is unreliable for StyledText with images and line breaks
|
||||
readonly property int fontSize: font.pixelSize
|
||||
readonly property int actualLineHeight: (text === rawText) ? fontSize : (fontSize * 6 / 5)
|
||||
readonly property int actualLineCount: Math.floor(implicitHeight/actualLineHeight)
|
||||
|
||||
Component.onCompleted: refitText()
|
||||
onFontSizeChanged: refitText()
|
||||
onWidthChanged: refitText()
|
||||
onRawTextChanged: refitText()
|
||||
onMaxLineCountChanged: refitText()
|
||||
|
||||
function emojify(str) {
|
||||
return Emoji.emojify(str, fontSize)
|
||||
}
|
||||
|
||||
function refitText() {
|
||||
text = emojify(rawText)
|
||||
if (maxLineCount > 0) {
|
||||
var divisor = 1
|
||||
var max = rawText.length
|
||||
var min = max
|
||||
while (actualLineCount > maxLineCount && divisor < rawText.length) {
|
||||
max = min
|
||||
divisor++
|
||||
min = rawText.length/divisor
|
||||
text = emojify(rawText.substr(0, min) + "…")
|
||||
}
|
||||
while (min < max) {
|
||||
var mid = Math.floor((min + max)/2)
|
||||
if (mid === min) {
|
||||
text = emojify(rawText.substr(0, min) + "…")
|
||||
break
|
||||
} else {
|
||||
text = emojify(rawText.substr(0, mid) + "…")
|
||||
if (actualLineCount > maxLineCount) {
|
||||
max = mid
|
||||
} else {
|
||||
min = mid
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../js/functions.js" as Functions
|
||||
|
||||
ListItem {
|
||||
id: chatListViewItem
|
||||
|
@ -11,36 +12,32 @@ ListItem {
|
|||
property alias tertiaryText: tertiaryText //usually last message date
|
||||
|
||||
property int unreadCount: 0
|
||||
property int unreadMentionCount: 0
|
||||
property int unreadReactionCount: 0
|
||||
property bool isSecret: false
|
||||
property bool isVerified: false
|
||||
property bool isMarkedAsUnread: false
|
||||
property bool isPinned: false
|
||||
property bool isMuted: false
|
||||
property alias pictureThumbnail: pictureThumbnail
|
||||
|
||||
contentHeight: mainRow.height + separator.height + 2 * Theme.paddingMedium
|
||||
contentHeight: Theme.itemSizeExtraLarge
|
||||
contentWidth: parent.width
|
||||
|
||||
Column {
|
||||
id: mainColumn
|
||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
ShaderEffectSource {
|
||||
id: pictureItem
|
||||
height: Theme.itemSizeLarge
|
||||
width: height
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
left: parent.left
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Row {
|
||||
id: mainRow
|
||||
height: contentColumn.height
|
||||
spacing: Theme.paddingMedium
|
||||
|
||||
Column {
|
||||
id: pictureColumn
|
||||
width: contentColumn.height - Theme.paddingSmall
|
||||
height: contentColumn.height - Theme.paddingSmall
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
Item {
|
||||
width: parent.width
|
||||
height: parent.width
|
||||
sourceItem: Item {
|
||||
width: pictureItem.width
|
||||
height: pictureItem.width
|
||||
|
||||
ProfileThumbnail {
|
||||
id: pictureThumbnail
|
||||
|
@ -49,33 +46,54 @@ ListItem {
|
|||
height: parent.width
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: chatPinnedBackground
|
||||
color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityFaint)
|
||||
width: Theme.fontSizeLarge
|
||||
height: Theme.fontSizeLarge
|
||||
anchors.top: parent.top
|
||||
radius: parent.width / 2
|
||||
visible: chatListViewItem.isPinned
|
||||
}
|
||||
|
||||
Icon {
|
||||
source: "../../images/icon-s-pin.svg"
|
||||
height: Theme.iconSizeExtraSmall
|
||||
width: Theme.iconSizeExtraSmall
|
||||
highlighted: chatListViewItem.highlighted
|
||||
sourceSize: Qt.size(Theme.iconSizeExtraSmall, Theme.iconSizeExtraSmall)
|
||||
anchors.centerIn: chatPinnedBackground
|
||||
visible: chatListViewItem.isPinned
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: chatSecretBackground
|
||||
color: Theme.overlayBackgroundColor
|
||||
width: Theme.fontSizeExtraLarge
|
||||
height: Theme.fontSizeExtraLarge
|
||||
color: Theme.rgba(Theme.overlayBackgroundColor, Theme.opacityFaint)
|
||||
width: Theme.fontSizeLarge
|
||||
height: Theme.fontSizeLarge
|
||||
anchors.bottom: parent.bottom
|
||||
radius: parent.width / 2
|
||||
visible: chatListViewItem.isSecret
|
||||
}
|
||||
|
||||
Image {
|
||||
Icon {
|
||||
source: "image://theme/icon-s-secure"
|
||||
height: Theme.fontSizeMedium
|
||||
width: Theme.fontSizeMedium
|
||||
height: Theme.iconSizeExtraSmall
|
||||
width: Theme.iconSizeExtraSmall
|
||||
highlighted: chatListViewItem.highlighted
|
||||
anchors.centerIn: chatSecretBackground
|
||||
visible: chatListViewItem.isSecret
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: chatUnreadMessagesCountBackground
|
||||
color: Theme.highlightBackgroundColor
|
||||
width: Theme.fontSizeLarge
|
||||
color: isMuted ? ((Theme.colorScheme === Theme.DarkOnLight) ? "lightgray" : "dimgray") : Theme.highlightBackgroundColor
|
||||
width: chatUnreadMessagesCount.width + Theme.fontSizeLarge / 2
|
||||
height: Theme.fontSizeLarge
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
radius: parent.width / 2
|
||||
visible: chatListViewItem.unreadCount > 0
|
||||
visible: chatListViewItem.unreadCount > 0 || chatListViewItem.isMarkedAsUnread
|
||||
}
|
||||
|
||||
Text {
|
||||
|
@ -84,16 +102,54 @@ ListItem {
|
|||
font.bold: true
|
||||
color: Theme.primaryColor
|
||||
anchors.centerIn: chatUnreadMessagesCountBackground
|
||||
visible: chatUnreadMessagesCountBackground.visible
|
||||
text: chatListViewItem.unreadCount > 99 ? "99+" : chatListViewItem.unreadCount
|
||||
visible: chatListViewItem.unreadCount > 0
|
||||
opacity: isMuted ? Theme.opacityHigh : 1.0
|
||||
text: Functions.formatUnreadCount(chatListViewItem.unreadCount)
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
color: isMuted ? ((Theme.colorScheme === Theme.DarkOnLight) ? "lightgray" : "dimgray") : Theme.highlightBackgroundColor
|
||||
width: Theme.fontSizeLarge
|
||||
height: Theme.fontSizeLarge
|
||||
anchors.right: parent.right
|
||||
anchors.top: parent.top
|
||||
radius: parent.width / 2
|
||||
visible: chatListViewItem.unreadReactionCount > 0 || chatListViewItem.unreadMentionCount > 0
|
||||
|
||||
Icon {
|
||||
source: "image://theme/icon-s-favorite"
|
||||
height: Theme.iconSizeExtraSmall
|
||||
width: Theme.iconSizeExtraSmall
|
||||
highlighted: chatListViewItem.highlighted
|
||||
anchors.centerIn: parent
|
||||
visible: chatListViewItem.unreadReactionCount > 0 && !chatListViewItem.unreadMentionCount
|
||||
}
|
||||
|
||||
Text {
|
||||
font {
|
||||
pixelSize: Theme.iconSizeExtraSmall
|
||||
bold: true
|
||||
}
|
||||
color: Theme.primaryColor
|
||||
anchors.centerIn: parent
|
||||
visible: chatListViewItem.unreadMentionCount > 0
|
||||
opacity: isMuted ? Theme.opacityHigh : 1.0
|
||||
text: "@"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: contentColumn
|
||||
width: mainColumn.width - pictureColumn.width - mainRow.spacing
|
||||
spacing: Theme.paddingSmall
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
left: pictureItem.right
|
||||
leftMargin: Theme.paddingSmall
|
||||
right: parent.right
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
spacing: Theme.paddingSmall / 2
|
||||
|
||||
Row {
|
||||
id: primaryTextRow
|
||||
|
@ -105,15 +161,29 @@ ListItem {
|
|||
font.pixelSize: Theme.fontSizeMedium
|
||||
truncationMode: TruncationMode.Fade
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: Math.min(contentColumn.width - (verifiedImage.visible ? (verifiedImage.width + primaryTextRow.spacing) : 0), implicitWidth)
|
||||
width: Math.min(contentColumn.width - (verifiedImage.visible ? (verifiedImage.width + primaryTextRow.spacing) : 0) - (mutedImage.visible ? (mutedImage.width + primaryTextRow.spacing) : 0), implicitWidth)
|
||||
font.bold: appSettings.highlightUnreadConversations && ( !chatListViewItem.isMuted && (chatListViewItem.unreadCount > 0 || chatListViewItem.isMarkedAsUnread) )
|
||||
font.italic: appSettings.highlightUnreadConversations && (chatListViewItem.unreadReactionCount > 0)
|
||||
color: (appSettings.highlightUnreadConversations && (chatListViewItem.unreadCount > 0)) ? Theme.highlightColor : Theme.primaryColor
|
||||
}
|
||||
|
||||
Image {
|
||||
id: verifiedImage
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
source: chatListViewItem.isVerified ? "../../images/icon-verified.svg" : ""
|
||||
sourceSize.width: Theme.iconSizeExtraSmall
|
||||
width: Theme.iconSizeExtraSmall
|
||||
sourceSize: Qt.size(Theme.iconSizeExtraSmall, Theme.iconSizeExtraSmall)
|
||||
width: Theme.iconSizeSmall
|
||||
height: Theme.iconSizeSmall
|
||||
visible: status === Image.Ready
|
||||
}
|
||||
|
||||
Image {
|
||||
id: mutedImage
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
source: chatListViewItem.isMuted ? "../js/emoji/1f507.svg" : ""
|
||||
sourceSize: Qt.size(Theme.iconSizeExtraSmall, Theme.iconSizeExtraSmall)
|
||||
width: Theme.iconSizeSmall
|
||||
height: Theme.iconSizeSmall
|
||||
visible: status === Image.Ready
|
||||
}
|
||||
}
|
||||
|
@ -147,14 +217,12 @@ ListItem {
|
|||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Separator {
|
||||
id: separator
|
||||
anchors {
|
||||
top: mainColumn.bottom
|
||||
topMargin: Theme.paddingMedium
|
||||
bottom: parent.bottom
|
||||
bottomMargin: -1
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
|
|
|
@ -33,9 +33,9 @@ Item {
|
|||
onPinnedMessageChanged: {
|
||||
if (pinnedMessage) {
|
||||
Debug.log("[ChatPage] Activating pinned message");
|
||||
var messageUserText = (pinnedMessage.sender_user_id !== chatPage.myUserId) ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(pinnedMessage.sender_user_id)), pinnedMessageUserText.font.pixelSize) : qsTr("You");
|
||||
var messageUserText = (pinnedMessage.sender_id.user_id !== chatPage.myUserId) ? Emoji.emojify(Functions.getUserName(tdLibWrapper.getUserInformation(pinnedMessage.sender_id.user_id)), pinnedMessageUserText.font.pixelSize) : qsTr("You");
|
||||
pinnedMessageUserText.text = (messageUserText === "" ? qsTr("Pinned Message") : messageUserText );
|
||||
pinnedMessageText.text = Emoji.emojify(Functions.getMessageText(pinnedMessage, true, pinnedMessage.sender_user_id === chatPage.myUserId, false), pinnedMessageText.font.pixelSize);
|
||||
pinnedMessageText.text = Emoji.emojify(Functions.getMessageText(pinnedMessage, true, chatPage.myUserId, false), pinnedMessageText.font.pixelSize);
|
||||
pinnedMessageItem.visible = true;
|
||||
} else {
|
||||
pinnedMessageItem.visible = false;
|
||||
|
@ -123,7 +123,7 @@ Item {
|
|||
id: unpinMessageIconButton
|
||||
icon.source: "image://theme/icon-m-remove"
|
||||
onClicked: {
|
||||
Remorse.itemAction(pinnedMessageRow, qsTr("Message unpinned"), function() { tdLibWrapper.unpinMessage(chatPage.chatInformation.id);
|
||||
Remorse.itemAction(pinnedMessageRow, qsTr("Message unpinned"), function() { tdLibWrapper.unpinMessage(chatPage.chatInformation.id, pinnedMessage.id);
|
||||
pinnedMessageItem.requestCloseMessage(); });
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
|
@ -18,25 +18,25 @@
|
|||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "../"
|
||||
|
||||
Item {
|
||||
visible: imageContainer.tweenFactor > 0.8 && bigProfilePictureList.count > 0
|
||||
property bool isActive: imageContainer.tweenFactor === 1.0
|
||||
id: profilePictureListItem
|
||||
visible: imageContainer.thumbnailVisible && bigProfilePictureList.count > 0
|
||||
property bool isActive: imageContainer.thumbnailActive
|
||||
readonly property int currentPictureIndex: bigProfilePictureList.currentIndex
|
||||
|
||||
opacity: isActive ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
|
||||
SlideshowView {
|
||||
id: bigProfilePictureList
|
||||
property bool isActive: imageContainer.tweenFactor === 1.0
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
clip: true
|
||||
itemWidth: width
|
||||
itemHeight: height
|
||||
interactive: parent.isActive
|
||||
model: chatInformationPage.chatPartnerProfilePhotos
|
||||
model: imageContainer.thumbnailModel
|
||||
delegate: Item {
|
||||
width: bigProfilePictureList.itemWidth
|
||||
height: bigProfilePictureList.itemHeight
|
||||
|
@ -44,13 +44,13 @@ Item {
|
|||
id: chatPictureDetail
|
||||
photoData: modelData.sizes[modelData.sizes.length - 1].photo
|
||||
replacementStringHint: ""
|
||||
radius: chatPictureThumbnail.radius
|
||||
radius: imageContainer.thumbnailRadius
|
||||
anchors.fill: parent
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("../../pages/ImagePage.qml"), { "photoData" : modelData });
|
||||
pageStack.push(Qt.resolvedUrl("../pages/ImagePage.qml"), { "photoData" : modelData });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,16 +58,18 @@ Item {
|
|||
|
||||
Text {
|
||||
visible: bigProfilePictureList.count > 1
|
||||
width: parent.width
|
||||
width: parent.width - Theme.paddingSmall
|
||||
anchors {
|
||||
bottomMargin: Theme.paddingSmall
|
||||
bottom: parent.bottom
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
property var baseString: new Array(bigProfilePictureList.count+1).join(" ○ ")
|
||||
text: baseString.substring(0,bigProfilePictureList.currentIndex*3) + " ● " + baseString.substring((bigProfilePictureList.currentIndex+1)*3)
|
||||
text: (baseString.substring(0,bigProfilePictureList.currentIndex*3) + " ● " + baseString.substring((bigProfilePictureList.currentIndex+1)*3)).trim()
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: Theme.primaryColor
|
||||
style: Text.Raised
|
||||
styleColor: Theme.highlightDimmerColor
|
||||
}
|
||||
|
||||
}
|
|
@ -22,7 +22,6 @@ import Sailfish.Silica 1.0
|
|||
import WerkWolf.Fernschreiber 1.0
|
||||
|
||||
Item {
|
||||
|
||||
id: profileThumbnail
|
||||
|
||||
property alias photoData: file.fileInformation
|
||||
|
@ -30,6 +29,10 @@ Item {
|
|||
property int radius: width / 2
|
||||
property int imageStatus: -1
|
||||
property bool optimizeImageSize: true
|
||||
property bool highlighted
|
||||
|
||||
layer.enabled: highlighted
|
||||
layer.effect: PressEffect { source: profileThumbnail }
|
||||
|
||||
function getReplacementString() {
|
||||
if (replacementStringHint.length > 2) {
|
||||
|
@ -66,7 +69,6 @@ Item {
|
|||
id: singleImage
|
||||
width: parent.width - Theme.paddingSmall
|
||||
height: width
|
||||
anchors.centerIn: parent
|
||||
source: file.path
|
||||
sourceSize.width: optimizeImageSize ? width : undefined
|
||||
sourceSize.height: optimizeImageSize ? height : undefined
|
||||
|
|
121
qml/components/ReplyMarkupButtons.qml
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "../js/twemoji.js" as Emoji
|
||||
import "../js/functions.js" as Functions
|
||||
import "../js/debug.js" as Debug
|
||||
|
||||
Column {
|
||||
id: replyMarkupButtons
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
Repeater {
|
||||
model: myMessage.reply_markup.rows
|
||||
delegate: Row {
|
||||
width: parent.width
|
||||
height: Theme.itemSizeSmall
|
||||
spacing: Theme.paddingSmall
|
||||
Repeater {
|
||||
id: buttonsRepeater
|
||||
model: modelData
|
||||
property int itemWidth: replyMarkupButtons.width / count
|
||||
delegate: MouseArea {
|
||||
/*
|
||||
Unimplemented callback types:
|
||||
inlineKeyboardButtonTypeBuy
|
||||
inlineKeyboardButtonTypeCallbackGame
|
||||
inlineKeyboardButtonTypeCallbackWithPassword
|
||||
inlineKeyboardButtonTypeLoginUrl
|
||||
inlineKeyboardButtonTypeSwitchInline
|
||||
*/
|
||||
property var callbacks: ({
|
||||
inlineKeyboardButtonTypeCallback: function(){
|
||||
tdLibWrapper.getCallbackQueryAnswer(myMessage.chat_id, myMessage.id, {data: modelData.type.data, "@type": "callbackQueryPayloadData"})
|
||||
},
|
||||
|
||||
inlineKeyboardButtonTypeCallbackGame: function(){
|
||||
tdLibWrapper.getCallbackQueryAnswer(myMessage.chat_id, myMessage.id, {game_short_name: myMessage.content.game.short_name, "@type": "callbackQueryPayloadGame"})
|
||||
},
|
||||
inlineKeyboardButtonTypeUrl: function() {
|
||||
Functions.handleLink(modelData.type.url);
|
||||
},
|
||||
inlineKeyboardButtonTypeSwitchInline: function() {
|
||||
if(modelData.type.in_current_chat) {
|
||||
chatPage.setMessageText("@" + userInformation.usernames.editable_username + " "+(modelData.type.query || ""))
|
||||
} else {
|
||||
|
||||
pageStack.push(Qt.resolvedUrl("../pages/ChatSelectionPage.qml"), {
|
||||
myUserId: chatPage.myUserId,
|
||||
payload: { neededPermissions: ["can_send_other_messages"], text:"@" + userInformation.usernames.editable_username + " "+(modelData.type.query || "")},
|
||||
state: "fillTextArea"
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
keyboardButtonTypeText: function() {
|
||||
chatPage.setMessageText(modelData.text, true);
|
||||
}
|
||||
})
|
||||
enabled: !!callbacks[modelData.type["@type"]]
|
||||
height: Theme.itemSizeSmall
|
||||
width: (replyMarkupButtons.width + Theme.paddingSmall) / buttonsRepeater.count - (Theme.paddingSmall)
|
||||
onClicked: {
|
||||
callbacks[modelData.type["@type"]]();
|
||||
}
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
radius: Theme.paddingSmall
|
||||
color: parent.pressed ? Theme.rgba(Theme.highlightBackgroundColor, Theme.highlightBackgroundOpacity)
|
||||
: Theme.rgba(Theme.primaryColor, Theme.opacityFaint)
|
||||
opacity: parent.enabled ? 1.0 : Theme.opacityLow
|
||||
|
||||
Label {
|
||||
width: Math.min(parent.width - Theme.paddingSmall*2, contentWidth)
|
||||
truncationMode: TruncationMode.Fade
|
||||
text: Emoji.emojify(modelData.text, Theme.fontSizeSmall)
|
||||
color: parent.parent.pressed ? Theme.highlightColor : Theme.primaryColor
|
||||
anchors.centerIn: parent
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
}
|
||||
Icon {
|
||||
property var sources: ({
|
||||
inlineKeyboardButtonTypeUrl: "../../images/icon-s-link.svg",
|
||||
inlineKeyboardButtonTypeSwitchInline: !modelData.type.in_current_chat ? "image://theme/icon-s-repost" : "image://theme/icon-s-edit",
|
||||
inlineKeyboardButtonTypeCallbackWithPassword: "image://theme/icon-s-asterisk"
|
||||
})
|
||||
visible: !!sources[modelData.type["@type"]]
|
||||
opacity: 0.6
|
||||
source: sources[modelData.type["@type"]] || ""
|
||||
sourceSize: Qt.size(Theme.iconSizeSmall, Theme.iconSizeSmall)
|
||||
highlighted: parent.pressed
|
||||
anchors {
|
||||
right: parent.right
|
||||
top: parent.top
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,22 +25,52 @@ Item {
|
|||
id: stickerPickerOverlayItem
|
||||
anchors.fill: parent
|
||||
|
||||
property var recentStickers: stickerManager.getRecentStickers()
|
||||
property var installedStickerSets: stickerManager.getInstalledStickerSets()
|
||||
property bool pickerLoaded: false
|
||||
property var recentStickers: stickerManager.getRecentStickers();
|
||||
property var installedStickerSets: stickerManager.getInstalledStickerSets();
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onOkReceived: {
|
||||
if (request === "removeStickerSet") {
|
||||
appNotification.show(qsTr("Sticker set successfully removed!"));
|
||||
tdLibWrapper.getInstalledStickerSets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: stickerManager
|
||||
onStickerSetsReceived: {
|
||||
installedStickerSets = stickerManager.getInstalledStickerSets();
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: stickerComponent
|
||||
BackgroundItem {
|
||||
id: stickerSetItem
|
||||
width: Theme.itemSizeExtraLarge
|
||||
height: Theme.itemSizeExtraLarge
|
||||
|
||||
onClicked: stickerPickerOverlayItem.stickerPicked(modelData.sticker.remote.id)
|
||||
|
||||
TDLibThumbnail {
|
||||
thumbnail: modelData.thumbnail
|
||||
anchors.fill: parent
|
||||
highlighted: stickerSetItem.highlighted
|
||||
}
|
||||
|
||||
Label {
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
text: Emoji.emojify(modelData.emoji, font.pixelSize)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
signal stickerPicked(var stickerId)
|
||||
|
||||
Timer {
|
||||
id: stickerPickerLoadedTimer
|
||||
interval: 100
|
||||
running: true
|
||||
repeat: false
|
||||
onTriggered: {
|
||||
stickerPickerOverlayItem.pickerLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: stickerPickerOverlayBackground
|
||||
anchors.fill: parent
|
||||
|
@ -49,35 +79,32 @@ Item {
|
|||
opacity: 0.7
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: stickerPickerFlickable
|
||||
SilicaListView {
|
||||
id: stickerPickerListView
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.paddingMedium
|
||||
|
||||
opacity: stickerPickerOverlayItem.pickerLoaded ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
visible: stickerPickerOverlayItem.pickerLoaded
|
||||
|
||||
contentHeight: stickerPickerColumn.height
|
||||
clip: true
|
||||
|
||||
Column {
|
||||
id: stickerPickerColumn
|
||||
spacing: Theme.paddingMedium
|
||||
width: stickerPickerFlickable.width
|
||||
model: stickerPickerOverlayItem.installedStickerSets
|
||||
|
||||
header: Column {
|
||||
spacing: Theme.paddingSmall
|
||||
width: stickerPickerListView.width
|
||||
height: recentStickersGridView.count > 0 ? ( Theme.fontSizeLarge + Theme.itemSizeExtraLarge + 4 * Theme.paddingSmall ) : 0
|
||||
topPadding: Theme.paddingSmall
|
||||
Label {
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.bold: true
|
||||
width: parent.width
|
||||
width: recentStickersGridView.width
|
||||
leftPadding: Theme.paddingMedium
|
||||
visible: recentStickersGridView.count > 0
|
||||
maximumLineCount: 1
|
||||
truncationMode: TruncationMode.Fade
|
||||
text: qsTr("Recently used")
|
||||
}
|
||||
|
||||
SilicaGridView {
|
||||
id: recentStickersGridView
|
||||
width: parent.width
|
||||
height: Theme.itemSizeExtraLarge
|
||||
width: stickerPickerListView.width
|
||||
height: Theme.itemSizeExtraLarge + Theme.paddingSmall
|
||||
cellWidth: Theme.itemSizeExtraLarge;
|
||||
cellHeight: Theme.itemSizeExtraLarge;
|
||||
visible: count > 0
|
||||
|
@ -85,119 +112,132 @@ Item {
|
|||
flow: GridView.FlowTopToBottom
|
||||
|
||||
model: stickerPickerOverlayItem.recentStickers
|
||||
|
||||
delegate: Item {
|
||||
width: recentStickersGridView.cellWidth
|
||||
height: recentStickersGridView.cellHeight
|
||||
|
||||
Image {
|
||||
source: modelData.thumbnail.photo.local.path
|
||||
anchors.fill: parent
|
||||
asynchronous: true
|
||||
onStatusChanged: {
|
||||
if (status === Image.Ready) {
|
||||
stickerPickerLoadedTimer.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: stickerPickerOverlayItem.stickerPicked(modelData.sticker.remote.id)
|
||||
}
|
||||
|
||||
}
|
||||
delegate: stickerComponent
|
||||
|
||||
HorizontalScrollDecorator {}
|
||||
|
||||
}
|
||||
}
|
||||
delegate: Column {
|
||||
id: stickerSetColumn
|
||||
|
||||
Repeater {
|
||||
model: stickerPickerOverlayItem.installedStickerSets
|
||||
width: stickerPickerFlickable.width
|
||||
Column {
|
||||
property bool isExpanded: false
|
||||
function toggleDisplaySet() {
|
||||
stickerSetColumn.isExpanded = !stickerSetColumn.isExpanded;
|
||||
if (stickerSetColumn.isExpanded) {
|
||||
stickerSetLoader.myStickerSet = modelData.stickers;
|
||||
}
|
||||
}
|
||||
|
||||
spacing: Theme.paddingSmall
|
||||
width: parent.width
|
||||
|
||||
Row {
|
||||
id: stickerSetTitleRow
|
||||
width: parent.width
|
||||
height: Theme.itemSizeMedium + ( 2 * Theme.paddingSmall )
|
||||
spacing: Theme.paddingMedium
|
||||
width: parent.width
|
||||
BackgroundItem {
|
||||
id: stickerSetToggle
|
||||
width: parent.width - removeSetButton.width - Theme.paddingMedium * 2
|
||||
height: parent.height
|
||||
|
||||
onClicked: {
|
||||
toggleDisplaySet();
|
||||
}
|
||||
TDLibThumbnail {
|
||||
id: stickerSetThumbnail
|
||||
thumbnail: modelData.thumbnail ? modelData.thumbnail : modelData.stickers[0].thumbnail
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
leftMargin: Theme.paddingMedium
|
||||
}
|
||||
width: Theme.itemSizeMedium
|
||||
height: Theme.itemSizeMedium
|
||||
highlighted: stickerSetToggle.down
|
||||
}
|
||||
|
||||
Label {
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
id: setTitleText
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
font.bold: true
|
||||
width: parent.width
|
||||
maximumLineCount: 1
|
||||
|
||||
anchors {
|
||||
left: stickerSetThumbnail.right
|
||||
right: expandSetButton.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
margins: Theme.paddingSmall
|
||||
}
|
||||
truncationMode: TruncationMode.Fade
|
||||
text: modelData.title
|
||||
}
|
||||
|
||||
SilicaGridView {
|
||||
id: installedStickerSetGridView
|
||||
Icon {
|
||||
id: expandSetButton
|
||||
source: stickerSetColumn.isExpanded ? "image://theme/icon-m-up" : "image://theme/icon-m-down"
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
rightMargin: Theme.paddingMedium
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
IconButton {
|
||||
id: removeSetButton
|
||||
icon.source: "image://theme/icon-m-remove"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: {
|
||||
var stickerSetId = modelData.id;
|
||||
Remorse.popupAction(chatPage, qsTr("Removing sticker set"), function() {
|
||||
tdLibWrapper.changeStickerSet(stickerSetId, false);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: stickerSetLoader
|
||||
width: parent.width
|
||||
height: Theme.itemSizeExtraLarge
|
||||
cellWidth: Theme.itemSizeExtraLarge;
|
||||
cellHeight: Theme.itemSizeExtraLarge;
|
||||
active: stickerSetColumn.isExpanded || height > 0
|
||||
height: stickerSetColumn.isExpanded ? Theme.itemSizeExtraLarge + Theme.paddingSmall : 0
|
||||
opacity: stickerSetColumn.isExpanded ? 1.0 : 0.0
|
||||
|
||||
Behavior on height {
|
||||
NumberAnimation { duration: 200 }
|
||||
}
|
||||
Behavior on opacity {
|
||||
NumberAnimation { duration: 200 }
|
||||
}
|
||||
|
||||
property var myStickerSet
|
||||
onActiveChanged: {
|
||||
if(!active) {
|
||||
myStickerSet = ({});
|
||||
}
|
||||
}
|
||||
|
||||
sourceComponent: Component {
|
||||
SilicaListView {
|
||||
id: installedStickerSetGridView
|
||||
width: stickerSetLoader.width
|
||||
height: stickerSetLoader.height
|
||||
|
||||
orientation: Qt.Horizontal
|
||||
visible: count > 0
|
||||
clip: true
|
||||
flow: GridView.FlowTopToBottom
|
||||
|
||||
model: modelData.stickers
|
||||
delegate: Item {
|
||||
width: installedStickerSetGridView.cellWidth
|
||||
height: installedStickerSetGridView.cellHeight
|
||||
|
||||
Image {
|
||||
id: singleStickerImage
|
||||
source: modelData.thumbnail.photo.local.is_downloading_completed ? modelData.thumbnail.photo.local.path : ""
|
||||
anchors.fill: parent
|
||||
visible: modelData.thumbnail.photo.local.is_downloading_completed
|
||||
asynchronous: true
|
||||
onStatusChanged: {
|
||||
if (status === Image.Ready) {
|
||||
stickerPickerLoadedTimer.restart();
|
||||
}
|
||||
}
|
||||
}
|
||||
Label {
|
||||
font.pixelSize: Theme.fontSizeHuge
|
||||
anchors.fill: parent
|
||||
maximumLineCount: 1
|
||||
truncationMode: TruncationMode.Fade
|
||||
text: Emoji.emojify(modelData.emoji, font.pixelSize)
|
||||
visible: !modelData.thumbnail.photo.local.is_downloading_completed
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: stickerPickerOverlayItem.stickerPicked(modelData.sticker.remote.id)
|
||||
}
|
||||
}
|
||||
model: stickerSetLoader.myStickerSet
|
||||
delegate: stickerComponent
|
||||
|
||||
HorizontalScrollDecorator {}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
width: parent.width
|
||||
spacing: Theme.paddingMedium
|
||||
|
||||
opacity: stickerPickerOverlayItem.pickerLoaded ? 0 : 1
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
visible: !stickerPickerOverlayItem.pickerLoaded
|
||||
|
||||
InfoLabel {
|
||||
id: loadingLabel
|
||||
text: qsTr("Loading stickers...")
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: loadingBusyIndicator
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
running: !stickerPickerOverlayItem.pickerLoaded
|
||||
size: BusyIndicatorSize.Large
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
173
qml/components/StickerSetOverlay.qml
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "./messageContent"
|
||||
import "../js/functions.js" as Functions
|
||||
import "../js/twemoji.js" as Emoji
|
||||
import "../js/debug.js" as Debug
|
||||
|
||||
Flickable {
|
||||
id: stickerSetOverlayFlickable
|
||||
anchors.fill: parent
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
contentHeight: stickerSetContentColumn.height
|
||||
clip: true
|
||||
|
||||
property string stickerSetId;
|
||||
property var stickerSet;
|
||||
signal requestClose;
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!stickerManager.hasStickerSet(stickerSetId)) {
|
||||
tdLibWrapper.getStickerSet(stickerSetId);
|
||||
} else {
|
||||
stickerSet = stickerManager.getStickerSet(stickerSetId);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onStickerSetReceived: {
|
||||
if (stickerSet.id === stickerSetOverlayFlickable.stickerSetId) {
|
||||
stickerSetOverlayFlickable.stickerSet = stickerSet;
|
||||
}
|
||||
}
|
||||
onOkReceived: {
|
||||
if (request === "installStickerSet") {
|
||||
appNotification.show(qsTr("Sticker set successfully installed!"));
|
||||
installSetButton.visible = false;
|
||||
tdLibWrapper.getInstalledStickerSets();
|
||||
}
|
||||
if (request === "removeStickerSet") {
|
||||
appNotification.show(qsTr("Sticker set successfully removed!"));
|
||||
installSetButton.visible = true;
|
||||
tdLibWrapper.getInstalledStickerSets();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: stickerSetContentBackground
|
||||
color: Theme.overlayBackgroundColor
|
||||
opacity: 0.7
|
||||
anchors.fill: parent
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
stickerSetOverlayFlickable.requestClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: stickerSetContentColumn
|
||||
spacing: Theme.paddingMedium
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
Row {
|
||||
id: stickerSetTitleRow
|
||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||
height: overlayStickerTitleText.height + ( 2 * Theme.paddingMedium )
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Label {
|
||||
id: overlayStickerTitleText
|
||||
|
||||
width: parent.width - installSetButton.width - closeSetButton.width
|
||||
text: stickerSet.title
|
||||
font.pixelSize: Theme.fontSizeExtraLarge
|
||||
font.weight: Font.ExtraBold
|
||||
maximumLineCount: 1
|
||||
truncationMode: TruncationMode.Fade
|
||||
textFormat: Text.StyledText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: installSetButton
|
||||
icon.source: "image://theme/icon-m-add"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: !stickerManager.isStickerSetInstalled(stickerSet.id)
|
||||
onClicked: {
|
||||
tdLibWrapper.changeStickerSet(stickerSet.id, true);
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: removeSetButton
|
||||
icon.source: "image://theme/icon-m-remove"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: !installSetButton.visible
|
||||
onClicked: {
|
||||
tdLibWrapper.changeStickerSet(stickerSet.id, false);
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: closeSetButton
|
||||
icon.source: "image://theme/icon-m-clear"
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
onClicked: {
|
||||
stickerSetOverlayFlickable.requestClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SilicaGridView {
|
||||
id: stickerSetGridView
|
||||
|
||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||
height: parent.height - stickerSetTitleRow.height - Theme.paddingMedium
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
cellWidth: chatPage.isLandscape ? (width / 5) : (width / 3);
|
||||
cellHeight: cellWidth
|
||||
|
||||
visible: count > 0
|
||||
|
||||
clip: true
|
||||
|
||||
model: stickerSet.stickers
|
||||
delegate: Item {
|
||||
width: stickerSetGridView.cellWidth - Theme.paddingSmall
|
||||
height: stickerSetGridView.cellHeight - Theme.paddingSmall
|
||||
|
||||
TDLibThumbnail {
|
||||
id: singleStickerThumbnail
|
||||
thumbnail: modelData.thumbnail
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
Label {
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
text: Emoji.emojify(modelData.emoji, font.pixelSize)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
VerticalScrollDecorator {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
55
qml/components/TDLibImage.qml
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
import "../js/debug.js" as Debug
|
||||
|
||||
Image {
|
||||
id: tdLibImage
|
||||
property alias fileInformation: file.fileInformation
|
||||
readonly property alias file: file
|
||||
property bool highlighted
|
||||
|
||||
asynchronous: true
|
||||
enabled: !!file.fileId
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
clip: true
|
||||
opacity: status === Image.Ready ? 1.0 : 0.0
|
||||
source: enabled && file.isDownloadingCompleted ? file.path : ""
|
||||
visible: opacity > 0
|
||||
sourceSize {
|
||||
width: width
|
||||
height: height
|
||||
}
|
||||
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
|
||||
layer {
|
||||
enabled: tdLibImage.enabled && tdLibImage.highlighted
|
||||
effect: PressEffect { source: tdLibImage }
|
||||
}
|
||||
|
||||
TDLibFile {
|
||||
id: file
|
||||
autoLoad: true
|
||||
tdlib: tdLibWrapper
|
||||
}
|
||||
}
|
54
qml/components/TDLibMinithumbnail.qml
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
property var minithumbnail
|
||||
property bool highlighted
|
||||
anchors.fill: parent
|
||||
active: !!minithumbnail
|
||||
sourceComponent: Component {
|
||||
Item {
|
||||
Image {
|
||||
id: minithumbnailImage
|
||||
anchors.fill: parent
|
||||
source: "data:image/jpg;base64,"+minithumbnail.data
|
||||
fillMode: tdLibImage.fillMode
|
||||
opacity: status === Image.Ready ? 1.0 : 0.0
|
||||
cache: false
|
||||
visible: opacity > 0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
|
||||
layer {
|
||||
enabled: loader.highlighted
|
||||
effect: PressEffect { source: minithumbnailImage }
|
||||
}
|
||||
}
|
||||
|
||||
FastBlur {
|
||||
anchors.fill: parent
|
||||
source: minithumbnailImage
|
||||
radius: Theme.paddingLarge
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
69
qml/components/TDLibPhoto.qml
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import Sailfish.Silica 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
|
||||
Item {
|
||||
id: tdLibPhoto
|
||||
property var photo
|
||||
property bool highlighted
|
||||
readonly property alias fileInformation: tdLibImage.fileInformation
|
||||
readonly property alias image: tdLibImage
|
||||
|
||||
onWidthChanged: setImageFile()
|
||||
onPhotoChanged: setImageFile()
|
||||
|
||||
function setImageFile() {
|
||||
if (photo) {
|
||||
var photoSize;
|
||||
for (var i = 0; i < photo.sizes.length; i++) {
|
||||
photoSize = photo.sizes[i].photo;
|
||||
if (photo.sizes[i].width >= width) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (photoSize && photoSize.id !== tdLibImage.fileInformation.id) {
|
||||
tdLibImage.fileInformation = photoSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TDLibMinithumbnail {
|
||||
id: minithumbnailLoader
|
||||
active: !!minithumbnail && tdLibImage.opacity < 1.0
|
||||
minithumbnail: tdLibPhoto.photo.minithumbnail
|
||||
highlighted: parent.highlighted
|
||||
}
|
||||
|
||||
BackgroundImage {
|
||||
visible: !tdLibImage.visible && !(minithumbnailLoader.item && minithumbnailLoader.item.visible)
|
||||
}
|
||||
|
||||
TDLibImage {
|
||||
id: tdLibImage
|
||||
width: parent.width //don't use anchors here for easier custom scaling
|
||||
height: parent.height
|
||||
cache: false
|
||||
highlighted: parent.highlighted
|
||||
}
|
||||
|
||||
Component.onCompleted: setImageFile()
|
||||
}
|
112
qml/components/TDLibThumbnail.qml
Normal file
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import Nemo.Thumbnailer 1.0
|
||||
|
||||
Item {
|
||||
id: tdlibThumbnail
|
||||
/*
|
||||
Optional thumbnail, usually as property "thumbnail".
|
||||
The following TDLib objects can have it:
|
||||
- animation
|
||||
- audio (as "album_cover_thumbnail")
|
||||
- document
|
||||
- sticker (no minithumbnail)
|
||||
- video
|
||||
- videoNote
|
||||
- stickerSet (no minithumbnail)
|
||||
- stickerSetInfo (no minithumbnail)
|
||||
- inlineQueryResultArticle (no minithumbnail)
|
||||
- inlineQueryResultContact (no minithumbnail)
|
||||
- inlineQueryResultLocation (no minithumbnail)
|
||||
- inlineQueryResultVenue (no minithumbnail)
|
||||
*/
|
||||
property var thumbnail
|
||||
/*
|
||||
Optional minithumbnail, usually as property "minithumbnail".
|
||||
Has data inline: If present, it doesn't need another request.
|
||||
The following TDLib objects can have it:
|
||||
- animation
|
||||
- audio (as "album_cover_minithumbnail")
|
||||
- document
|
||||
- photo / chatPhoto (Note: No thumbnail, so not applicable here)
|
||||
- video
|
||||
- videoNote
|
||||
*/
|
||||
property alias minithumbnail: minithumbnailLoader.minithumbnail
|
||||
property bool useBackgroundImage: true
|
||||
property bool highlighted
|
||||
|
||||
property bool isVideo: !!thumbnail && thumbnail.format["@type"] === "thumbnailFormatMpeg4"
|
||||
property string videoMimeType: "video/mp4"
|
||||
|
||||
readonly property bool hasVisibleThumbnail: thumbnailImage.opacity !== 1.0
|
||||
&& !(videoThumbnailLoader.item && videoThumbnailLoader.item.opacity === 1.0)
|
||||
|
||||
layer {
|
||||
enabled: highlighted
|
||||
effect: PressEffect { source: tdlibThumbnail }
|
||||
}
|
||||
|
||||
TDLibMinithumbnail {
|
||||
id: minithumbnailLoader
|
||||
active: !!minithumbnail && thumbnailImage.opacity < 1.0
|
||||
}
|
||||
BackgroundImage {
|
||||
visible: tdlibThumbnail.useBackgroundImage && thumbnailImage.opacity < 1.0
|
||||
}
|
||||
|
||||
// image thumbnail
|
||||
TDLibImage {
|
||||
id: thumbnailImage
|
||||
anchors.fill: parent
|
||||
enabled: !parent.isVideo
|
||||
fileInformation: tdlibThumbnail.thumbnail ? tdlibThumbnail.thumbnail.file : {}
|
||||
onStatusChanged: { //TODO check if this is really how it is ;)
|
||||
if(status === Image.Error) {
|
||||
// in some cases, webp is used (without correct mime type).
|
||||
// we just try it blindly and cross our fingers:
|
||||
tdlibThumbnail.videoMimeType = "image/webp";
|
||||
tdlibThumbnail.isVideo = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback for video thumbnail format: try to use Nemo.Thumbnailer
|
||||
Loader {
|
||||
id: videoThumbnailLoader
|
||||
active: parent.isVideo
|
||||
asynchronous: true
|
||||
anchors.fill: parent
|
||||
sourceComponent: Component {
|
||||
id: videoThumbnail
|
||||
Thumbnail {
|
||||
id: thumbnail
|
||||
source: thumbnailImage.file.path
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
mimeType: tdlibThumbnail.videoMimeType
|
||||
visible: opacity > 0
|
||||
opacity: status === Thumbnail.Ready ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
221
qml/components/VoiceNoteOverlay.qml
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../components"
|
||||
import "../js/twemoji.js" as Emoji
|
||||
import "../js/debug.js" as Debug
|
||||
|
||||
Item {
|
||||
id: voiceNoteOverlayItem
|
||||
anchors.fill: parent
|
||||
|
||||
property int recordingState: fernschreiberUtils.getVoiceNoteRecordingState();
|
||||
property int recordingDuration: 0;
|
||||
property bool recordingDone: false;
|
||||
|
||||
function handleRecordingState() {
|
||||
switch (recordingState) {
|
||||
case FernschreiberUtilities.Unavailable:
|
||||
recordingStateLabel.text = qsTr("Unavailable");
|
||||
break;
|
||||
case FernschreiberUtilities.Ready:
|
||||
recordingStateLabel.text = qsTr("Ready");
|
||||
break;
|
||||
case FernschreiberUtilities.Starting:
|
||||
recordingStateLabel.text = qsTr("Starting");
|
||||
break;
|
||||
case FernschreiberUtilities.Recording:
|
||||
recordingStateLabel.text = qsTr("Recording");
|
||||
break;
|
||||
case FernschreiberUtilities.Stopping:
|
||||
recordingStateLabel.text = qsTr("Stopping");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function getTwoDigitString(numberToBeConverted) {
|
||||
var numberString = "00";
|
||||
if (numberToBeConverted > 0 && numberToBeConverted < 10) {
|
||||
numberString = "0" + String(numberToBeConverted);
|
||||
}
|
||||
if (numberToBeConverted >= 10) {
|
||||
numberString = String(numberToBeConverted);
|
||||
}
|
||||
return numberString;
|
||||
}
|
||||
|
||||
function handleRecordingDuration() {
|
||||
var minutes = Math.floor(recordingDuration / 60);
|
||||
var seconds = recordingDuration % 60;
|
||||
recordingDurationLabel.text = getTwoDigitString(minutes) + ":" + getTwoDigitString(seconds);
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
handleRecordingState();
|
||||
handleRecordingDuration();
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: fernschreiberUtils
|
||||
onVoiceNoteDurationChanged: {
|
||||
Debug.log("New duration received: " + duration);
|
||||
recordingDuration = Math.round(duration / 1000);
|
||||
handleRecordingDuration();
|
||||
}
|
||||
onVoiceNoteRecordingStateChanged: {
|
||||
Debug.log("New state received: " + state);
|
||||
recordingState = state;
|
||||
handleRecordingState();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: stickerPickerOverlayBackground
|
||||
anchors.fill: parent
|
||||
|
||||
color: Theme.overlayBackgroundColor
|
||||
opacity: Theme.opacityHigh
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: voiceNoteFlickable
|
||||
anchors.fill: parent
|
||||
anchors.margins: Theme.paddingMedium
|
||||
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
|
||||
contentHeight: voiceNoteColumn.height
|
||||
clip: true
|
||||
|
||||
Column {
|
||||
id: voiceNoteColumn
|
||||
spacing: Theme.paddingMedium
|
||||
width: voiceNoteFlickable.width
|
||||
|
||||
InfoLabel {
|
||||
text: qsTr("Record a Voice Note")
|
||||
}
|
||||
|
||||
Label {
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: qsTr("Press the button to start recording")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
width: Theme.iconSizeExtraLarge
|
||||
height: Theme.iconSizeExtraLarge
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
Rectangle {
|
||||
color: Theme.primaryColor
|
||||
opacity: Theme.opacityOverlay
|
||||
width: Theme.iconSizeExtraLarge
|
||||
height: Theme.iconSizeExtraLarge
|
||||
anchors.centerIn: parent
|
||||
radius: width / 2
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: recordButton
|
||||
color: "red"
|
||||
width: Theme.iconSizeExtraLarge * 0.6
|
||||
height: Theme.iconSizeExtraLarge * 0.6
|
||||
anchors.centerIn: parent
|
||||
radius: width / 2
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
recordButton.visible = false;
|
||||
recordingDone = false;
|
||||
recordingDuration = 0;
|
||||
handleRecordingDuration();
|
||||
fernschreiberUtils.startRecordingVoiceNote();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: stopButton
|
||||
visible: !recordButton.visible
|
||||
color: Theme.overlayBackgroundColor
|
||||
width: Theme.iconSizeExtraLarge * 0.4
|
||||
height: Theme.iconSizeExtraLarge * 0.4
|
||||
anchors.centerIn: parent
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
recordButton.visible = true;
|
||||
fernschreiberUtils.stopRecordingVoiceNote();
|
||||
recordingDone = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: recordingStateLabel
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: recordingDurationLabel
|
||||
wrapMode: Text.Wrap
|
||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
visible: recordingDone
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
text: qsTr("Use recording")
|
||||
onClicked: {
|
||||
attachmentOptionsFlickable.isNeeded = false;
|
||||
attachmentPreviewRow.isVoiceNote = true;
|
||||
attachmentPreviewRow.attachmentDescription = qsTr("Voice Note (%1)").arg(recordingDurationLabel.text);
|
||||
controlSendButton();
|
||||
voiceNoteOverlayLoader.active = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ SilicaFlickable {
|
|||
if(groupFullInfo.members && groupFullInfo.members.length > 0) {
|
||||
for(var memberIndex in groupFullInfo.members) {
|
||||
var memberData = groupFullInfo.members[memberIndex];
|
||||
var userInfo = tdLibWrapper.getUserInformation(memberData.user_id) || {user:{}, bot_info:{}};
|
||||
var userInfo = tdLibWrapper.getUserInformation(memberData.member_id.user_id) || {user:{}, bot_info:{}};
|
||||
memberData.user = userInfo;
|
||||
memberData.bot_info = memberData.bot_info || {};
|
||||
membersList.append(memberData);
|
||||
|
@ -187,6 +187,14 @@ SilicaFlickable {
|
|||
chatInformationPage.chatInformation = newInformation
|
||||
}
|
||||
}
|
||||
onChatNotificationSettingsUpdated: {
|
||||
if (chatInformationPage.chatInformation.id.toString() === chatId) {
|
||||
// set whole object to trigger change
|
||||
var newInformation = chatInformation;
|
||||
newInformation.notification_settings = chatNotificationSettings;
|
||||
chatInformationPage.chatInformation = newInformation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
|
@ -232,7 +240,7 @@ SilicaFlickable {
|
|||
MenuItem {
|
||||
visible: chatInformationPage.isPrivateChat
|
||||
onClicked: {
|
||||
tdLibWrapper.createNewSecretChat(chatInformationPage.chatPartnerGroupId);
|
||||
tdLibWrapper.createNewSecretChat(chatInformationPage.chatPartnerGroupId, "openDirectly");
|
||||
}
|
||||
text: qsTr("New Secret Chat")
|
||||
}
|
||||
|
@ -256,6 +264,10 @@ SilicaFlickable {
|
|||
}
|
||||
return 1 - Math.max(0, Math.min(1, contentFlickable.contentY / maxDimension))
|
||||
}
|
||||
property bool thumbnailVisible: imageContainer.tweenFactor > 0.8
|
||||
property bool thumbnailActive: imageContainer.tweenFactor === 1.0
|
||||
property var thumbnailModel: chatInformationPage.chatPartnerProfilePhotos
|
||||
property int thumbnailRadius: imageContainer.minDimension / 2
|
||||
|
||||
function getEased(min,max,factor) {
|
||||
return min + (max-min)*factor
|
||||
|
@ -271,23 +283,25 @@ SilicaFlickable {
|
|||
replacementStringHint: headerItem.title
|
||||
width: parent.width
|
||||
height: width
|
||||
radius: imageContainer.minDimension / 2
|
||||
radius: imageContainer.thumbnailRadius
|
||||
opacity: profilePictureLoader.status !== Loader.Ready || profilePictureLoader.item.opacity < 1 ? 1.0 : 0.0
|
||||
optimizeImageSize: false
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: profilePictureLoader
|
||||
active: imageContainer.hasImage
|
||||
asynchronous: true
|
||||
anchors.fill: chatPictureThumbnail
|
||||
source: ( chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat)
|
||||
? "ChatInformationProfilePictureList.qml"
|
||||
? "../ProfilePictureList.qml"
|
||||
: "ChatInformationProfilePicture.qml"
|
||||
}
|
||||
}
|
||||
leftMargin: imageContainer.getEased((imageContainer.minDimension + Theme.paddingMedium), 0, imageContainer.tweenFactor) + Theme.horizontalPageMargin
|
||||
title: chatInformationPage.chatInformation.title !== "" ? Emoji.emojify(chatInformationPage.chatInformation.title, Theme.fontSizeLarge) : qsTr("Unknown")
|
||||
description: (chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? ("@"+(chatInformationPage.privateChatUserInformation.username || chatInformationPage.chatPartnerGroupId)) : ""
|
||||
description: ((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && chatInformationPage.privateChatUserInformation.usernames.editable_username)
|
||||
? ("@"+chatInformationPage.privateChatUserInformation.usernames.editable_username) : ""
|
||||
}
|
||||
|
||||
SilicaFlickable {
|
||||
|
@ -350,7 +364,28 @@ SilicaFlickable {
|
|||
height: imageContainer.hasImage ? imageContainer.maxDimension : 0
|
||||
}
|
||||
|
||||
ChatInformationEditArea {
|
||||
Label {
|
||||
id: copyIdText
|
||||
x: Math.max(headerItem.x + imageContainer.x - groupInfoItem.x + (imageContainer.width - width)/2, 0)
|
||||
text: chatInformationPage.chatPartnerGroupId
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: copyIdMouseArea.pressed ? Theme.secondaryHighlightColor : Theme.highlightColor
|
||||
visible: text !== ""
|
||||
|
||||
MouseArea {
|
||||
id: copyIdMouseArea
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: -Theme.paddingLarge
|
||||
}
|
||||
onClicked: {
|
||||
Clipboard.text = copyIdText.text
|
||||
appNotification.show(qsTr("ID has been copied to the clipboard."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InformationEditArea {
|
||||
visible: canEdit
|
||||
canEdit: !(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && chatInformationPage.groupInformation.status && (chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator")
|
||||
headerText: qsTr("Chat Title", "group title header")
|
||||
|
@ -376,7 +411,7 @@ SilicaFlickable {
|
|||
}
|
||||
}
|
||||
}
|
||||
ChatInformationEditArea {
|
||||
InformationEditArea {
|
||||
canEdit: ((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && chatInformationPage.privateChatUserInformation.id === chatInformationPage.myUserId) || ((chatInformationPage.isBasicGroup || chatInformationPage.isSuperGroup) && chatInformationPage.groupInformation && (chatInformationPage.groupInformation.status.can_change_info || chatInformationPage.groupInformation.status["@type"] === "chatMemberStatusCreator"))
|
||||
emptyPlaceholderText: qsTr("There is no information text available, yet.")
|
||||
headerText: qsTr("Info", "group or user infotext header")
|
||||
|
@ -391,7 +426,7 @@ SilicaFlickable {
|
|||
}
|
||||
}
|
||||
|
||||
ChatInformationTextItem {
|
||||
InformationTextItem {
|
||||
headerText: qsTr("Phone Number", "user phone number header")
|
||||
text: ((chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) && chatInformationPage.privateChatUserInformation.phone_number ? "+"+chatInformationPage.privateChatUserInformation.phone_number : "") || ""
|
||||
isLinkedLabel: true
|
||||
|
@ -408,7 +443,7 @@ SilicaFlickable {
|
|||
Row {
|
||||
width: parent.width
|
||||
visible: !!inviteLinkItem.text
|
||||
ChatInformationTextItem {
|
||||
InformationTextItem {
|
||||
id: inviteLinkItem
|
||||
text: !(chatInformationPage.isPrivateChat || chatInformationPage.isSecretChat) ? chatInformationPage.groupFullInformation.invite_link : ""
|
||||
width: parent.width - inviteLinkButton.width
|
||||
|
|
|
@ -22,8 +22,8 @@ import Sailfish.Silica 1.0
|
|||
import "../"
|
||||
|
||||
Item {
|
||||
visible: imageContainer.tweenFactor > 0.8 && chatPictureDetail.imageStatus === Image.Ready
|
||||
property bool isActive: imageContainer.tweenFactor === 1.0
|
||||
visible: parent.thumbnailVisible && chatPictureDetail.imageStatus === Image.Ready
|
||||
property bool isActive: parent.thumbnailActive
|
||||
opacity: isActive ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
ProfileThumbnail {
|
||||
|
|
|
@ -38,18 +38,18 @@ ChatInformationTabItemBase {
|
|||
width: tabBase.width - Theme.horizontalPageMargin * 2
|
||||
x: Theme.horizontalPageMargin
|
||||
|
||||
ChatInformationTextItem {
|
||||
InformationTextItem {
|
||||
headerText: "chatInformation"
|
||||
text:chatInformationPage.chatInformation ? JSON.stringify(chatInformationPage.chatInformation, null, 2) : ""
|
||||
isLinkedLabel: true
|
||||
}
|
||||
ChatInformationTextItem {
|
||||
InformationTextItem {
|
||||
headerText: "groupInformation"
|
||||
text: chatInformationPage.groupInformation ? JSON.stringify(chatInformationPage.groupInformation, null, 2) : ""
|
||||
isLinkedLabel: true
|
||||
}
|
||||
|
||||
ChatInformationTextItem {
|
||||
InformationTextItem {
|
||||
headerText: "groupFullInformation"
|
||||
text: chatInformationPage.groupFullInformation ? JSON.stringify(chatInformationPage.groupFullInformation, null, 2) : ""
|
||||
isLinkedLabel: true
|
||||
|
|
|
@ -72,14 +72,14 @@ ChatInformationTabItemBase {
|
|||
}
|
||||
delegate: PhotoTextsListItem {
|
||||
pictureThumbnail {
|
||||
photoData: (typeof user.profile_photo !== "undefined") ? user.profile_photo.small : ""
|
||||
photoData: user.profile_photo ? user.profile_photo.small : null
|
||||
}
|
||||
width: parent.width
|
||||
|
||||
// chat title
|
||||
primaryText.text: Emoji.emojify(Functions.getUserName(user), primaryText.font.pixelSize)
|
||||
// last user
|
||||
prologSecondaryText.text: "@"+(user.username !== "" ? user.username : user_id) + (user_id === chatInformationPage.myUserId ? " " + qsTr("You") : "")
|
||||
prologSecondaryText.text: "@"+(user.username ? user.username : member_id.user_id) + (member_id.user_id === chatInformationPage.myUserId ? " " + qsTr("You") : "")
|
||||
secondaryText {
|
||||
horizontalAlignment: Text.AlignRight
|
||||
property string statusText: Functions.getChatMemberStatusText(model.status["@type"])
|
||||
|
@ -92,7 +92,7 @@ ChatInformationTabItemBase {
|
|||
}
|
||||
|
||||
onClicked: {
|
||||
tdLibWrapper.createPrivateChat(user_id);
|
||||
tdLibWrapper.createPrivateChat(member_id.user_id, "openDirectly");
|
||||
}
|
||||
}
|
||||
footer: Component {
|
||||
|
@ -154,15 +154,6 @@ ChatInformationTabItemBase {
|
|||
pageStack.pop(pageStack.find( function(page){ return(page._depth === 0)} ), PageStackAction.Immediate);
|
||||
pageStack.push(Qt.resolvedUrl("../../pages/ChatPage.qml"), { "chatInformation" : display });
|
||||
}
|
||||
Connections {
|
||||
target: chatListModel
|
||||
onChatChanged: {
|
||||
if (changedChatId === chat_id) {
|
||||
// Force update of some list item elements (currently only last message text seems to create problems). dataChanged() doesn't seem to trigger them all :(
|
||||
secondaryText.text = last_message_text ? Emoji.emojify(Functions.enhanceHtmlEntities(last_message_text), Theme.fontSizeExtraSmall) : qsTr("Unknown")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -171,7 +162,7 @@ ChatInformationTabItemBase {
|
|||
interval: 600
|
||||
property int fetchLimit: 50
|
||||
onTriggered: {
|
||||
if(chatInformationPage.isSuperGroup && !chatInformationPage.isChannel && (chatInformationPage.groupInformation.member_count > membersView.count)) { //
|
||||
if(chatInformationPage.isSuperGroup && (!chatInformationPage.isChannel || chatInformationPage.canGetMembers) && (chatInformationPage.groupInformation.member_count > membersView.count)) {
|
||||
tabBase.loading = true
|
||||
tdLibWrapper.getSupergroupMembers(chatInformationPage.chatPartnerGroupId, fetchLimit, pageContent.membersList.count);
|
||||
fetchLimit = 200
|
||||
|
@ -188,7 +179,10 @@ ChatInformationTabItemBase {
|
|||
if(members && members.length > 0 && chatInformationPage.groupInformation.member_count > membersView.count) {
|
||||
for(var memberIndex in members) {
|
||||
var memberData = members[memberIndex];
|
||||
var userInfo = tdLibWrapper.getUserInformation(memberData.user_id) || {user:{}, bot_info:{}};
|
||||
var userInfo = tdLibWrapper.getUserInformation(memberData.member_id.user_id) || {user:{}, bot_info:{}};
|
||||
if (!userInfo.username && userInfo.usernames && userInfo.usernames.active_usernames) {
|
||||
userInfo.username = userInfo.usernames.active_usernames[0]
|
||||
}
|
||||
memberData.user = userInfo;
|
||||
memberData.bot_info = memberData.bot_info || {};
|
||||
pageContent.membersList.append(memberData);
|
||||
|
|
33
qml/components/inlineQueryResults/InlineQueryResult.qml
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
BackgroundItem {
|
||||
id: queryResultItem
|
||||
|
||||
function sendInlineQueryResultMessage() {
|
||||
tdLibWrapper.sendInlineQueryResultMessage(inlineQueryLoader.chatId, 0, 0, inlineQueryComponent.inlineQueryId, model.id);
|
||||
inlineQueryLoader.textField.text = "";
|
||||
}
|
||||
onClicked: {
|
||||
sendInlineQueryResultMessage()
|
||||
}
|
||||
|
||||
}
|
291
qml/components/inlineQueryResults/InlineQueryResultAnimation.qml
Normal file
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import QtMultimedia 5.6
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
import Nemo.Thumbnailer 1.0
|
||||
import "../"
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
import "../../js/debug.js" as Debug
|
||||
|
||||
InlineQueryResult {
|
||||
id: queryResultItem
|
||||
property bool isAnimation: true
|
||||
property bool loopPreview: isAnimation
|
||||
property bool mutePreview: isAnimation
|
||||
enabled: false // don't send on click
|
||||
layer.enabled: mouseArea.pressed
|
||||
layer.effect: PressEffect { source: queryResultItem }
|
||||
|
||||
property string animationKey: "animation"
|
||||
property bool hasThumbnail: !!model[queryResultItem.animationKey].thumbnail
|
||||
|
||||
property string videoMimeType: "video/mp4"
|
||||
|
||||
TDLibFile {
|
||||
id: file
|
||||
tdlib: tdLibWrapper
|
||||
autoLoad: true
|
||||
fileInformation: hasThumbnail ? model[queryResultItem.animationKey].thumbnail.file : (queryResultItem.isAnimation ? model[queryResultItem.animationKey].animation : model[queryResultItem.animationKey].video)
|
||||
}
|
||||
|
||||
Image {
|
||||
id: miniThumbnail
|
||||
asynchronous: true
|
||||
source: model[queryResultItem.animationKey].minithumbnail ? "data:image/jpg;base64,"+model[queryResultItem.animationKey].minithumbnail.data : ""
|
||||
anchors.fill: parent
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
layer.enabled: queryResultItem.pressed
|
||||
layer.effect: PressEffect { source: miniThumbnail }
|
||||
}
|
||||
Component {
|
||||
id: videoThumbnail
|
||||
Thumbnail {
|
||||
id: thumbnail
|
||||
source: file.path
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
mimeType: queryResultItem.videoMimeType
|
||||
layer.enabled: queryResultItem.pressed
|
||||
layer.effect: PressEffect { source: thumbnail }
|
||||
opacity: status === Thumbnail.Ready ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: imageThumbnail
|
||||
Image {
|
||||
id: thumbnail
|
||||
source: file.path
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
layer.enabled: queryResultItem.pressed
|
||||
layer.effect: PressEffect { source: thumbnail }
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
opacity: status === Image.Ready ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
onStatusChanged: {
|
||||
// we don't get many hints what may be wrong, so we guess it may be a webp image ;)
|
||||
if(status === Image.Error) {
|
||||
Debug.log("Inline Query Video: Thumbnail invalid. Blindly trying webp, which might work.")
|
||||
queryResultItem.videoMimeType = "image/webp";
|
||||
thumbnailLoader.sourceComponent = videoThumbnail;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
id: thumbnailLoader
|
||||
asynchronous: true
|
||||
active: file.isDownloadingCompleted
|
||||
anchors.fill: parent
|
||||
sourceComponent: queryResultItem.hasThumbnail ? (model[queryResultItem.animationKey].thumbnail.format["@type"] === "thumbnailFormatMpeg4" ? videoThumbnail : imageThumbnail) : model[queryResultItem.animationKey].mime_type === "video/mp4" ? videoThumbnail : imageThumbnail
|
||||
}
|
||||
Column {
|
||||
id: texts
|
||||
anchors {
|
||||
left: parent.left
|
||||
margins: Theme.paddingSmall
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
Label {
|
||||
id: titleLabel
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
visible: text.length > 0
|
||||
text: Emoji.emojify(model.title || "", font.pixelSize);
|
||||
}
|
||||
Label {
|
||||
id: descriptionLabel
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.Wrap
|
||||
visible: text.length > 0
|
||||
text: Emoji.emojify(model.description || "", font.pixelSize);
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
anchors.fill: texts
|
||||
asynchronous: true
|
||||
active: titleLabel.visible || descriptionLabel.visible
|
||||
sourceComponent: Component {
|
||||
DropShadow {
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 0
|
||||
radius: Theme.paddingSmall
|
||||
spread: 0.5
|
||||
samples: 17
|
||||
color: Theme.overlayBackgroundColor
|
||||
source: texts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
// dialog
|
||||
|
||||
var dialog = pageStack.push(dialogComponent,{})
|
||||
dialog.accepted.connect(function() {
|
||||
queryResultItem.sendInlineQueryResultMessage();
|
||||
})
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: dialogComponent
|
||||
Dialog {
|
||||
|
||||
TDLibFile {
|
||||
id: previewFile
|
||||
tdlib: tdLibWrapper
|
||||
autoLoad: model[queryResultItem.animationKey].mime_type !== "text/html"
|
||||
fileInformation: queryResultItem.isAnimation ? model[queryResultItem.animationKey].animation : model[queryResultItem.animationKey].video
|
||||
}
|
||||
|
||||
DialogHeader { id: dialogHeader }
|
||||
|
||||
ProgressCircle {
|
||||
value: previewFile.downloadedSize / previewFile.expectedSize
|
||||
width: Theme.iconSizeMedium
|
||||
height: Theme.iconSizeMedium
|
||||
anchors.centerIn: parent
|
||||
opacity: previewFile.isDownloadingActive ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
}
|
||||
Column {
|
||||
visible: !previewFile.autoLoad
|
||||
spacing: Theme.paddingLarge
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: Theme.horizontalPageMargin
|
||||
right: parent.right
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.secondaryHighlightColor
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
text: Emoji.emojify(model.title || "", font.pixelSize);
|
||||
visible: text.length > 1
|
||||
linkColor: Theme.primaryColor
|
||||
}
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeLarge
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.highlightColor
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
text: '<a href="'+Emoji.emojify(previewFile.fileInformation.remote.id, font.pixelSize)+'">'+Emoji.emojify(previewFile.fileInformation.remote.id, font.pixelSize)+'</a> '
|
||||
linkColor: Theme.primaryColor
|
||||
}
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.secondaryHighlightColor
|
||||
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||
text: Emoji.emojify(model.description || "", font.pixelSize)
|
||||
visible: text.length > 1
|
||||
linkColor: Theme.secondaryColor
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loader {
|
||||
id: videoLoader
|
||||
anchors {
|
||||
top: dialogHeader.bottom
|
||||
left: parent.left
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
active: previewFile.isDownloadingCompleted
|
||||
asynchronous: true
|
||||
sourceComponent: Component {
|
||||
Item {
|
||||
Connections {
|
||||
target: resultView
|
||||
onRequestPlayback: {
|
||||
if(previewVideo.playbackState === MediaPlayer.PlayingState && previewVideo.source !== playbackSource) {
|
||||
previewVideo.pause()
|
||||
}
|
||||
}
|
||||
}
|
||||
Timer {
|
||||
id: loopTimer
|
||||
interval: 0
|
||||
onTriggered: previewVideo.play()
|
||||
}
|
||||
|
||||
Video {
|
||||
id: previewVideo
|
||||
source: previewFile.path
|
||||
autoPlay: true
|
||||
muted: queryResultItem.mutePreview
|
||||
anchors.fill: parent
|
||||
|
||||
onStatusChanged: {
|
||||
if (status == MediaPlayer.EndOfMedia) {
|
||||
if(queryResultItem.loopPreview) {
|
||||
loopTimer.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
onPlaybackStateChanged: {
|
||||
if(playbackState === MediaPlayer.PlayingState) {
|
||||
resultView.requestPlayback(source);
|
||||
}
|
||||
}
|
||||
layer.enabled: playPauseMouseArea.pressed
|
||||
layer.effect: PressEffect { source: previewVideo }
|
||||
}
|
||||
MouseArea {
|
||||
id: playPauseMouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if(previewVideo.playbackState === MediaPlayer.PlayingState) {
|
||||
previewVideo.pause();
|
||||
} else {
|
||||
previewVideo.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
InlineQueryResultDefaultBase {
|
||||
id: queryResultItem
|
||||
|
||||
title: Emoji.emojify(model.title || "", titleLable.font.pixelSize)
|
||||
description: Emoji.emojify(model.description || "", descriptionLabel.font.pixelSize)
|
||||
descriptionLabel {
|
||||
maximumLineCount: 3
|
||||
wrapMode: extraText.length === 0 ? Text.Wrap : Text.NoWrap
|
||||
}
|
||||
|
||||
extraText: model.url || ""
|
||||
extraTextLabel.visible: !model.hide_url && extraText.length > 0
|
||||
|
||||
thumbnailFileInformation: model.thumbnail ? model.thumbnail.file : {}
|
||||
|
||||
icon.source: "image://theme/icon-m-link"
|
||||
icon.visible: thumbnail.visible && thumbnail.opacity === 0
|
||||
|
||||
thumbnail.visible: model.thumbnail || !!model.url
|
||||
}
|
183
qml/components/inlineQueryResults/InlineQueryResultAudio.qml
Normal file
|
@ -0,0 +1,183 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import QtMultimedia 5.6
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../"
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
InlineQueryResult {
|
||||
id: queryResultItem
|
||||
property var resultData: model.audio || model.voice_note
|
||||
property var audioData: resultData.audio || resultData.voice
|
||||
|
||||
enabled: false // don't send on click
|
||||
|
||||
Connections {
|
||||
target: resultView
|
||||
onRequestPlayback: {
|
||||
if(audioPlayer.playbackState === Audio.PlayingState && audioPlayer.source !== playbackSource) {
|
||||
audioPlayer.pause()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TDLibFile {
|
||||
id: file
|
||||
tdlib: tdLibWrapper
|
||||
autoLoad: false
|
||||
fileInformation: queryResultItem.audioData
|
||||
}
|
||||
|
||||
TDLibFile {
|
||||
id: thumbnail
|
||||
tdlib: tdLibWrapper
|
||||
autoLoad: true
|
||||
fileInformation: queryResultItem.resultData.album_cover_thumbnail ? queryResultItem.resultData.album_cover_thumbnail.file : {}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: thumbnailLoader
|
||||
asynchronous: true
|
||||
active: thumbnail.isDownloadingCompleted
|
||||
height: parent.height
|
||||
width: height
|
||||
opacity: item && item.status === Image.Ready ? 0.5 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
sourceComponent: Component {
|
||||
Image {
|
||||
id: thumbnailImage
|
||||
source: thumbnail.path
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
|
||||
layer.enabled: playPauseButton.pressed
|
||||
layer.effect: PressEffect { source: thumbnailImage }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: playPauseButton
|
||||
anchors.centerIn: thumbnailLoader
|
||||
icon {
|
||||
asynchronous: true
|
||||
source: audioPlayer.playbackState === Audio.PlayingState || (file.isDownloadingActive && audioPlayer.autoPlay) ? "image://theme/icon-m-pause": "image://theme/icon-m-play"
|
||||
}
|
||||
onClicked: {
|
||||
if(!file.isDownloadingCompleted && !file.isDownloadingActive) {
|
||||
file.load();
|
||||
audioPlayer.autoPlay = true
|
||||
} else if(file.isDownloadingActive) {
|
||||
// cancel playback intent?
|
||||
audioPlayer.autoPlay = false
|
||||
} else if(file.isDownloadingCompleted) {
|
||||
//playPause
|
||||
if(audioPlayer.playbackState === Audio.PlayingState) {
|
||||
audioPlayer.pause();
|
||||
} else {
|
||||
audioPlayer.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ProgressCircle {
|
||||
value: file.downloadedSize / file.expectedSize
|
||||
width: Theme.iconSizeMedium
|
||||
height: Theme.iconSizeMedium
|
||||
anchors.centerIn: playPauseButton
|
||||
opacity: file.isDownloadingActive ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
}
|
||||
|
||||
Audio {
|
||||
id: audioPlayer
|
||||
source: file.isDownloadingCompleted ? file.path : ""
|
||||
autoPlay: false
|
||||
onPlaybackStateChanged: {
|
||||
if(playbackState === Audio.PlayingState) {
|
||||
resultView.requestPlayback(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors {
|
||||
left: thumbnailLoader.right
|
||||
leftMargin: Theme.paddingSmall
|
||||
right: sendButton.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: Theme.highlightColor
|
||||
text: Emoji.emojify(queryResultItem.resultData.performer || "", font.pixelSize)
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
Label {
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: Theme.secondaryHighlightColor
|
||||
text: Emoji.emojify(queryResultItem.resultData.title || model.title || "", font.pixelSize)
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
Item {
|
||||
height: sizeLabel.height
|
||||
width: parent.width
|
||||
Label {
|
||||
id: durationLabel
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: Theme.secondaryColor
|
||||
text: (audioPlayer.position > 0 || audioPlayer.playbackState === Audio.PlayingState ? (Format.formatDuration(audioPlayer.position/1000, Formatter.DurationShort)+" / ") : "") + Format.formatDuration(queryResultItem.audioData.duration || (audioPlayer.duration/1000), Formatter.DurationShort)
|
||||
visible: (queryResultItem.audioData.duration || (audioPlayer.duration/1000)) > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
Label {
|
||||
id: sizeLabel
|
||||
anchors.right: parent.right
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: Theme.secondaryColor
|
||||
text: Format.formatFileSize(file.expectedSize)
|
||||
visible: file.expectedSize > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: sendButton
|
||||
anchors {
|
||||
right: parent.right
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
icon {
|
||||
asynchronous: true
|
||||
source: "image://theme/icon-m-send"
|
||||
}
|
||||
onClicked: {
|
||||
queryResultItem.sendInlineQueryResultMessage();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
InlineQueryResultDefaultBase {
|
||||
id: queryResultItem
|
||||
property string namesSeparator: model.contact.first_name && model.contact.last_name ? " " : ""
|
||||
|
||||
title: Emoji.emojify(model.contact.first_name + namesSeparator + model.contact.last_name || "", titleLable.font.pixelSize)
|
||||
description: Emoji.emojify(model.contact.phone_number || "", descriptionLabel.font.pixelSize)
|
||||
|
||||
extraText: model.url || ""
|
||||
extraTextLabel.visible: !model.hide_url && extraText.length > 0
|
||||
|
||||
thumbnailFileInformation: model.thumbnail ? model.thumbnail.file : {}
|
||||
|
||||
icon.source: "image://theme/icon-m-contact"
|
||||
icon.visible: thumbnail.visible && thumbnail.opacity === 0
|
||||
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../"
|
||||
|
||||
InlineQueryResult {
|
||||
id: queryResultItem
|
||||
|
||||
property alias title: titleLabel.text
|
||||
property alias titleLable: titleLabel
|
||||
|
||||
property alias description: descriptionLabel.text
|
||||
property alias descriptionLabel: descriptionLabel
|
||||
|
||||
property alias extraText: extraTextLabel.text
|
||||
property alias extraTextLabel: extraTextLabel
|
||||
|
||||
property alias thumbnailFileInformation: thumbnailFile.fileInformation
|
||||
property alias thumbnail: thumbnail
|
||||
|
||||
property alias icon: icon
|
||||
|
||||
|
||||
Image {
|
||||
id: thumbnail
|
||||
source: thumbnailFile.isDownloadingCompleted ? thumbnailFile.path : ""
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
asynchronous: true
|
||||
width: visible ? Theme.itemSizeLarge : 0
|
||||
height: width
|
||||
opacity: status === Image.Ready ? 1.0 : 0.0
|
||||
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
layer.enabled: queryResultItem.pressed
|
||||
layer.effect: PressEffect { source: thumbnail }
|
||||
|
||||
TDLibFile {
|
||||
id: thumbnailFile
|
||||
tdlib: tdLibWrapper
|
||||
autoLoad: true
|
||||
}
|
||||
}
|
||||
Icon {
|
||||
id: icon
|
||||
asynchronous: true
|
||||
anchors.centerIn: thumbnail
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
}
|
||||
|
||||
Column {
|
||||
anchors {
|
||||
left: thumbnail.right
|
||||
leftMargin: thumbnail.visible ? Theme.paddingLarge : Theme.horizontalPageMargin
|
||||
right: parent.right
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
|
||||
Label {
|
||||
id: titleLabel
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
color: highlighted || !queryResultItem.enabled ? Theme.highlightColor : Theme.primaryColor
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
Label {
|
||||
id: descriptionLabel
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: highlighted || !queryResultItem.enabled ? Theme.secondaryColor : Theme.secondaryHighlightColor
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
|
||||
Label {
|
||||
id: extraTextLabel
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: highlighted || !queryResultItem.enabled ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../"
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
Loader {
|
||||
Component {
|
||||
id: documentComponent
|
||||
InlineQueryResultDefaultBase {
|
||||
id: queryResultItem
|
||||
|
||||
title: Emoji.emojify(model.title || model.document.file_name || "", titleLable.font.pixelSize)
|
||||
description: Emoji.emojify(model.description || model.document.file_name || "", descriptionLabel.font.pixelSize)
|
||||
extraText: Format.formatFileSize(model.document.document.expected_size)
|
||||
|
||||
thumbnailFileInformation: model.thumbnail ? model.thumbnail.file : {}
|
||||
|
||||
icon.source: Theme.iconForMimeType(model.document.mime_type)
|
||||
icon.visible: thumbnail.visible && thumbnail.opacity === 0
|
||||
}
|
||||
}
|
||||
Component {
|
||||
id: voiceNoteDocumentComponent
|
||||
InlineQueryResultVoiceNote {
|
||||
resultData: model.document
|
||||
audioData: model.document.document
|
||||
}
|
||||
}
|
||||
sourceComponent: model.document.mime_type === "audio/ogg" ? voiceNoteDocumentComponent : documentComponent
|
||||
}
|
53
qml/components/inlineQueryResults/InlineQueryResultGame.qml
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
InlineQueryResultDefaultBase {
|
||||
id: queryResultItem
|
||||
|
||||
title: Emoji.emojify(model.game.title || "", titleLable.font.pixelSize)
|
||||
description: Emoji.emojify(model.game.description || "", descriptionLabel.font.pixelSize)
|
||||
descriptionLabel {
|
||||
maximumLineCount: 3
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
|
||||
icon.source: "image://theme/icon-m-game-controller"
|
||||
icon.visible: thumbnail.opacity === 0
|
||||
|
||||
|
||||
Component.onCompleted: {
|
||||
if (model.game.photo) {
|
||||
// Check first which size fits best...
|
||||
var photo
|
||||
for (var i = 0; i < model.game.photo.sizes.length; i++) {
|
||||
photo = model.game.photo.sizes[i].photo
|
||||
if (model.game.photo.sizes[i].width >= queryResultItem.width) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (photo) {
|
||||
thumbnailFileInformation = photo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
|
||||
InlineQueryResultVenue {
|
||||
resultData: model
|
||||
}
|
29
qml/components/inlineQueryResults/InlineQueryResultPhoto.qml
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import "../"
|
||||
|
||||
InlineQueryResult {
|
||||
id: queryResultItem
|
||||
|
||||
TDLibPhoto {
|
||||
anchors.fill: parent
|
||||
photo: model.photo
|
||||
}
|
||||
}
|
106
qml/components/inlineQueryResults/InlineQueryResultSticker.qml
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import Nemo.Thumbnailer 1.0
|
||||
import "../"
|
||||
|
||||
InlineQueryResult {
|
||||
id: queryResultItem
|
||||
|
||||
property bool animate
|
||||
property bool animating: animate && model.sticker.is_animated
|
||||
property url stickerId: "http://sticker/" + model.sticker.sticker.remote.id
|
||||
onAnimatingChanged: {
|
||||
if(animating) {
|
||||
resultView.requestPlayback(stickerId);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: resultView
|
||||
onRequestPlayback: {
|
||||
if(queryResultItem.animating && queryResultItem.stickerId !== playbackSource) {
|
||||
animate = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onPressAndHold: {
|
||||
animate = !animate
|
||||
}
|
||||
|
||||
TDLibFile {
|
||||
id: file
|
||||
tdlib: tdLibWrapper
|
||||
fileInformation: model.sticker.sticker
|
||||
autoLoad: true
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: animatedStickerLoader
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: Theme.paddingLarge
|
||||
}
|
||||
active: queryResultItem.animating
|
||||
sourceComponent: Component {
|
||||
AnimatedImage {
|
||||
id: animatedSticker
|
||||
anchors.fill: parent
|
||||
source: file.path
|
||||
asynchronous: true
|
||||
paused: !Qt.application.active
|
||||
cache: false
|
||||
layer.enabled: highlighted
|
||||
layer.effect: PressEffect { source: animatedSticker }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Image {
|
||||
id: staticSticker
|
||||
anchors {
|
||||
fill: parent
|
||||
margins: Theme.paddingLarge
|
||||
}
|
||||
source: file.path
|
||||
fillMode: Image.PreserveAspectFit
|
||||
autoTransform: true
|
||||
asynchronous: true
|
||||
visible: !queryResultItem.animating && opacity > 0
|
||||
opacity: status === Image.Ready ? 1 : 0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
layer.enabled: queryResultItem.highlighted
|
||||
layer.effect: PressEffect { source: staticSticker }
|
||||
}
|
||||
|
||||
Icon {
|
||||
source: "image://theme/icon-m-video"
|
||||
width: Theme.iconSizeExtraSmall
|
||||
height: width
|
||||
visible: model.sticker.is_animated
|
||||
highlighted: queryResultItem.highlighted || queryResultItem.animating
|
||||
anchors {
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
}
|
51
qml/components/inlineQueryResults/InlineQueryResultVenue.qml
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
InlineQueryResultDefaultBase {
|
||||
id: queryResultItem
|
||||
property string locationId
|
||||
property var resultData: model.venue
|
||||
|
||||
title: Emoji.emojify(queryResultItem.resultData.title || (queryResultItem.resultData.location.latitude + ":" + queryResultItem.resultData.location.longitude), titleLable.font.pixelSize)
|
||||
description: Emoji.emojify(queryResultItem.resultData.address || "", descriptionLabel.font.pixelSize)
|
||||
extraText: Emoji.emojify(queryResultItem.resultData.type || "", extraTextLabel.font.pixelSize)
|
||||
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onFileUpdated: {
|
||||
if(fileInformation["@extra"] === queryResultItem.locationId) {
|
||||
thumbnailFileInformation = fileInformation
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
var dimensions = [ Math.round(thumbnail.width), Math.round(thumbnail.height)];
|
||||
|
||||
locationId = "location:" + resultData.location.latitude + ":" + resultData.location.longitude + ":" + dimensions[0] + ":" + dimensions[1];
|
||||
|
||||
tdLibWrapper.getMapThumbnailFile(chatId, resultData.location.latitude, resultData.location.longitude, dimensions[0], dimensions[1], locationId);
|
||||
}
|
||||
}
|
25
qml/components/inlineQueryResults/InlineQueryResultVideo.qml
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
|
||||
InlineQueryResultAnimation {
|
||||
isAnimation: false
|
||||
animationKey: "video"
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
|
||||
InlineQueryResultAudio {
|
||||
|
||||
}
|
27
qml/components/messageContent/MessageAnimatedEmoji.qml
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../"
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
MessageSticker {
|
||||
stickerData: messageListItem ? messageListItem.myMessage.content.animated_emoji.sticker : overlayFlickable.overlayMessage.content.animated_emoji.sticker;
|
||||
}
|
21
qml/components/messageContent/MessageAnimation.qml
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
|
||||
MessageVideo {}
|
96
qml/components/messageContent/MessageAudio.qml
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import QtMultimedia 5.6
|
||||
import "../"
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
import "../../js/functions.js" as Functions
|
||||
import "../../js/debug.js" as Debug
|
||||
|
||||
|
||||
MessageContentFileInfoBase {
|
||||
id: contentItem
|
||||
|
||||
fileInformation: rawMessage.content.audio.audio
|
||||
thumbnail: rawMessage.content.audio.album_cover_thumbnail
|
||||
minithumbnail: rawMessage.content.audio.album_cover_minithumbnail
|
||||
|
||||
primaryText: Emoji.emojify(rawMessage.content.audio.performer, primaryLabel.font.pixelSize)
|
||||
secondaryText: Emoji.emojify(rawMessage.content.audio.title, secondaryLabel.font.pixelSize)
|
||||
tertiaryLabel.visible: (duration || (audioPlayer.duration/1000)) > 0
|
||||
tertiaryText: (audioPlayer.position > 0 || audioPlayer.playbackState === Audio.PlayingState ? (Format.formatDuration(audioPlayer.position/1000, Formatter.DurationShort)+" / ") : "") + Format.formatDuration(contentItem.duration > 0 ? contentItem.duration : (audioPlayer.duration/1000), Formatter.DurationShort)
|
||||
|
||||
leftButton {
|
||||
icon.source: audioPlayer.playbackState === Audio.PlayingState || (file.isDownloadingActive && audioPlayer.autoPlay) ? "image://theme/icon-m-pause": "image://theme/icon-m-play"
|
||||
onClicked: {
|
||||
if(!file.isDownloadingCompleted && !file.isDownloadingActive) {
|
||||
file.load();
|
||||
audioPlayer.autoPlay = true;
|
||||
} else if(file.isDownloadingActive) {
|
||||
audioPlayer.autoPlay = false;
|
||||
file.cancel();
|
||||
} else if(file.isDownloadingCompleted) {
|
||||
//playPause
|
||||
if(audioPlayer.playbackState === Audio.PlayingState) {
|
||||
audioPlayer.pause();
|
||||
} else {
|
||||
audioPlayer.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
property int duration: rawMessage.content.audio.duration
|
||||
|
||||
Audio {
|
||||
id: audioPlayer
|
||||
source: file.isDownloadingCompleted ? file.path : ""
|
||||
autoPlay: false
|
||||
}
|
||||
|
||||
Slider {
|
||||
width: parent.width
|
||||
anchors {
|
||||
left: parent.left
|
||||
leftMargin: -Screen.width/16
|
||||
right: parent.right
|
||||
rightMargin: -Screen.width/16
|
||||
top: primaryItem.bottom
|
||||
topMargin: -height/3
|
||||
}
|
||||
minimumValue: 0
|
||||
maximumValue: audioPlayer.duration ? audioPlayer.duration : 0.1
|
||||
stepSize: 1
|
||||
value: audioPlayer.position
|
||||
enabled: audioPlayer.seekable
|
||||
visible: file.isDownloadingCompleted && audioPlayer.playbackState === Audio.PlayingState || audioPlayer.playbackState === Audio.PausedState
|
||||
opacity: visible ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
height: visible ? implicitHeight : 0
|
||||
Behavior on height { NumberAnimation { duration: 200 } }
|
||||
|
||||
highlighted: contentItem.highlighted || down
|
||||
onReleased: {
|
||||
audioPlayer.seek(Math.floor(value));
|
||||
audioPlayer.play();
|
||||
}
|
||||
}
|
||||
}
|
32
qml/components/messageContent/MessageContentBase.qml
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import QtMultimedia 5.6
|
||||
import "../"
|
||||
import "../../js/functions.js" as Functions
|
||||
import "../../js/debug.js" as Debug
|
||||
|
||||
Item {
|
||||
property ListItem messageListItem
|
||||
property MessageOverlayFlickable overlayFlickable
|
||||
property var rawMessage: messageListItem ? messageListItem.myMessage : overlayFlickable.overlayMessage
|
||||
property bool highlighted
|
||||
signal clicked()
|
||||
}
|
201
qml/components/messageContent/MessageContentFileInfoBase.qml
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import QtMultimedia 5.6
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import QtGraphicalEffects 1.0
|
||||
import "../"
|
||||
import "../../js/functions.js" as Functions
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
import "../../js/debug.js" as Debug
|
||||
|
||||
MessageContentBase {
|
||||
id: contentItem
|
||||
height: childrenRect.height
|
||||
property alias fileInformation: file.fileInformation
|
||||
property alias primaryLabel: primaryLabel
|
||||
property alias primaryText: primaryLabel.text
|
||||
property alias secondaryLabel: secondaryLabel
|
||||
property alias secondaryText: secondaryLabel.text
|
||||
property alias tertiaryLabel: tertiaryLabel
|
||||
property alias tertiaryText: tertiaryLabel.text
|
||||
property var thumbnail
|
||||
property var minithumbnail
|
||||
|
||||
readonly property alias file: file
|
||||
readonly property alias primaryItem: primaryItem
|
||||
readonly property alias leftButton: leftButton
|
||||
readonly property alias labelsColumn: labelsColumn
|
||||
readonly property alias copyButton: copyButton
|
||||
// readonly property alias downloadNeededIndicatorIcon: downloadNeededIndicatorIcon
|
||||
|
||||
TDLibFile {
|
||||
id: file
|
||||
tdlib: tdLibWrapper
|
||||
autoLoad: false
|
||||
}
|
||||
|
||||
Item {
|
||||
id: primaryItem
|
||||
width: parent.width
|
||||
height: Theme.itemSizeLarge
|
||||
Loader {
|
||||
active: contentItem.thumbnail || contentItem.minithumbnail
|
||||
visible: active
|
||||
anchors.fill: leftButton
|
||||
sourceComponent: Component {
|
||||
TDLibThumbnail {
|
||||
opacity: 0.3
|
||||
thumbnail: contentItem.thumbnail
|
||||
minithumbnail: contentItem.minithumbnail
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: leftButton
|
||||
highlighted: down || contentItem.highlighted
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
icon {
|
||||
asynchronous: true
|
||||
}
|
||||
|
||||
ProgressCircle {
|
||||
value: file.downloadedSize / file.expectedSize
|
||||
progressColor: Theme.highlightColor
|
||||
backgroundColor: Theme.highlightDimmerColor
|
||||
width: Theme.iconSizeMedium
|
||||
height: Theme.iconSizeMedium
|
||||
visible: opacity > 0
|
||||
opacity: file.isDownloadingActive ? 1.0 : 0.0
|
||||
anchors.centerIn: parent
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
}
|
||||
Rectangle {
|
||||
anchors.centerIn: downloadNeededIndicatorIcon
|
||||
width: downloadNeededIndicatorIcon.width + Theme.paddingMedium
|
||||
height: width
|
||||
|
||||
color: Theme.rgba(Theme.overlayBackgroundColor, 0.2)
|
||||
opacity: file.isDownloadingActive ? 1.0 : 0.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
visible: opacity > 0
|
||||
radius: width/2
|
||||
}
|
||||
|
||||
Icon {
|
||||
id: downloadNeededIndicatorIcon
|
||||
source: file.isDownloadingActive || file.isDownloadingCompleted ? "image://theme/icon-s-clear-opaque-cross" : "image://theme/icon-s-cloud-download"
|
||||
asynchronous: true
|
||||
width: Theme.iconSizeExtraSmall
|
||||
height: width
|
||||
visible: opacity > 0
|
||||
sourceSize.width: width
|
||||
sourceSize.height: height
|
||||
opacity: file.isDownloadingCompleted ? 0.0 : 1.0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
anchors {
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
margins: Theme.paddingSmall
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: labelsColumn
|
||||
anchors {
|
||||
left: leftButton.right
|
||||
leftMargin: Theme.paddingSmall
|
||||
right: copyButton.left
|
||||
verticalCenter: leftButton.verticalCenter
|
||||
}
|
||||
|
||||
Label {
|
||||
id: primaryLabel
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
fontSizeMode: Text.HorizontalFit
|
||||
minimumPixelSize: Theme.fontSizeTiny
|
||||
color: Theme.highlightColor
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
|
||||
Label {
|
||||
id: secondaryLabel
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
fontSizeMode: Text.HorizontalFit
|
||||
minimumPixelSize: Theme.fontSizeTiny
|
||||
color: Theme.secondaryHighlightColor
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
Item {
|
||||
height: sizeLabel.height
|
||||
width: parent.width
|
||||
Label {
|
||||
id: tertiaryLabel
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: highlighted ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||
visible: text.length > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
Label {
|
||||
id: sizeLabel
|
||||
anchors.right: parent.right
|
||||
font.pixelSize: Theme.fontSizeTiny
|
||||
color: tertiaryLabel.color
|
||||
text: Format.formatFileSize(file.size || file.expectedSize)
|
||||
visible: (file.size || file.expectedSize) > 0
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
}
|
||||
}
|
||||
IconButton {
|
||||
id: copyButton
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
opacity: file.isDownloadingCompleted ? 1.0 : 0.0
|
||||
width: file.isDownloadingCompleted ? Theme.itemSizeMedium : 0
|
||||
visible: opacity > 0
|
||||
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
Behavior on width { NumberAnimation { duration: 200 } }
|
||||
icon {
|
||||
asynchronous: true
|
||||
source: "../../../images/icon-m-copy-to-folder.svg"
|
||||
sourceSize {
|
||||
width: Theme.iconSizeMedium
|
||||
height: Theme.iconSizeMedium
|
||||
}
|
||||
}
|
||||
onClicked: {
|
||||
tdLibWrapper.copyFileToDownloads(file.path);
|
||||
// not persistent:
|
||||
opacity = 0;
|
||||
width = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
82
qml/components/messageContent/MessageDocument.qml
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
MessageContentFileInfoBase {
|
||||
id: contentItem
|
||||
fileInformation: rawMessage.content.document.document
|
||||
|
||||
primaryText: Emoji.emojify(rawMessage.content.document.file_name || "", primaryLabel.font.pixelSize)
|
||||
secondaryText: Emoji.emojify(Functions.enhanceMessageText(rawMessage.content.caption) || "", secondaryLabel.font.pixelSize)
|
||||
|
||||
minithumbnail: rawMessage.content.document.minithumbnail
|
||||
thumbnail: rawMessage.content.document.thumbnail
|
||||
|
||||
leftButton {
|
||||
icon.source: Theme.iconForMimeType(rawMessage.content.document.mime_type)
|
||||
onClicked: {
|
||||
if(file.isDownloadingCompleted) {
|
||||
// in this case, the MouseArea should take over
|
||||
tdLibWrapper.copyFileToDownloads(file.path, true);
|
||||
} else if(!file.isDownloadingActive) {
|
||||
file.load();
|
||||
} else {
|
||||
file.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
when: file.isDownloadingCompleted
|
||||
PropertyChanges { target: openMouseArea; enabled: true }
|
||||
PropertyChanges {
|
||||
target: primaryLabel
|
||||
color: (contentItem.highlighted || openMouseArea.pressed) ? Theme.highlightColor : Theme.primaryColor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: secondaryLabel
|
||||
color: (contentItem.highlighted || openMouseArea.pressed) ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: tertiaryLabel
|
||||
color: (contentItem.highlighted || openMouseArea.pressed) ? Theme.secondaryHighlightColor : Theme.secondaryColor
|
||||
}
|
||||
PropertyChanges {
|
||||
target: leftButton
|
||||
highlighted: contentItem.highlighted || openMouseArea.pressed
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
MouseArea {
|
||||
id: openMouseArea
|
||||
enabled: file.isDownloadingCompleted
|
||||
visible: enabled
|
||||
anchors {
|
||||
fill: primaryItem
|
||||
rightMargin: copyButton.width
|
||||
}
|
||||
onClicked: {
|
||||
tdLibWrapper.copyFileToDownloads(file.path, true);
|
||||
}
|
||||
}
|
||||
}
|
128
qml/components/messageContent/MessageGame.qml
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../"
|
||||
import "../../js/functions.js" as Functions
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
|
||||
MessageContentBase {
|
||||
id: messageContent
|
||||
height: gamePreviewItem.height
|
||||
|
||||
Column {
|
||||
id: gamePreviewItem
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
font.bold: true
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
text: Emoji.emojify(rawMessage.content.game.title || "", font.pixelSize)
|
||||
truncationMode: TruncationMode.Fade
|
||||
textFormat: Text.StyledText
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
Label {
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
text: Emoji.emojify(rawMessage.content.game.description || "", font.pixelSize)
|
||||
truncationMode: TruncationMode.Fade
|
||||
textFormat: Text.StyledText
|
||||
wrapMode: Text.Wrap
|
||||
}
|
||||
Label {
|
||||
width: parent.width
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
text: Emoji.emojify(Functions.enhanceMessageText(rawMessage.content.game.text) || "", font.pixelSize)
|
||||
truncationMode: TruncationMode.Fade
|
||||
wrapMode: Text.Wrap
|
||||
textFormat: Text.StyledText
|
||||
onLinkActivated: {
|
||||
var chatCommand = Functions.handleLink(link);
|
||||
if(chatCommand) {
|
||||
tdLibWrapper.sendTextMessage(chatInformation.id, chatCommand);
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
width: parent.width
|
||||
height: Theme.paddingLarge
|
||||
}
|
||||
|
||||
Image {
|
||||
id: thumbnail
|
||||
source: thumbnailFile.isDownloadingCompleted ? thumbnailFile.path : ""
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
asynchronous: true
|
||||
visible: opacity > 0
|
||||
opacity: status === Image.Ready ? 1.0 : 0.0
|
||||
width: parent.width
|
||||
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
layer.enabled: messageContent.highlighted
|
||||
layer.effect: PressEffect { source: thumbnail }
|
||||
|
||||
TDLibFile {
|
||||
id: thumbnailFile
|
||||
tdlib: tdLibWrapper
|
||||
autoLoad: true
|
||||
}
|
||||
Rectangle {
|
||||
width: Theme.iconSizeMedium
|
||||
height: width
|
||||
anchors {
|
||||
top: parent.top
|
||||
topMargin: Theme.paddingSmall
|
||||
left: parent.left
|
||||
leftMargin: Theme.paddingSmall
|
||||
}
|
||||
|
||||
color: Theme.rgba(Theme.overlayBackgroundColor, 0.2)
|
||||
radius: Theme.paddingSmall
|
||||
Icon {
|
||||
id: icon
|
||||
source: "image://theme/icon-m-game-controller"
|
||||
asynchronous: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (rawMessage.content.game.photo) {
|
||||
// Check first which size fits best...
|
||||
var photo
|
||||
for (var i = 0; i < rawMessage.content.game.photo.sizes.length; i++) {
|
||||
photo = rawMessage.content.game.photo.sizes[i].photo
|
||||
if (rawMessage.content.game.photo.sizes[i].width >= gamePreviewItem.width) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if (photo) {
|
||||
thumbnailFile.fileInformation = photo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
91
qml/components/messageContent/MessageLocation.qml
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import QtGraphicalEffects 1.0
|
||||
import Sailfish.Silica 1.0
|
||||
import "../"
|
||||
|
||||
MessageContentBase {
|
||||
id: contentItem
|
||||
height: width * 0.66666666;
|
||||
|
||||
property var locationData : rawMessage.content.location
|
||||
property string fileExtra;
|
||||
|
||||
onClicked: {
|
||||
Qt.openUrlExternally("geo:" + locationData.latitude + "," + locationData.longitude);
|
||||
}
|
||||
onLocationDataChanged: updatePicture()
|
||||
onWidthChanged: updatePicture()
|
||||
|
||||
function updatePicture() {
|
||||
if (locationData) {
|
||||
fileExtra = "location:" + locationData.latitude + ":" + locationData.longitude + ":" + Math.round(contentItem.width) + ":" + Math.round(contentItem.height);
|
||||
tdLibWrapper.getMapThumbnailFile(rawMessage.chat_id, locationData.latitude, locationData.longitude, Math.round(contentItem.width), Math.round(contentItem.height), fileExtra);
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onFileUpdated: {
|
||||
if(fileInformation["@extra"] === contentItem.fileExtra) {
|
||||
if(fileInformation.id !== image.file.fileId) {
|
||||
image.fileInformation = fileInformation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AppNotification {
|
||||
id: imageNotification
|
||||
}
|
||||
TDLibImage {
|
||||
id: image
|
||||
anchors.fill: parent
|
||||
cache: false
|
||||
highlighted: contentItem.highlighted
|
||||
Item {
|
||||
anchors.centerIn: parent
|
||||
width: markerImage.width
|
||||
height: markerImage.height * 1.75 // 0.875 (vertical pin point) * 2
|
||||
Icon {
|
||||
id: markerImage
|
||||
source: 'image://theme/icon-m-location'
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
anchors.fill: markerImage
|
||||
horizontalOffset: 3
|
||||
verticalOffset: 3
|
||||
radius: 8.0
|
||||
samples: 17
|
||||
color: Theme.colorScheme ? Theme.lightPrimaryColor : Theme.darkPrimaryColor
|
||||
source: markerImage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BackgroundImage {
|
||||
visible: image.status !== Image.Ready
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
updatePicture();
|
||||
}
|
||||
}
|
57
qml/components/messageContent/MessagePhoto.qml
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "../"
|
||||
|
||||
MessageContentBase {
|
||||
|
||||
function calculateBiggest() {
|
||||
var candidateBiggest = rawMessage.content.photo.sizes[rawMessage.content.photo.sizes.length - 1];
|
||||
if (candidateBiggest.width === 0 && rawMessage.content.photo.sizes.length > 1) {
|
||||
for (var i = (rawMessage.content.photo.sizes.length - 2); i >= 0; i--) {
|
||||
candidateBiggest = rawMessage.content.photo.sizes[i];
|
||||
if (candidateBiggest.width > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return candidateBiggest;
|
||||
}
|
||||
|
||||
height: Math.max(Theme.itemSizeExtraSmall, Math.min(defaultHeight, width / (biggest.width/biggest.height)))
|
||||
readonly property int defaultHeight: Math.round(width * 0.66666666)
|
||||
readonly property var biggest: calculateBiggest();
|
||||
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("../../pages/ImagePage.qml"), {
|
||||
"photoData" : photo.photo,
|
||||
// "pictureFileInformation" : photo.fileInformation
|
||||
})
|
||||
}
|
||||
TDLibPhoto {
|
||||
id: photo
|
||||
anchors.fill: parent
|
||||
photo: rawMessage.content.photo
|
||||
highlighted: parent.highlighted
|
||||
}
|
||||
BackgroundImage {
|
||||
visible: !rawMessage.content.photo.minithumbnail && photo.image.status !== Image.Ready
|
||||
}
|
||||
}
|
|
@ -21,15 +21,13 @@ import QtQuick 2.6
|
|||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
|
||||
import "../js/functions.js" as Functions
|
||||
import "../js/twemoji.js" as Emoji
|
||||
import "../../js/functions.js" as Functions
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
Item {
|
||||
MessageContentBase {
|
||||
id: pollMessageComponent
|
||||
height: pollColumn.height
|
||||
|
||||
property ListItem messageListItem
|
||||
property MessageOverlayFlickable overlayFlickable
|
||||
readonly property var rawMessage: messageListItem ? messageListItem.myMessage : overlayFlickable.overlayMessage
|
||||
readonly property string chatId: rawMessage.chat_id
|
||||
readonly property bool isOwnMessage: messageListItem ? messageListItem.isOwnMessage : overlayFlickable.isOwnMessage
|
||||
readonly property string messageId: rawMessage.id
|
||||
|
@ -44,9 +42,6 @@ Item {
|
|||
}
|
||||
readonly property bool canAnswer: !hasAnswered && !pollData.is_closed
|
||||
readonly property bool isQuiz: pollData.type['@type'] === "pollTypeQuiz"
|
||||
property bool highlighted
|
||||
width: parent.width
|
||||
height: pollColumn.height
|
||||
property list<NamedAction> extraContextMenuItems: [
|
||||
NamedAction {
|
||||
visible: !pollData.is_closed && pollMessageComponent.canEdit
|
||||
|
@ -235,6 +230,24 @@ Item {
|
|||
width: 1
|
||||
height: Theme.paddingSmall
|
||||
}
|
||||
Label {
|
||||
width: parent.width
|
||||
wrapMode: Text.Wrap
|
||||
visible: isQuiz && text.length > 0
|
||||
text: Emoji.emojify(Functions.enhanceMessageText(pollData.type.explanation) || "", font.pixelSize)
|
||||
textFormat: Text.StyledText
|
||||
color: pollMessageComponent.isOwnMessage || pollMessageComponent.highlighted ? Theme.highlightColor : Theme.primaryColor
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
leftPadding: Theme.iconSizeSmall
|
||||
bottomPadding: Theme.paddingSmall
|
||||
Icon {
|
||||
source: "image://theme/icon-s-high-importance"
|
||||
asynchronous: true
|
||||
width: Theme.iconSizeExtraSmall
|
||||
height: Theme.iconSizeExtraSmall
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
x: -Theme.horizontalPageMargin/2
|
||||
|
@ -264,7 +277,7 @@ Item {
|
|||
visible: !pollMessageComponent.canAnswer && !pollData.is_anonymous && pollData.total_voter_count > 0
|
||||
icon.source: "image://theme/icon-m-media-artists"
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("../pages/PollResultsPage.qml"), { chatId:chatId, message:pollMessageComponent.message});
|
||||
pageStack.push(Qt.resolvedUrl("../../pages/PollResultsPage.qml"), { chatId:chatId, message:pollMessageComponent.rawMessage});
|
||||
}
|
||||
Icon {
|
||||
opacity: 0.8
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
|
@ -19,25 +19,23 @@
|
|||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../"
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
|
||||
Item {
|
||||
property ListItem messageListItem
|
||||
property MessageOverlayFlickable overlayFlickable
|
||||
MessageContentBase {
|
||||
id: thisItem
|
||||
|
||||
readonly property var stickerData: messageListItem ? messageListItem.myMessage.content.sticker : overlayFlickable.overlayMessage.content.sticker;
|
||||
readonly property bool animated: stickerData.is_animated && appSettings.animateStickers
|
||||
property var stickerData: messageListItem ? messageListItem.myMessage.content.sticker : overlayFlickable.overlayMessage.content.sticker;
|
||||
readonly property bool asEmoji: appSettings.showStickersAsEmojis
|
||||
readonly property bool animated: stickerData.format["@type"] === "stickerFormatTgs" && appSettings.animateStickers
|
||||
readonly property bool stickerVisible: staticStickerLoader.item ? staticStickerLoader.item.visible :
|
||||
animatedStickerLoader.item ? animatedStickerLoader.item.visible : false
|
||||
readonly property bool isOwnSticker : messageListItem ? messageListItem.isOwnMessage : overlayFlickable.isOwnMessage
|
||||
property real aspectRatio: stickerData.width / stickerData.height
|
||||
property bool highlighted
|
||||
readonly property real aspectRatio: stickerData.width / stickerData.height
|
||||
|
||||
implicitWidth: stickerData.width
|
||||
implicitHeight: stickerData.height
|
||||
|
||||
layer.enabled: highlighted
|
||||
layer.effect: PressEffect { source: singleImage }
|
||||
|
||||
TDLibFile {
|
||||
id: file
|
||||
tdlib: tdLibWrapper
|
||||
|
@ -46,6 +44,7 @@ Item {
|
|||
}
|
||||
|
||||
Item {
|
||||
|
||||
width: Math.min( stickerData.width, parent.width )
|
||||
height: width * aspectRatio
|
||||
// (centered in image mode, text-like in sticker mode)
|
||||
|
@ -56,14 +55,17 @@ Item {
|
|||
Loader {
|
||||
id: animatedStickerLoader
|
||||
anchors.fill: parent
|
||||
active: animated
|
||||
active: animated && !asEmoji
|
||||
sourceComponent: Component {
|
||||
AnimatedImage {
|
||||
id: animatedSticker
|
||||
anchors.fill: parent
|
||||
source: file.path
|
||||
asynchronous: true
|
||||
paused: !Qt.application.active
|
||||
cache: false
|
||||
layer.enabled: thisItem.highlighted
|
||||
layer.effect: PressEffect { source: animatedSticker }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,17 +73,24 @@ Item {
|
|||
Loader {
|
||||
id: staticStickerLoader
|
||||
anchors.fill: parent
|
||||
active: !animated
|
||||
active: !animated || asEmoji
|
||||
sourceComponent: Component {
|
||||
Image {
|
||||
id: staticSticker
|
||||
anchors.fill: parent
|
||||
source: file.path
|
||||
source: asEmoji ? Emoji.getEmojiPath(stickerData.emoji) : file.path
|
||||
sourceSize {
|
||||
width: width
|
||||
height: height
|
||||
}
|
||||
fillMode: Image.PreserveAspectFit
|
||||
autoTransform: true
|
||||
asynchronous: true
|
||||
visible: opacity > 0
|
||||
opacity: status === Image.Ready ? 1 : 0
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
layer.enabled: thisItem.highlighted
|
||||
layer.effect: PressEffect { source: staticSticker }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +107,11 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
stickerSetOverlayLoader.stickerSetId = stickerData.set_id
|
||||
stickerSetOverlayLoader.active = true
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: placeHolderDelayTimer
|
||||
interval: 1000
|
24
qml/components/messageContent/MessageVenue.qml
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
|
||||
MessageLocation {
|
||||
locationData: rawMessage.content.venue.location
|
||||
}
|
|
@ -19,16 +19,13 @@
|
|||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import QtMultimedia 5.6
|
||||
import "../js/functions.js" as Functions
|
||||
import "../js/debug.js" as Debug
|
||||
import "../"
|
||||
import "../../js/functions.js" as Functions
|
||||
import "../../js/debug.js" as Debug
|
||||
|
||||
Item {
|
||||
MessageContentBase {
|
||||
id: videoMessageComponent
|
||||
|
||||
property ListItem messageListItem
|
||||
property MessageOverlayFlickable overlayFlickable
|
||||
property var rawMessage: messageListItem ? messageListItem.myMessage : overlayFlickable.overlayMessage
|
||||
|
||||
property var videoData: ( rawMessage.content['@type'] === "messageVideo" ) ? rawMessage.content.video : ( ( rawMessage.content['@type'] === "messageAnimation" ) ? rawMessage.content.animation : rawMessage.content.video_note )
|
||||
property string videoUrl;
|
||||
property int previewFileId;
|
||||
|
@ -38,10 +35,7 @@ Item {
|
|||
property bool onScreen: messageListItem ? messageListItem.page.status === PageStatus.Active : true;
|
||||
property string videoType : "video";
|
||||
property bool playRequested: false;
|
||||
property bool highlighted;
|
||||
signal clicked();
|
||||
|
||||
width: parent.width
|
||||
height: videoMessageComponent.isVideoNote ? width : Functions.getVideoHeight(width, videoData)
|
||||
|
||||
Timer {
|
||||
|
@ -89,15 +83,19 @@ Item {
|
|||
|
||||
videoMessageComponent.videoType = videoMessageComponent.isVideoNote ? "video" : videoData['@type'];
|
||||
videoFileId = videoData[videoType].id;
|
||||
if (typeof videoData.thumbnail !== "undefined") {
|
||||
previewFileId = videoData.thumbnail.photo.id;
|
||||
if (videoData.thumbnail.photo.local.is_downloading_completed) {
|
||||
placeholderImage.source = videoData.thumbnail.photo.local.path;
|
||||
if (typeof rawMessage !== "undefined" && rawMessage.content['@type'] === "messageAnimation") {
|
||||
playButton.visible = true;
|
||||
fullscreenButton.visible = !videoMessageComponent.fullscreen;
|
||||
handlePlay();
|
||||
} else if (typeof videoData.thumbnail !== "undefined") {
|
||||
previewFileId = videoData.thumbnail.file.id;
|
||||
if (videoData.thumbnail.file.local.is_downloading_completed) {
|
||||
placeholderImage.source = videoData.thumbnail.file.local.path;
|
||||
} else {
|
||||
tdLibWrapper.downloadFile(previewFileId);
|
||||
}
|
||||
} else {
|
||||
placeholderImage.source = "image://theme/icon-l-video?white";
|
||||
placeholderImage.source = "image://theme/icon-m-video?white";
|
||||
placeholderImage.width = Theme.itemSizeLarge
|
||||
placeholderImage.height = Theme.itemSizeLarge
|
||||
}
|
||||
|
@ -149,7 +147,7 @@ Item {
|
|||
asynchronous: true
|
||||
visible: status === Image.Ready ? true : false
|
||||
layer.enabled: videoMessageComponent.highlighted
|
||||
layer.effect: PressEffect { source: singleImage }
|
||||
layer.effect: PressEffect { source: placeholderImage }
|
||||
}
|
||||
|
||||
BackgroundImage {
|
||||
|
@ -157,7 +155,6 @@ Item {
|
|||
}
|
||||
|
||||
Rectangle {
|
||||
id: placeholderBackground
|
||||
color: "black"
|
||||
opacity: 0.3
|
||||
height: parent.height
|
||||
|
@ -212,7 +209,7 @@ Item {
|
|||
height: Theme.iconSizeLarge
|
||||
icon {
|
||||
asynchronous: true
|
||||
source: "../../images/icon-l-fullscreen.svg"
|
||||
source: "../../../images/icon-l-fullscreen.svg"
|
||||
sourceSize {
|
||||
width: Theme.iconSizeLarge
|
||||
height: Theme.iconSizeLarge
|
||||
|
@ -221,7 +218,7 @@ Item {
|
|||
highlighted: videoMessageComponent.highlighted || down
|
||||
visible: ( placeholderImage.status === Image.Ready && !videoMessageComponent.fullscreen ) ? true : false
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("../pages/VideoPage.qml"), {"videoData": videoData});
|
||||
pageStack.push(Qt.resolvedUrl("../../pages/VideoPage.qml"), {"videoData": videoData, "sourceMessage": rawMessage});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -237,7 +234,6 @@ Item {
|
|||
}
|
||||
|
||||
Rectangle {
|
||||
id: videoErrorShade
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
color: "lightgrey"
|
||||
|
@ -292,21 +288,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: videoMessageComponent
|
||||
onClicked: {
|
||||
if (messageVideo.playbackState === MediaPlayer.PlayingState) {
|
||||
enableScreensaver();
|
||||
messageVideo.pause();
|
||||
timeLeftItem.visible = true;
|
||||
} else {
|
||||
disableScreensaver();
|
||||
messageVideo.play();
|
||||
timeLeftTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Video {
|
||||
id: messageVideo
|
||||
|
||||
|
@ -365,7 +346,7 @@ Item {
|
|||
height: parent.height
|
||||
source: videoUrl
|
||||
layer.enabled: videoMessageComponent.highlighted
|
||||
layer.effect: PressEffect { source: singleImage }
|
||||
layer.effect: PressEffect { source: messageVideo }
|
||||
onStopped: {
|
||||
enableScreensaver();
|
||||
messageVideo.visible = false;
|
||||
|
@ -374,6 +355,21 @@ Item {
|
|||
videoComponentLoader.active = false;
|
||||
fullscreenItem.visible = !videoMessageComponent.fullscreen;
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
if (messageVideo.playbackState === MediaPlayer.PlayingState) {
|
||||
enableScreensaver();
|
||||
messageVideo.pause();
|
||||
timeLeftItem.visible = true;
|
||||
} else {
|
||||
disableScreensaver();
|
||||
messageVideo.play();
|
||||
timeLeftTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
|
@ -460,7 +456,7 @@ Item {
|
|||
highlighted: videoMessageComponent.highlighted || down
|
||||
icon {
|
||||
asynchronous: true
|
||||
source: "../../images/icon-l-fullscreen.svg"
|
||||
source: "../../../images/icon-l-fullscreen.svg"
|
||||
sourceSize {
|
||||
width: Theme.iconSizeLarge
|
||||
height: Theme.iconSizeLarge
|
||||
|
@ -468,7 +464,7 @@ Item {
|
|||
}
|
||||
visible: ( videoComponentLoader.active && messageVideo.playbackState === MediaPlayer.PausedState ) ? true : false
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("../pages/VideoPage.qml"), {"videoData": videoData});
|
||||
pageStack.push(Qt.resolvedUrl("../../pages/VideoPage.qml"), {"videoData": videoData, "sourceMessage": rawMessage});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -480,7 +476,7 @@ Item {
|
|||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: positionText.top
|
||||
minimumValue: 0
|
||||
maximumValue: messageVideo.duration ? messageVideo.duration : 0
|
||||
maximumValue: messageVideo.duration ? messageVideo.duration : 0.1
|
||||
|
||||
highlighted: videoMessageComponent.highlighted || down
|
||||
stepSize: 1
|
||||
|
@ -512,7 +508,6 @@ Item {
|
|||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
21
qml/components/messageContent/MessageVideoNote.qml
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
|
||||
MessageVideo {}
|
28
qml/components/messageContent/MessageVoiceNote.qml
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2020 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
|
||||
MessageAudio {
|
||||
fileInformation: rawMessage.content.voice_note.voice
|
||||
primaryText: qsTr("Voice Note")
|
||||
secondaryText: ""
|
||||
duration: rawMessage.content.voice_note.duration
|
||||
thumbnail: null
|
||||
minithumbnail: null
|
||||
}
|
77
qml/components/messageContent/SponsoredMessage.qml
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Copyright (C) 2021 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import QtQuick 2.6
|
||||
import QtGraphicalEffects 1.0
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../"
|
||||
import "../../js/functions.js" as Functions
|
||||
|
||||
Column {
|
||||
id: sponsoredMessageColumn
|
||||
|
||||
property var sponsoredMessageData;
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onMessageLinkInfoReceived: {
|
||||
if (sponsoredMessageData.link.url === url) {
|
||||
messageOverlayLoader.overlayMessage = messageLinkInfo.message;
|
||||
messageOverlayLoader.active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (sponsoredMessageData) {
|
||||
if (typeof sponsoredMessageData.link === "undefined") {
|
||||
sponsoredMessageButton.text = qsTr("Go to Channel");
|
||||
sponsoredMessageButton.advertisesChannel = true;
|
||||
} else if (sponsoredMessageData.link['@type'] === "internalLinkTypeMessage") {
|
||||
sponsoredMessageButton.text = qsTr("Go to Message");
|
||||
sponsoredMessageButton.advertisesMessage = true;
|
||||
} else {
|
||||
sponsoredMessageButton.text = qsTr("Start Bot");
|
||||
sponsoredMessageButton.advertisesBot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: sponsoredMessageButton
|
||||
property bool advertisesChannel: false;
|
||||
property bool advertisesMessage: false;
|
||||
property bool advertisesBot: false;
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
onClicked: {
|
||||
if (advertisesChannel) {
|
||||
tdLibWrapper.createSupergroupChat(tdLibWrapper.getChat(sponsoredMessageData.sponsor_chat_id).type.supergroup_id, "openDirectly");
|
||||
}
|
||||
if (advertisesMessage) {
|
||||
tdLibWrapper.getMessageLinkInfo(sponsoredMessageData.link.url);
|
||||
}
|
||||
if (advertisesBot) {
|
||||
tdLibWrapper.createPrivateChat(tdLibWrapper.getUserInformationByName(sponsoredMessageData.link.bot_username).id, "openAndSendStartToBot:" + sponsoredMessageData.link.start_parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -19,97 +19,92 @@
|
|||
import QtQuick 2.6
|
||||
import QtGraphicalEffects 1.0
|
||||
import Sailfish.Silica 1.0
|
||||
import "../components"
|
||||
import "../js/twemoji.js" as Emoji
|
||||
import "../js/functions.js" as Functions
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../"
|
||||
import "../../js/functions.js" as Functions
|
||||
|
||||
Column {
|
||||
|
||||
id: webPagePreviewColumn
|
||||
|
||||
property var webPageData;
|
||||
property var pictureFileInformation;
|
||||
property bool hasImage: false;
|
||||
property bool largerFontSize: false;
|
||||
property bool highlighted
|
||||
readonly property bool hasImage: picture.fileId !== 0
|
||||
readonly property int fontSize: largerFontSize ? Theme.fontSizeSmall : Theme.fontSizeExtraSmall
|
||||
|
||||
spacing: Theme.paddingSmall
|
||||
|
||||
Component.onCompleted: {
|
||||
updateWebPage();
|
||||
}
|
||||
Component.onCompleted: updatePhoto()
|
||||
|
||||
function updateWebPage() {
|
||||
onWebPageDataChanged: updatePhoto()
|
||||
|
||||
function updatePhoto() {
|
||||
if (webPageData) {
|
||||
if (typeof webPageData.photo !== "undefined") {
|
||||
hasImage = true;
|
||||
if (webPageData.photo) {
|
||||
// Check first which size fits best...
|
||||
var photo
|
||||
for (var i = 0; i < webPageData.photo.sizes.length; i++) {
|
||||
pictureFileInformation = webPageData.photo.sizes[i].photo;
|
||||
photo = webPageData.photo.sizes[i].photo;
|
||||
if (webPageData.photo.sizes[i].width >= webPagePreviewColumn.width) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pictureFileInformation.local.is_downloading_completed) {
|
||||
singleImage.source = pictureFileInformation.local.path;
|
||||
} else {
|
||||
tdLibWrapper.downloadFile(pictureFileInformation.id);
|
||||
if (photo) {
|
||||
picture.fileInformation = photo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onFileUpdated: {
|
||||
if (typeof pictureFileInformation !== "undefined" && fileId === pictureFileInformation.id) {
|
||||
if (fileInformation.local.is_downloading_completed) {
|
||||
pictureFileInformation = fileInformation;
|
||||
singleImage.source = fileInformation.local.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
function clicked() {
|
||||
descriptionText.toggleMaxLineCount()
|
||||
}
|
||||
|
||||
Label {
|
||||
TDLibFile {
|
||||
id: picture
|
||||
tdlib: tdLibWrapper
|
||||
autoLoad: true
|
||||
}
|
||||
|
||||
MultilineEmojiLabel {
|
||||
id: siteNameText
|
||||
|
||||
width: parent.width
|
||||
text: webPageData.site_name ? Emoji.emojify(webPageData.site_name, font.pixelSize) : ""
|
||||
font.pixelSize: webPagePreviewColumn.largerFontSize ? Theme.fontSizeSmall : Theme.fontSizeExtraSmall
|
||||
rawText: webPageData.site_name ? webPageData.site_name : ""
|
||||
font.pixelSize: webPagePreviewColumn.fontSize
|
||||
font.bold: true
|
||||
color: Theme.secondaryHighlightColor
|
||||
truncationMode: TruncationMode.Fade
|
||||
maximumLineCount: 1
|
||||
textFormat: Text.StyledText
|
||||
visible: (text !== "")
|
||||
visible: (rawText !== "")
|
||||
maxLineCount: 1
|
||||
}
|
||||
|
||||
Label {
|
||||
MultilineEmojiLabel {
|
||||
id: titleText
|
||||
|
||||
width: parent.width
|
||||
text: webPageData.title ? Emoji.emojify(webPageData.title, font.pixelSize) : ""
|
||||
font.pixelSize: webPagePreviewColumn.largerFontSize ? Theme.fontSizeSmall : Theme.fontSizeExtraSmall
|
||||
rawText: webPageData.title ? webPageData.title : ""
|
||||
font.pixelSize: webPagePreviewColumn.fontSize
|
||||
font.bold: true
|
||||
truncationMode: TruncationMode.Fade
|
||||
wrapMode: Text.Wrap
|
||||
maximumLineCount: 2
|
||||
textFormat: Text.StyledText
|
||||
visible: (text !== "")
|
||||
visible: (rawText !== "")
|
||||
maxLineCount: 2
|
||||
}
|
||||
|
||||
Label {
|
||||
MultilineEmojiLabel {
|
||||
id: descriptionText
|
||||
|
||||
width: parent.width
|
||||
text: webPageData.description ? Emoji.emojify(webPageData.description, font.pixelSize) : ""
|
||||
font.pixelSize: webPagePreviewColumn.largerFontSize ? Theme.fontSizeSmall : Theme.fontSizeExtraSmall
|
||||
truncationMode: TruncationMode.Fade
|
||||
wrapMode: Text.Wrap
|
||||
maximumLineCount: 3
|
||||
textFormat: Text.StyledText
|
||||
visible: (text !== "")
|
||||
rawText: webPageData.description ? Functions.enhanceMessageText(webPageData.description) : ""
|
||||
font.pixelSize: webPagePreviewColumn.fontSize
|
||||
visible: (rawText !== "")
|
||||
readonly property int defaultMaxLineCount: 3
|
||||
maxLineCount: defaultMaxLineCount
|
||||
linkColor: Theme.highlightColor
|
||||
onLinkActivated: {
|
||||
Functions.handleLink(link);
|
||||
}
|
||||
function toggleMaxLineCount() {
|
||||
maxLineCount = maxLineCount > 0 ? 0 : defaultMaxLineCount
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
|
@ -129,38 +124,35 @@ Column {
|
|||
fillMode: Image.PreserveAspectCrop
|
||||
autoTransform: true
|
||||
asynchronous: true
|
||||
visible: hasImage && status === Image.Ready
|
||||
source: picture.isDownloadingCompleted ? picture.path : ""
|
||||
visible: opacity > 0
|
||||
opacity: hasImage && status === Image.Ready ? 1 : 0
|
||||
layer.enabled: webPagePreviewColumn.highlighted
|
||||
layer.effect: PressEffect { source: singleImage }
|
||||
Behavior on opacity { NumberAnimation {} }
|
||||
Behavior on opacity { FadeAnimation {} }
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
pageStack.push(Qt.resolvedUrl("../pages/ImagePage.qml"), { "photoData" : webPageData.photo, "pictureFileInformation" : pictureFileInformation });
|
||||
pageStack.push(Qt.resolvedUrl("../../pages/ImagePage.qml"), { "photoData" : webPageData.photo, "pictureFileInformation" : picture.fileInformation });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BackgroundImage {
|
||||
id: backgroundImage
|
||||
visible: hasImage && singleImage.status !== Image.Ready
|
||||
layer.enabled: webPagePreviewColumn.highlighted
|
||||
layer.effect: PressEffect { source: singleImage }
|
||||
layer.effect: PressEffect { source: backgroundImage }
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
id: noPreviewAvailableText
|
||||
|
||||
width: parent.width
|
||||
text: qsTr("Preview not supported for this link...")
|
||||
font.pixelSize: webPagePreviewColumn.largerFontSize ? Theme.fontSizeExtraSmall : Theme.fontSizeTiny
|
||||
font.italic: true
|
||||
color: Theme.secondaryColor
|
||||
truncationMode: TruncationMode.Fade
|
||||
wrapMode: Text.Wrap
|
||||
maximumLineCount: 1
|
||||
textFormat: Text.StyledText
|
||||
visible: !siteNameText.visible && !titleText.visible && !descriptionText.visible && !webPagePreviewImageItem.visible
|
||||
}
|
||||
|
42
qml/components/settingsPage/Accordion.qml
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
Copyright (C) 2021 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
property SilicaFlickable flickable
|
||||
property bool animate: false
|
||||
signal setActiveArea(string activeAreaTitle)
|
||||
function scrollUpFlickable(amount) {
|
||||
if(flickable) {
|
||||
flickableAnimation.to = Math.max(0, flickable.contentY - amount);
|
||||
flickableAnimation.start()
|
||||
}
|
||||
}
|
||||
|
||||
NumberAnimation {
|
||||
id: flickableAnimation
|
||||
target: flickable
|
||||
property: "contentY"
|
||||
duration: 200
|
||||
}
|
||||
}
|
106
qml/components/settingsPage/AccordionItem.qml
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
Copyright (C) 2021 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
Item {
|
||||
id: area
|
||||
width: parent.width
|
||||
height: button.height + content.height
|
||||
property alias icon: image
|
||||
property alias text: label.text
|
||||
property alias asynchronous: content.asynchronous
|
||||
property bool expanded: false
|
||||
default property alias els: content.sourceComponent
|
||||
states: [
|
||||
State {
|
||||
when: area.expanded
|
||||
PropertyChanges { target: image; rotation: 90 }
|
||||
PropertyChanges { target: content; height: content.implicitHeight + Theme.paddingLarge; opacity: 1.0 }
|
||||
}
|
||||
]
|
||||
transitions: Transition {
|
||||
to: "*"
|
||||
enabled: area.parent.animate
|
||||
NumberAnimation { target: content; properties: "height, opacity"; duration: 200}
|
||||
NumberAnimation { target: image; properties: "rotation"; duration: 200}
|
||||
}
|
||||
Connections {
|
||||
target: area.parent
|
||||
onSetActiveArea: {
|
||||
var expand = (activeAreaTitle === area.text);
|
||||
if(area.expanded && !expand && area.parent.scrollUpFlickable) {
|
||||
area.parent.scrollUpFlickable(content.implicitHeight + Theme.paddingLarge);
|
||||
}
|
||||
|
||||
area.expanded = expand;
|
||||
}
|
||||
}
|
||||
BackgroundItem {
|
||||
id: button
|
||||
height: Theme.itemSizeMedium
|
||||
onClicked: {
|
||||
area.parent.animate = true;
|
||||
area.parent.setActiveArea(area.expanded ? -1 : area.text)
|
||||
}
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
gradient: Gradient {
|
||||
GradientStop { position: 0.0; color: Theme.rgba(Theme.highlightBackgroundColor, 0.15) }
|
||||
GradientStop { position: 1.0; color: "transparent" }
|
||||
}
|
||||
}
|
||||
Label {
|
||||
id: label
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: image.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
leftMargin: Theme.horizontalPageMargin + Theme.paddingLarge
|
||||
rightMargin: Theme.paddingMedium
|
||||
}
|
||||
horizontalAlignment: Text.AlignRight
|
||||
truncationMode: TruncationMode.Fade
|
||||
color: button.highlighted ? Theme.highlightColor : Theme.primaryColor
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
HighlightImage {
|
||||
id: image
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: parent.verticalCenter
|
||||
rightMargin: Theme.horizontalPageMargin
|
||||
}
|
||||
width: visible ? Theme.iconSizeMedium : 0
|
||||
highlighted: parent.highlighted
|
||||
source: "image://theme/icon-m-left"
|
||||
rotation: -90
|
||||
}
|
||||
}
|
||||
Loader {
|
||||
id: content
|
||||
width: parent.width
|
||||
height: 0
|
||||
opacity: 0
|
||||
anchors.top: button.bottom
|
||||
asynchronous: true
|
||||
clip: true
|
||||
}
|
||||
}
|
28
qml/components/settingsPage/ResponsiveGrid.qml
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
Copyright (C) 2021 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import "../../js/functions.js" as Functions
|
||||
|
||||
Grid {
|
||||
width: parent.width - ( 2 * x )
|
||||
columns: Functions.isWidescreen(appWindow) ? 2 : 1
|
||||
readonly property real columnWidth: width/columns
|
||||
}
|
89
qml/components/settingsPage/SettingsAppearance.qml
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
Copyright (C) 2021 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
|
||||
AccordionItem {
|
||||
text: qsTr("Appearance")
|
||||
clip: heightBehavior.enabled || heightAnimation.running
|
||||
|
||||
// One-shot behavior
|
||||
Behavior on height {
|
||||
id: heightBehavior
|
||||
enabled: false
|
||||
SequentialAnimation {
|
||||
id: heightAnimation
|
||||
SmoothedAnimation { duration: 200 }
|
||||
ScriptAction { script: heightBehavior.enabled = false }
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
ResponsiveGrid {
|
||||
bottomPadding: Theme.paddingMedium
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.showStickersAsEmojis
|
||||
text: qsTr("Show stickers as emojis")
|
||||
description: qsTr("Only display emojis instead of the actual stickers")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
heightBehavior.enabled = true
|
||||
appSettings.showStickersAsEmojis = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.showStickersAsImages
|
||||
text: qsTr("Show stickers as images")
|
||||
description: qsTr("Show background for stickers and align them centrally like images")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.showStickersAsImages = !checked
|
||||
}
|
||||
visible: !appSettings.showStickersAsEmojis
|
||||
opacity: visible ? 1 : 0
|
||||
Behavior on opacity { FadeAnimation { } }
|
||||
}
|
||||
|
||||
Item {
|
||||
// Placeholder to move the next switch to the second column
|
||||
visible: parent.columns === 2
|
||||
width: 1
|
||||
height: 1
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.animateStickers
|
||||
text: qsTr("Animate stickers")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.animateStickers = !checked
|
||||
}
|
||||
visible: !appSettings.showStickersAsEmojis
|
||||
opacity: visible ? 1 : 0
|
||||
Behavior on opacity { FadeAnimation { } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
221
qml/components/settingsPage/SettingsBehavior.qml
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
Copyright (C) 2021 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
|
||||
AccordionItem {
|
||||
text: qsTr("Behavior")
|
||||
Component {
|
||||
ResponsiveGrid {
|
||||
bottomPadding: Theme.paddingMedium
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.sendByEnter
|
||||
text: qsTr("Send message by enter")
|
||||
description: qsTr("Send your message by pressing the enter key")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.sendByEnter = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.focusTextAreaOnChatOpen
|
||||
text: qsTr("Focus text input on chat open")
|
||||
description: qsTr("Focus the text input area when entering a chat")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.focusTextAreaOnChatOpen = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.focusTextAreaAfterSend
|
||||
text: qsTr("Focus text input area after send")
|
||||
description: qsTr("Focus the text input area after sending a message")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.focusTextAreaAfterSend = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.delayMessageRead
|
||||
text: qsTr("Delay before marking messages as read")
|
||||
description: qsTr("Fernschreiber will wait a bit before messages are marked as read")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.delayMessageRead = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.highlightUnreadConversations
|
||||
text: qsTr("Highlight unread messages")
|
||||
description: qsTr("Highlight Conversations with unread messages")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.highlightUnreadConversations = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.useOpenWith
|
||||
text: qsTr("Open-with menu integration")
|
||||
description: qsTr("Integrate Fernschreiber into open-with menu of Sailfish OS")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.useOpenWith = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.notificationAlwaysShowPreview
|
||||
text: qsTr("Always append message preview to notifications")
|
||||
description: qsTr("In addition to showing the number of unread messages, the latest message will also be appended to notifications.")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.notificationAlwaysShowPreview = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.goToQuotedMessage
|
||||
text: qsTr("Go to quoted message")
|
||||
description: qsTr("When tapping a quoted message, open it in chat instead of showing it in an overlay.")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.goToQuotedMessage = !checked
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: feedbackComboBox
|
||||
width: parent.columnWidth
|
||||
label: qsTr("Notification feedback")
|
||||
description: qsTr("Use non-graphical feedback (sound, vibration) for notifications")
|
||||
menu: ContextMenu {
|
||||
id: feedbackMenu
|
||||
x: 0
|
||||
width: feedbackComboBox.width
|
||||
|
||||
MenuItem {
|
||||
readonly property int value: AppSettings.NotificationFeedbackAll
|
||||
text: qsTr("All events")
|
||||
onClicked: {
|
||||
appSettings.notificationFeedback = value
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
readonly property int value: AppSettings.NotificationFeedbackNew
|
||||
text: qsTr("Only new events")
|
||||
onClicked: {
|
||||
appSettings.notificationFeedback = value
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
readonly property int value: AppSettings.NotificationFeedbackNone
|
||||
text: qsTr("None")
|
||||
onClicked: {
|
||||
appSettings.notificationFeedback = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: updateFeedbackSelection()
|
||||
|
||||
function updateFeedbackSelection() {
|
||||
var menuItems = feedbackMenu.children
|
||||
var n = menuItems.length
|
||||
for (var i=0; i<n; i++) {
|
||||
if (menuItems[i].value === appSettings.notificationFeedback) {
|
||||
currentIndex = i
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: appSettings
|
||||
onNotificationFeedbackChanged: {
|
||||
feedbackComboBox.updateFeedbackSelection()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
// Occupies one grid cell so that the column ends up under the combo box
|
||||
// in the landscape layout
|
||||
visible: parent.columns === 2
|
||||
width: 1
|
||||
height: 1
|
||||
}
|
||||
|
||||
Column {
|
||||
enabled: appSettings.notificationFeedback !== AppSettings.NotificationFeedbackNone
|
||||
width: parent.columnWidth
|
||||
height: enabled ? implicitHeight: 0
|
||||
clip: height < implicitHeight
|
||||
visible: height > 0
|
||||
|
||||
Behavior on height { SmoothedAnimation { duration: 200 } }
|
||||
|
||||
TextSwitch {
|
||||
checked: appSettings.notificationSuppressContent && enabled
|
||||
text: qsTr("Hide content in notifications")
|
||||
enabled: parent.enabled
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.notificationSuppressContent = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
checked: appSettings.notificationTurnsDisplayOn && enabled
|
||||
text: qsTr("Notification turns on the display")
|
||||
enabled: parent.enabled
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.notificationTurnsDisplayOn = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
checked: appSettings.notificationSoundsEnabled && enabled
|
||||
text: qsTr("Enable notification sounds")
|
||||
description: qsTr("When sounds are enabled, Fernschreiber will use the current Sailfish OS notification sound for chats, which can be configured in the system settings.")
|
||||
enabled: parent.enabled
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.notificationSoundsEnabled = !checked
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
266
qml/components/settingsPage/SettingsPrivacy.qml
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
Copyright (C) 2021 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
|
||||
AccordionItem {
|
||||
text: qsTr("Privacy")
|
||||
Component {
|
||||
Column {
|
||||
bottomPadding: Theme.paddingMedium
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onUserPrivacySettingUpdated: {
|
||||
Debug.log("Received updated privacy setting: " + setting + ":" + rule);
|
||||
switch (setting) {
|
||||
case TelegramAPI.SettingAllowChatInvites:
|
||||
allowChatInvitesComboBox.currentIndex = rule;
|
||||
break;
|
||||
case TelegramAPI.SettingAllowFindingByPhoneNumber:
|
||||
allowFindingByPhoneNumberComboBox.currentIndex = rule;
|
||||
break;
|
||||
case TelegramAPI.SettingShowLinkInForwardedMessages:
|
||||
showLinkInForwardedMessagesComboBox.currentIndex = rule;
|
||||
break;
|
||||
case TelegramAPI.SettingShowPhoneNumber:
|
||||
showPhoneNumberComboBox.currentIndex = rule;
|
||||
break;
|
||||
case TelegramAPI.SettingShowProfilePhoto:
|
||||
showProfilePhotoComboBox.currentIndex = rule;
|
||||
break;
|
||||
case TelegramAPI.SettingShowStatus:
|
||||
showStatusComboBox.currentIndex = rule;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ResponsiveGrid {
|
||||
ComboBox {
|
||||
id: allowChatInvitesComboBox
|
||||
width: parent.columnWidth
|
||||
label: qsTr("Allow chat invites")
|
||||
description: qsTr("Privacy setting for managing whether you can be invited to chats.")
|
||||
menu: ContextMenu {
|
||||
x: 0
|
||||
width: allowChatInvitesComboBox.width
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Yes")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites, TelegramAPI.RuleAllowAll);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Your contacts only")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites, TelegramAPI.RuleAllowContacts);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("No")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites, TelegramAPI.RuleRestrictAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingAllowChatInvites);
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: allowFindingByPhoneNumberComboBox
|
||||
width: parent.columnWidth
|
||||
label: qsTr("Allow finding by phone number")
|
||||
description: qsTr("Privacy setting for managing whether you can be found by your phone number.")
|
||||
menu: ContextMenu {
|
||||
x: 0
|
||||
width: allowFindingByPhoneNumberComboBox.width
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Yes")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowFindingByPhoneNumber, TelegramAPI.RuleAllowAll);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Your contacts only")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingAllowFindingByPhoneNumber, TelegramAPI.RuleAllowContacts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingAllowFindingByPhoneNumber);
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: showLinkInForwardedMessagesComboBox
|
||||
width: parent.columnWidth
|
||||
label: qsTr("Show link in forwarded messages")
|
||||
description: qsTr("Privacy setting for managing whether a link to your account is included in forwarded messages.")
|
||||
menu: ContextMenu {
|
||||
x: 0
|
||||
width: showLinkInForwardedMessagesComboBox.width
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Yes")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages, TelegramAPI.RuleAllowAll);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Your contacts only")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages, TelegramAPI.RuleAllowContacts);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("No")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages, TelegramAPI.RuleRestrictAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowLinkInForwardedMessages);
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: showPhoneNumberComboBox
|
||||
width: parent.columnWidth
|
||||
label: qsTr("Show phone number")
|
||||
description: qsTr("Privacy setting for managing whether your phone number is visible.")
|
||||
menu: ContextMenu {
|
||||
x: 0
|
||||
width: showPhoneNumberComboBox.width
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Yes")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber, TelegramAPI.RuleAllowAll);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Your contacts only")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber, TelegramAPI.RuleAllowContacts);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("No")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber, TelegramAPI.RuleRestrictAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowPhoneNumber);
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: showProfilePhotoComboBox
|
||||
width: parent.columnWidth
|
||||
label: qsTr("Show profile photo")
|
||||
description: qsTr("Privacy setting for managing whether your profile photo is visible.")
|
||||
menu: ContextMenu {
|
||||
x: 0
|
||||
width: showProfilePhotoComboBox.width
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Yes")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto, TelegramAPI.RuleAllowAll);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Your contacts only")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto, TelegramAPI.RuleAllowContacts);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("No")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto, TelegramAPI.RuleRestrictAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowProfilePhoto);
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: showStatusComboBox
|
||||
width: parent.columnWidth
|
||||
label: qsTr("Show status")
|
||||
description: qsTr("Privacy setting for managing whether your online status is visible.")
|
||||
menu: ContextMenu {
|
||||
x: 0
|
||||
width: showStatusComboBox.width
|
||||
|
||||
MenuItem {
|
||||
text: qsTr("Yes")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowStatus, TelegramAPI.RuleAllowAll);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("Your contacts only")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowStatus, TelegramAPI.RuleAllowContacts);
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: qsTr("No")
|
||||
onClicked: {
|
||||
tdLibWrapper.setUserPrivacySettingRule(TelegramAPI.SettingShowStatus, TelegramAPI.RuleRestrictAll);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
currentIndex = tdLibWrapper.getUserPrivacySettingRule(TelegramAPI.SettingShowStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
checked: appSettings.allowInlineBotLocationAccess
|
||||
text: qsTr("Allow sending Location to inline bots")
|
||||
description: qsTr("Some inline bots request location data when using them")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.allowInlineBotLocationAccess = !checked
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
216
qml/components/settingsPage/SettingsSession.qml
Normal file
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
Copyright (C) 2020-21 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../../components"
|
||||
import "../../js/functions.js" as Functions
|
||||
|
||||
AccordionItem {
|
||||
text: qsTr("Sessions")
|
||||
property SilicaFlickable flickable: parent.flickable
|
||||
Component {
|
||||
Column {
|
||||
id: activeSessionsItem
|
||||
bottomPadding: Theme.paddingMedium
|
||||
property variant activeSessions
|
||||
property int inactiveSessionsTtlDays
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!activeSessions) {
|
||||
tdLibWrapper.getActiveSessions();
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onSessionsReceived: {
|
||||
activeSessionsItem.activeSessions = sessions
|
||||
activeSessionsItem.inactiveSessionsTtlDays = inactive_session_ttl_days
|
||||
}
|
||||
onOkReceived: {
|
||||
if (request === "terminateSession") {
|
||||
appNotification.show(qsTr("Session was terminated"));
|
||||
tdLibWrapper.getActiveSessions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
active: tdLibWrapper.authorizationState === TelegramAPI.AuthorizationReady
|
||||
width: parent.width
|
||||
sourceComponent: Component {
|
||||
Column {
|
||||
BusyIndicator {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
running: !activeSessionsListView.count && !activeSessionsItem.inactiveSessionsTtlDays
|
||||
size: BusyIndicatorSize.Medium
|
||||
visible: opacity > 0
|
||||
height: running ? implicitHeight : 0
|
||||
}
|
||||
|
||||
SilicaListView {
|
||||
id: activeSessionsListView
|
||||
width: parent.width
|
||||
height: contentHeight
|
||||
model: activeSessionsItem.activeSessions
|
||||
headerPositioning: ListView.OverlayHeader
|
||||
header: Separator {
|
||||
width: parent.width
|
||||
color: Theme.primaryColor
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
visible: activeSessionsListView.count > 0
|
||||
}
|
||||
delegate: ListItem {
|
||||
id: activeSessionListItem
|
||||
width: parent.width
|
||||
contentHeight: activeSessionColumn.height + ( 2 * Theme.paddingMedium )
|
||||
|
||||
menu: ContextMenu {
|
||||
hasContent: !modelData.is_current
|
||||
onHeightChanged: {
|
||||
if (parent && flickable) {
|
||||
// Make sure we are inside the screen area
|
||||
var bottom = parent.mapToItem(flickable, x, y).y + height
|
||||
if (bottom > flickable.height) {
|
||||
flickable.contentY += bottom - flickable.height
|
||||
}
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
onClicked: {
|
||||
var sessionId = modelData.id;
|
||||
Remorse.itemAction(activeSessionListItem, qsTr("Terminating session"), function() { tdLibWrapper.terminateSession(sessionId); });
|
||||
}
|
||||
text: qsTr("Terminate Session")
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: activeSessionColumn
|
||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||
spacing: Theme.paddingSmall
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
text: qsTr("This app")
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.bold: true
|
||||
visible: modelData.is_current
|
||||
color: Theme.highlightColor
|
||||
}
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
text: modelData.application_name + " " + modelData.application_version
|
||||
font.pixelSize: Theme.fontSizeMedium
|
||||
font.bold: true
|
||||
maximumLineCount: 1
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
text: modelData.device_model + ", " + (modelData.platform + " " + modelData.system_version).trim()
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
maximumLineCount: 1
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
text: qsTr("Active since: %1, last online: %2").arg(Functions.getDateTimeTimepoint(modelData.log_in_date)).arg(Functions.getDateTimeElapsed(modelData.last_active_date))
|
||||
font.pixelSize: Theme.fontSizeExtraSmall
|
||||
maximumLineCount: 1
|
||||
truncationMode: TruncationMode.Fade
|
||||
}
|
||||
}
|
||||
|
||||
Separator {
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
width: parent.width
|
||||
color: Theme.primaryColor
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
readonly property int ttl: activeSessionsItem.inactiveSessionsTtlDays
|
||||
label: qsTr("Session Timeout")
|
||||
description: qsTr("Inactive sessions will be terminated after this timeframe")
|
||||
value: (currentItem && currentItem.text) ? currentItem.text : qsTr("%1 day(s)", "", ttl).arg(ttl)
|
||||
visible: ttl > 0
|
||||
menu: ContextMenu {
|
||||
id: ttlMenu
|
||||
MenuItem {
|
||||
readonly property int days: 7
|
||||
text: qsTr("1 week")
|
||||
onClicked: tdLibWrapper.setInactiveSessionTtl(days)
|
||||
}
|
||||
MenuItem {
|
||||
readonly property int days: 30
|
||||
text: qsTr("1 month")
|
||||
onClicked: tdLibWrapper.setInactiveSessionTtl(days)
|
||||
}
|
||||
MenuItem {
|
||||
readonly property int days: 90
|
||||
text: qsTr("3 months")
|
||||
onClicked: tdLibWrapper.setInactiveSessionTtl(days)
|
||||
}
|
||||
MenuItem {
|
||||
readonly property int days: 180
|
||||
text: qsTr("6 months")
|
||||
onClicked: tdLibWrapper.setInactiveSessionTtl(days)
|
||||
}
|
||||
MenuItem {
|
||||
readonly property int days: 365
|
||||
text: qsTr("1 year")
|
||||
onClicked: tdLibWrapper.setInactiveSessionTtl(days)
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: updateSelection()
|
||||
|
||||
onTtlChanged: updateSelection()
|
||||
|
||||
function updateSelection() {
|
||||
var menuItems = ttlMenu.children
|
||||
var n = menuItems.length
|
||||
for (var i = 0; i < n; i++) {
|
||||
if (menuItems[i].days === ttl) {
|
||||
currentIndex = i
|
||||
return
|
||||
}
|
||||
}
|
||||
currentIndex = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
51
qml/components/settingsPage/SettingsStorage.qml
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright (C) 2021 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
|
||||
AccordionItem {
|
||||
text: qsTr("Storage")
|
||||
Component {
|
||||
ResponsiveGrid {
|
||||
bottomPadding: Theme.paddingMedium
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.onlineOnlyMode
|
||||
text: qsTr("Enable online-only mode")
|
||||
description: qsTr("Disables offline caching. Certain features may be limited or missing in this mode. Changes require a restart of Fernschreiber to take effect.")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.onlineOnlyMode = !checked
|
||||
}
|
||||
}
|
||||
|
||||
TextSwitch {
|
||||
width: parent.columnWidth
|
||||
checked: appSettings.storageOptimizer
|
||||
text: qsTr("Enable storage optimizer")
|
||||
automaticCheck: false
|
||||
onClicked: {
|
||||
appSettings.storageOptimizer = !checked
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
346
qml/components/settingsPage/SettingsUserProfile.qml
Normal file
|
@ -0,0 +1,346 @@
|
|||
/*
|
||||
Copyright (C) 2021 Sebastian J. Wolf and other contributors
|
||||
|
||||
This file is part of Fernschreiber.
|
||||
|
||||
Fernschreiber is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Fernschreiber is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Fernschreiber. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import QtQuick 2.6
|
||||
import Sailfish.Silica 1.0
|
||||
import Sailfish.Pickers 1.0
|
||||
import WerkWolf.Fernschreiber 1.0
|
||||
import "../"
|
||||
import "../../pages/"
|
||||
import "../../js/twemoji.js" as Emoji
|
||||
import "../../js/functions.js" as Functions
|
||||
|
||||
AccordionItem {
|
||||
text: qsTr("User Profile")
|
||||
Component {
|
||||
Column {
|
||||
id: accordionContent
|
||||
bottomPadding: Theme.paddingMedium
|
||||
|
||||
readonly property var userInformation: tdLibWrapper.getUserInformation()
|
||||
property bool uploadInProgress: false
|
||||
property bool contactSyncEnabled: false
|
||||
|
||||
Component.onCompleted: {
|
||||
tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0);
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onOwnUserUpdated: {
|
||||
firstNameEditArea.text = userInformation.first_name;
|
||||
lastNameEditArea.text = userInformation.last_name;
|
||||
userNameEditArea.text = userInformation.username;
|
||||
}
|
||||
onUserProfilePhotosReceived: {
|
||||
if (extra === userInformation.id.toString()) {
|
||||
imageContainer.thumbnailModel = photos;
|
||||
}
|
||||
}
|
||||
onFileUpdated: {
|
||||
if (uploadInProgress) {
|
||||
profilePictureButtonColumn.visible = !fileInformation.remote.is_uploading_active;
|
||||
uploadInProgress = fileInformation.remote.is_uploading_active;
|
||||
if (!fileInformation.remote.is_uploading_active) {
|
||||
uploadInProgress = false;
|
||||
tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
onOkReceived: {
|
||||
if (request === "deleteProfilePhoto") {
|
||||
tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0);
|
||||
}
|
||||
if (request === "setProfilePhoto") {
|
||||
tdLibWrapper.getUserProfilePhotos(userInformation.id, 100, 0);
|
||||
profilePictureButtonColumn.visible = true;
|
||||
uploadInProgress = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResponsiveGrid {
|
||||
x: Theme.horizontalPageMargin
|
||||
|
||||
InformationEditArea {
|
||||
id: firstNameEditArea
|
||||
visible: true
|
||||
canEdit: true
|
||||
headerText: qsTr("First Name", "first name of the logged-in profile - header")
|
||||
text: userInformation.first_name
|
||||
width: parent.columnWidth
|
||||
headerLeftAligned: true
|
||||
|
||||
onSaveButtonClicked: {
|
||||
if(!editItem.errorHighlight) {
|
||||
tdLibWrapper.setName(textValue, lastNameEditArea.text);
|
||||
} else {
|
||||
isEditing = true;
|
||||
}
|
||||
}
|
||||
|
||||
onTextEdited: {
|
||||
if(textValue.length > 0 && textValue.length < 65) {
|
||||
editItem.errorHighlight = false;
|
||||
editItem.label = "";
|
||||
editItem.placeholderText = "";
|
||||
} else {
|
||||
editItem.label = qsTr("Enter 1-64 characters");
|
||||
editItem.placeholderText = editItem.label;
|
||||
editItem.errorHighlight = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InformationEditArea {
|
||||
id: lastNameEditArea
|
||||
visible: true
|
||||
canEdit: true
|
||||
headerText: qsTr("Last Name", "last name of the logged-in profile - header")
|
||||
text: userInformation.last_name
|
||||
width: parent.columnWidth
|
||||
headerLeftAligned: true
|
||||
|
||||
onSaveButtonClicked: {
|
||||
if(!editItem.errorHighlight) {
|
||||
tdLibWrapper.setName(firstNameEditArea.text, textValue);
|
||||
} else {
|
||||
isEditing = true;
|
||||
}
|
||||
}
|
||||
|
||||
onTextEdited: {
|
||||
if(textValue.length >= 0 && textValue.length < 65) {
|
||||
editItem.errorHighlight = false;
|
||||
editItem.label = "";
|
||||
editItem.placeholderText = "";
|
||||
} else {
|
||||
editItem.label = qsTr("Enter 0-64 characters");
|
||||
editItem.placeholderText = editItem.label;
|
||||
editItem.errorHighlight = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InformationEditArea {
|
||||
id: userNameEditArea
|
||||
visible: true
|
||||
canEdit: true
|
||||
headerText: qsTr("Username", "user name of the logged-in profile - header")
|
||||
text: userInformation.usernames.editable_username
|
||||
width: parent.columnWidth
|
||||
headerLeftAligned: true
|
||||
|
||||
onSaveButtonClicked: {
|
||||
tdLibWrapper.setUsername(textValue);
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: contactSyncItem
|
||||
width: parent.width
|
||||
height: syncInProgress ? ( syncContactsBusyIndicator.height + Theme.paddingMedium ) : ( syncContactsButton.height + Theme.paddingMedium )
|
||||
visible: accordionContent.contactSyncEnabled
|
||||
|
||||
property bool syncInProgress: false
|
||||
|
||||
Connections {
|
||||
target: contactSyncLoader.item
|
||||
onSyncError: {
|
||||
contactSyncItem.syncInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onContactsImported: {
|
||||
appNotification.show(qsTr("Contacts successfully synchronized with Telegram."));
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: syncContactsButton
|
||||
text: qsTr("Synchronize Contacts with Telegram")
|
||||
visible: !contactSyncItem.syncInProgress
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
onClicked: {
|
||||
contactSyncLoader.item.synchronize();
|
||||
}
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
id: syncContactsBusyIndicator
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
running: contactSyncItem.syncInProgress
|
||||
size: BusyIndicatorSize.Small
|
||||
visible: running
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SectionHeader {
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
text: qsTr("Profile Pictures")
|
||||
}
|
||||
|
||||
Row {
|
||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||
spacing: Theme.paddingMedium
|
||||
|
||||
Item {
|
||||
id: imageContainer
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: parent.width / 2
|
||||
height: profilePictureLoader.height
|
||||
property var thumbnailModel: ({})
|
||||
property bool thumbnailVisible: true
|
||||
property bool thumbnailActive: thumbnailModel.length > 0
|
||||
property int thumbnailRadius: imageContainer.width / 2
|
||||
|
||||
Loader {
|
||||
id: profilePictureLoader
|
||||
active: imageContainer.thumbnailActive
|
||||
asynchronous: true
|
||||
width: Theme.itemSizeExtraLarge
|
||||
height: Theme.itemSizeExtraLarge
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
source: "../ProfilePictureList.qml"
|
||||
}
|
||||
|
||||
ProfileThumbnail {
|
||||
id: chatPictureReplacement
|
||||
visible: !profilePictureLoader.active
|
||||
replacementStringHint: Functions.getUserName(accordionContent.userInformation)
|
||||
radius: imageContainer.thumbnailRadius
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
width: Theme.itemSizeExtraLarge
|
||||
height: Theme.itemSizeExtraLarge
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: profilePictureButtonColumn
|
||||
spacing: Theme.paddingSmall
|
||||
width: parent.width / 2
|
||||
|
||||
Button {
|
||||
id: addProfilePictureButton
|
||||
text: qsTr("Add Picture")
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
onClicked: {
|
||||
pageStack.push(imagePickerPage);
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: removeProfilePictureButton
|
||||
text: qsTr("Delete Picture")
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
onClicked: {
|
||||
var pictureIdForDeletion = imageContainer.thumbnailModel[profilePictureLoader.item.currentPictureIndex].id;
|
||||
Remorse.popupAction(settingsPage, qsTr("Deleting profile picture"), function() { tdLibWrapper.deleteProfilePhoto(pictureIdForDeletion) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
id: uploadStatusColumn
|
||||
visible: !profilePictureButtonColumn.visible
|
||||
spacing: Theme.paddingMedium
|
||||
width: parent.width / 2
|
||||
|
||||
Text {
|
||||
id: uploadingText
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
text: qsTr("Uploading...")
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
color: Theme.secondaryColor
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
BusyIndicator {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
running: uploadStatusColumn.visible
|
||||
size: BusyIndicatorSize.Medium
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: contactSyncLoader
|
||||
source: "../ContactSync.qml"
|
||||
active: true
|
||||
onLoaded: {
|
||||
accordionContent.contactSyncEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: imagePickerPage
|
||||
ImagePickerPage {
|
||||
onSelectedContentPropertiesChanged: {
|
||||
profilePictureButtonColumn.visible = false;
|
||||
uploadInProgress = true;
|
||||
tdLibWrapper.setProfilePhoto(selectedContentProperties.filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
|
||||
width: parent.width - ( 2 * Theme.horizontalPageMargin )
|
||||
spacing: Theme.paddingMedium
|
||||
|
||||
Label {
|
||||
width: parent.width
|
||||
height: Theme.fontSizeExtraLarge
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignBottom
|
||||
text: qsTr("Phone number: +%1").arg(accordionContent.userInformation.phone_number)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
wrapMode: Text.Wrap
|
||||
anchors {
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: logOutButton
|
||||
text: qsTr("Log Out")
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
onClicked: Remorse.popupAction(settingsPage, qsTr("Logged out"), function() {
|
||||
tdLibWrapper.logout();
|
||||
pageStack.pop();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,6 +40,16 @@ ApplicationWindow
|
|||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: tdLibWrapper
|
||||
onOpenFileExternally: {
|
||||
Qt.openUrlExternally(filePath);
|
||||
}
|
||||
onTgUrlFound: {
|
||||
Functions.handleLink(tgUrl);
|
||||
}
|
||||
}
|
||||
|
||||
AppNotification {
|
||||
id: appNotification
|
||||
parent: pageStack.currentPage
|
||||
|
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#141414" d="M4 5C1.791 5 0 6.791 0 9v18c0 2.209 1.791 4 4 4h8V5H4z"/><path fill="#FEE833" d="M12 5h12v26H12z"/><path fill="#EE232C" d="M32 5h-8v26h8c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" xml:space="preserve"><path fill="#141414" d="M7 5a4 4 0 0 0-4 4v18a4 4 0 0 0 4 4h6V5H7z"/><path fill="#FDDA24" d="M13 5h10v26H13z"/><path fill="#EF3340" d="M29 5h-6v26h6a4 4 0 0 0 4-4V9a4 4 0 0 0-4-4z"/></svg>
|
Before Width: | Height: | Size: 272 B After Width: | Height: | Size: 269 B |
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#138808" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-4H0v4z"/><path fill="#EEE" d="M0 13h36v10H0z"/><path fill="#F93" d="M36 13V9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9v4h36z"/><circle fill="navy" cx="18" cy="18" r="4"/><circle fill="#EEE" cx="18" cy="18" r="3"/><path fill="#6666B3" d="M18 15l.146 2.264 1.001-2.035-.73 2.147 1.704-1.498-1.497 1.705 2.147-.731-2.035 1.002L21 18l-2.264.146 2.035 1.001-2.147-.73 1.497 1.704-1.704-1.497.73 2.147-1.001-2.035L18 21l-.146-2.264-1.002 2.035.731-2.147-1.705 1.497 1.498-1.704-2.147.73 2.035-1.001L15 18l2.264-.146-2.035-1.002 2.147.731-1.498-1.705 1.705 1.498-.731-2.147 1.002 2.035z"/><circle fill="navy" cx="18" cy="18" r="1"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" xml:space="preserve"><path fill="#138808" d="M0 27a4 4 0 0 0 4 4h28a4 4 0 0 0 4-4v-5H0v5z"/><path fill="#F93" d="M36 14V9a4 4 0 0 0-4-4H4a4 4 0 0 0-4 4v5h36z"/><path fill="#F7F7F7" d="M0 13.667h36v8.667H0z"/><circle fill="navy" cx="18" cy="18" r="4"/><circle fill="#F7F7F7" cx="18" cy="18" r="3.375"/><path d="m18.1 16.75-.1.65-.1-.65.1-1.95zm-.928-1.841.408 1.909.265.602-.072-.653zm-.772.32.888 1.738.412.513-.238-.613zm-.663.508 1.308 1.45.531.389-.389-.531zm-.508.663 1.638 1.062.613.238-.513-.412zm-.32.772 1.858.601.653.072-.602-.265zM14.8 18l1.95.1.65-.1-.65-.1zm.109.828 1.909-.408.602-.265-.653.072zm.32.772 1.738-.888.513-.412-.613.238zm.508.663 1.45-1.308.389-.531-.531.389zm.663.508 1.062-1.638.238-.613-.412.513zm.772.32.601-1.858.072-.653-.265.602zM18 21.2l.1-1.95-.1-.65-.1.65zm.828-.109-.408-1.909-.265-.602.072.653zm.772-.32-.888-1.738-.412-.513.238.613zm.663-.508-1.308-1.45-.531-.389.389.531zm.508-.663-1.638-1.062-.613-.238.513.412zm.32-.772-1.858-.601-.653-.072.602.265zM21.2 18l-1.95-.1-.65.1.65.1zm-.109-.828-1.909.408-.602.265.653-.072zm-.32-.772-1.738.888-.513.412.613-.238zm-.508-.663-1.45 1.308-.389.531.531-.389zm-.663-.508-1.062 1.638-.238.613.412-.513zm-.772-.32-.601 1.858-.072.653.265-.602z" fill="#6666B3"/><g fill="navy"><circle cx="17.56" cy="14.659" r=".2"/><circle cx="16.71" cy="14.887" r=".2"/><circle cx="15.948" cy="15.326" r=".2"/><circle cx="15.326" cy="15.948" r=".2"/><circle cx="14.887" cy="16.71" r=".2"/><circle cx="14.659" cy="17.56" r=".2"/><circle cx="14.659" cy="18.44" r=".2"/><circle cx="14.887" cy="19.29" r=".2"/><circle cx="15.326" cy="20.052" r=".2"/><circle cx="15.948" cy="20.674" r=".2"/><circle cx="16.71" cy="21.113" r=".2"/><circle cx="17.56" cy="21.341" r=".2"/><circle cx="18.44" cy="21.341" r=".2"/><circle cx="19.29" cy="21.113" r=".2"/><circle cx="20.052" cy="20.674" r=".2"/><circle cx="20.674" cy="20.052" r=".2"/><circle cx="21.113" cy="19.29" r=".2"/><circle cx="21.341" cy="18.44" r=".2"/><circle cx="21.341" cy="17.56" r=".2"/><circle cx="21.113" cy="16.71" r=".2"/><circle cx="20.674" cy="15.948" r=".2"/><circle cx="20.052" cy="15.326" r=".2"/><circle cx="19.29" cy="14.887" r=".2"/><circle cx="18.44" cy="14.659" r=".2"/><circle cx="18" cy="18" r=".9"/></g></svg>
|
Before Width: | Height: | Size: 765 B After Width: | Height: | Size: 2.2 KiB |
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#060" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#D52B1E" d="M32 5H15v26h17c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFCC4D" d="M15 10c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zm3.994 5.938l2.089-1.393c.491.863.803 1.839.888 2.881l-2.977-1.488zM16 24h2.592c-.779.467-1.655.786-2.592.92V24zm-7.971-6.574c.083-1.022.383-1.982.858-2.832l1.602 1.602-2.46 1.23zm0 1.147l3.747 1.874.447-.895L9.118 18l2.116-1.058 1.412 1.412.707-.707-1.176-1.176.046-.023-.447-.895-.344.172-.975-.975 1.461.244.164-.986-2.514-.419c1.084-1.333 2.65-2.253 4.432-2.508V23h-3.099l2.376-1.584-.555-.832-3 2 .014.021c-.959-1.097-1.582-2.492-1.707-4.032zM14 24.92c-.937-.135-1.813-.453-2.592-.92H14v.92zm6.287-2.34l-2.933-2.933-.707.707.471.471-.395.592L19.099 23H16V11.08c1.321.189 2.524.741 3.499 1.561l-2.657.886.316.948 3-1-.103-.308c.167.174.323.357.471.548l-2.804 1.869L18 16l-.224.447L20.882 18l-3.105 1.553.447.895 3.747-1.874c-.124 1.527-.737 2.913-1.684 4.006z"/><path fill="#D52B1E" d="M11 13v7c0 2.209 1.791 4 4 4s4-1.791 4-4v-7h-8z"/><path fill="#FFF" d="M12 14v6c0 1.656 1.343 3 3 3s3-1.344 3-3v-6h-6z"/><path fill="#829ACD" d="M13 17h4v2h-4z"/><path fill="#829ACD" d="M14 16h2v4h-2z"/><path fill="#039" d="M12 17h1v2h-1zm2 0h2v2h-2zm3 0h1v2h-1zm-3 3h2v2h-2zm0-6h2v2h-2z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#060" d="M36 27c0 2.209-1.791 4-4 4H4c-2.209 0-4-1.791-4-4V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v18z"/><path fill="#D52B1E" d="M32 5H15v26h17c2.209 0 4-1.791 4-4V9c0-2.209-1.791-4-4-4z"/><path fill="#FFCC4D" d="M15 10c-4.419 0-8 3.581-8 8 0 4.418 3.581 8 8 8 4.418 0 8-3.582 8-8 0-4.419-3.582-8-8-8zm-6.113 4.594l1.602 1.602-2.46 1.23c.083-1.022.383-1.981.858-2.832zm-.858 3.979l4.4 2.207-2.706 1.804.014.021c-.96-1.097-1.583-2.492-1.708-4.032zM14 24.92c-.937-.134-1.813-.453-2.592-.92H14v.92zM14 23h-3.099L14 20.934V23zm0-3.268l-.607.405L9.118 18l2.116-1.058L14 19.707v.025zm0-1.439l-3.543-3.543 3.543.59v2.953zm0-3.992l-4.432-.713c1.084-1.333 2.65-2.253 4.432-2.508v3.221zm7.113.293c.475.851.775 1.81.858 2.833l-2.46-1.23 1.602-1.603zM16 11.08c1.782.256 3.348 1.175 4.432 2.508L16 14.301V11.08zm0 4.26l3.543-.591L16 18.293V15.34zm0 4.367l2.765-2.765L20.882 18l-4.274 2.137-.608-.405v-.025zm0 5.213V24h2.592c-.779.467-1.655.786-2.592.92zM16 23v-2.066L19.099 23H16zm4.264-.395l.014-.021-2.706-1.804 4.4-2.207c-.126 1.54-.749 2.935-1.708 4.032z"/><path fill="#D52B1E" d="M11 13v7c0 2.209 1.791 4 4 4s4-1.791 4-4v-7h-8z"/><path fill="#FFF" d="M12 14v6c0 1.656 1.343 3 3 3s3-1.344 3-3v-6h-6z"/><path fill="#829ACD" d="M13 17h4v2h-4z"/><path fill="#829ACD" d="M14 16h2v4h-2z"/><path fill="#039" d="M12 17h1v2h-1zm2 0h2v2h-2zm3 0h1v2h-1zm-3 3h2v2h-2zm0-6h2v2h-2z"/></svg>
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#ED1C24" d="M32 5H4C1.791 5 0 6.791 0 9h36c0-2.209-1.791-4-4-4z"/><path fill="#EEE" d="M0 9h36v4H0z"/><path fill="#ED1C24" d="M32 31H4c-2.209 0-4-1.791-4-4h36c0 2.209-1.791 4-4 4z"/><path fill="#EEE" d="M0 23h36v4H0z"/><path fill="#241D4F" d="M0 13h36v10H0z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#A7122D" d="M0 26.518V27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-.482H0z"/><path fill="#EEE" d="M0 22.181h36v4.485H0z"/><path fill="#292648" d="M0 13.513h36v8.821H0z"/><path fill="#EEE" d="M0 9.181h36v4.485H0z"/><path fill="#A7122D" d="M0 9.333V9c0-2.209 1.791-4 4-4h28c2.209 0 4 1.791 4 4v.333H0z"/></svg>
|
Before Width: | Height: | Size: 338 B After Width: | Height: | Size: 382 B |
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#CCD6DD" cx="18" cy="18" r="18"/><circle fill="#3B88C3" cx="18" cy="18" r="14"/><circle fill="#DD2E44" cx="18" cy="18" r="10"/><circle fill="#FFAC33" cx="18" cy="18" r="6"/><path d="M34.864 29.199c-.42.306-1.257.592-1.934.592-1.965 0-4.654-.717-6.334-2.386l-2.954-3.872c-.274-.275-.357-.575-.21-.932.148-.359-.73-.601-.342-.601h5.058c1.867 0 4.308 1.256 5.925 3.018l.371.351c.772.843 1.183 1.629 1.182 2.386 0 .621-.272 1.087-.762 1.444z"/><path d="M28.305 35.204c-.771 0-1.632-.417-2.49-1.204l-.488-.378C23.532 31.977 22 29.491 22 27.59v-5.164c0-.396.5.514.865.363.363-.15.915-.066 1.195.214l3.166 3.124c1.699 1.711 3.061 4.619 3.061 6.62 0 .689-.143 1.255-.452 1.682-.364.499-.897.775-1.53.775z"/><path fill="#C1694F" d="M31.345 31.964c-.256 0-.487-.122-.683-.317l-14-14c-.391-.391-.391-1.023 0-1.415.391-.391 1.023-.39 1.414 0l14 14c.391.391.378 1.036-.013 1.427-.194.195-.461.305-.718.305z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><circle fill="#DD2E44" cx="18" cy="18" r="18"/><circle fill="#FFF" cx="18" cy="18" r="13.5"/><circle fill="#DD2E44" cx="18" cy="18" r="10"/><circle fill="#FFF" cx="18" cy="18" r="6"/><circle fill="#DD2E44" cx="18" cy="18" r="3"/><path opacity=".2" d="M18.24 18.282l13.144 11.754s-2.647 3.376-7.89 5.109L17.579 18.42l.661-.138z"/><path fill="#FFAC33" d="M18.294 19c-.255 0-.509-.097-.704-.292-.389-.389-.389-1.018 0-1.407l.563-.563c.389-.389 1.018-.389 1.408 0 .388.389.388 1.018 0 1.407l-.564.563c-.194.195-.448.292-.703.292z"/><path fill="#55ACEE" d="M24.016 6.981c-.403 2.079 0 4.691 0 4.691l7.054-7.388c.291-1.454-.528-3.932-1.718-4.238-1.19-.306-4.079.803-5.336 6.935zm5.003 5.003c-2.079.403-4.691 0-4.691 0l7.388-7.054c1.454-.291 3.932.528 4.238 1.718.306 1.19-.803 4.079-6.935 5.336z"/><path fill="#3A87C2" d="M32.798 4.485L21.176 17.587c-.362.362-1.673.882-2.51.046-.836-.836-.419-2.08-.057-2.443L31.815 3.501s.676-.635 1.159-.152-.176 1.136-.176 1.136z"/></svg>
|
Before Width: | Height: | Size: 976 B After Width: | Height: | Size: 1 KiB |
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#880082" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-.5H0v.5z"/><path fill="#3558A0" d="M0 22.07h36v4.6H0z"/><path fill="#138F3E" d="M0 17.83h36v4.5H0z"/><path fill="#FAD220" d="M0 13.5h36V18H0z"/><path fill="#FF5000" d="M0 9.17h36v4.5H0z"/><path fill="#FF000E" d="M32 5H4C1.791 5 0 6.791 0 9v.33h36V9c0-2.209-1.791-4-4-4z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36" xml:space="preserve"><path fill="#880082" d="M0 27a4 4 0 0 0 4 4h28a4 4 0 0 0 4-4v-.5H0v.5z"/><path fill="#3558A0" d="M0 22.07h36v4.6H0z"/><path fill="#138F3E" d="M0 17.83h36v4.5H0z"/><path fill="#FAD220" d="M0 13.5h36V18H0z"/><path fill="#FF7300" d="M0 9.17h36v4.5H0z"/><path fill="#FF000E" d="M32 5H4a4 4 0 0 0-4 4v.33h36V9a4 4 0 0 0-4-4z"/></svg>
|
Before Width: | Height: | Size: 412 B After Width: | Height: | Size: 409 B |
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5BCEFA" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-1.3H0V27z"/><path fill="#F5A9B8" d="M.026 20.5L0 25.8h36v-5.3z"/><path fill="#EEE" d="M0 15.3h36v5.3H0z"/><path fill="#F5A9B8" d="M.026 10.1L0 15.4h36v-5.3z"/><path fill="#5BCEFA" d="M36 9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9v1.2h36V9z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#5BCEFA" d="M0 27c0 2.209 1.791 4 4 4h28c2.209 0 4-1.791 4-4v-1.3H0V27z"/><path fill="#F5A9B8" d="M.026 20.5L0 25.8h36v-5.3z"/><path fill="#EEE" d="M0 15.3h36v5.3H0z"/><path fill="#F5A9B8" d="M0 9.902h36V15.4H0z"/><path fill="#5BCEFA" d="M36 9c0-2.209-1.791-4-4-4H4C1.791 5 0 6.791 0 9v1.2h36V9z"/></svg>
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 376 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#292F33" d="M11 11.844c-2.297-.669-3.315-3.565-3.734-5.369C6.313 7.952 4.23 10.155 0 11.28V.425C.955.154 1.959 0 3 0c6.075 0 11 4.925 11 11 0 3.009-1.211 5.733-3.168 7.719.107-.557.168-1.13.168-1.719v-5.156z"/><path fill="#F7DECE" d="M0 28.604L2 32l3-5v-1.523c2.968-1.051 5.222-3.607 5.832-6.757.107-.558.168-1.131.168-1.72v-5.156c-2.297-.669-3.315-3.565-3.734-5.369C6.313 7.952 4.23 10.155 0 11.28v17.324z"/><path fill="#3B94D9" d="M0 28.604L2 32l3-5h6c2.209 0 4 1.791 4 4v5H0v-7.396z"/><path fill="#1C6399" d="M10 32h1v4h-1z"/><path fill="#C1694F" d="M5 22h1s-1 2-4 2c-.809 0-1.462-.151-2-.363V22h5zm-2-2.5H1c-.276 0-.5-.224-.5-.5s.224-.5.5-.5h2c.276 0 .5.224.5.5s-.224.5-.5.5z"/><path fill="#662113" d="M6 16c-.553 0-1-.448-1-1v-1c0-.552.447-1 1-1s1 .448 1 1v1c0 .552-.447 1-1 1z"/><path fill="#292F33" d="M25 11.844c2.297-.669 3.315-3.565 3.734-5.369.953 1.477 3.036 3.68 7.266 4.805V.425C35.045.154 34.041 0 33 0c-6.075 0-11 4.925-11 11 0 3.009 1.211 5.733 3.168 7.719C25.061 18.162 25 17.589 25 17v-5.156z"/><path fill="#F7DECE" d="M36 11.28c-4.23-1.125-6.313-3.328-7.266-4.804-.42 1.804-1.438 4.699-3.734 5.369V17c0 .589.061 1.162.168 1.719.61 3.15 2.863 5.706 5.832 6.757V27l3 5 2-3.396V11.28z"/><path fill="#3B94D9" d="M36 28.604L34 32l-3-5h-6c-2.209 0-4 1.791-4 4v5h15v-7.396z"/><path fill="#1C6399" d="M25 32h1v4h-1z"/><path fill="#C1694F" d="M31 22h-1s1 2 4 2c.809 0 1.462-.151 2-.363V22h-5zm2-2.5h2c.276 0 .5-.224.5-.5s-.224-.5-.5-.5h-2c-.276 0-.5.224-.5.5s.224.5.5.5z"/><path fill="#662113" d="M30 16c.553 0 1-.448 1-1v-1c0-.552-.447-1-1-1s-1 .448-1 1v1c0 .552.447 1 1 1z"/><path fill="#DD2E44" d="M26.539 4.711c0-2.602-2.11-4.711-4.711-4.711C20.249 0 18.855.78 18 1.972 17.144.78 15.751 0 14.172 0c-2.601 0-4.711 2.109-4.711 4.711 0 .369.047.727.127 1.07.654 4.065 5.173 8.353 8.411 9.529 3.238-1.177 7.758-5.465 8.412-9.528.081-.344.128-.702.128-1.071z"/></svg>
|
After Width: | Height: | Size: 1.9 KiB |