Compare commits

...

756 Commits

Author SHA1 Message Date
Grishka
33cbd85e19 Bump version 2023-05-11 05:42:40 +03:00
Grishka
8cb1f3f387 Merge branch 'l10n_master' 2023-05-11 05:40:54 +03:00
Eugen Rochko
3f0c6fcec5 New translations strings.xml (Icelandic) 2023-05-10 13:59:12 +02:00
Eugen Rochko
797cf893da New translations strings.xml (Italian) 2023-05-08 15:58:22 +02:00
Eugen Rochko
a3564b70e1 New translations strings.xml (Ukrainian) 2023-05-08 07:52:51 +02:00
Eugen Rochko
43004307b8 New translations strings.xml (Ukrainian) 2023-05-08 06:34:46 +02:00
Eugen Rochko
acd1e4ced3 New translations full_description.txt (Scottish Gaelic) 2023-05-06 07:17:18 +02:00
Eugen Rochko
6717070f93 New translations strings.xml (Scottish Gaelic) 2023-05-06 07:17:17 +02:00
Eugen Rochko
387499ae49 New translations strings.xml (Vietnamese) 2023-05-05 08:49:53 +02:00
Eugen Rochko
8ab140c55d New translations strings.xml (Japanese) 2023-05-04 22:50:38 +02:00
Eugen Rochko
914abb95dd New translations strings.xml (Japanese) 2023-05-04 21:34:45 +02:00
Eugen Rochko
5360c0f0f7 New translations strings.xml (Greek) 2023-05-04 01:44:50 +02:00
Eugen Rochko
243d803b51 New translations strings.xml (Turkish) 2023-05-03 23:31:14 +02:00
Eugen Rochko
b343fe3835 New translations strings.xml (Turkish) 2023-05-03 22:27:36 +02:00
Eugen Rochko
3c42c1120f New translations strings.xml (Japanese) 2023-05-03 17:42:48 +02:00
Eugen Rochko
ad840dcef6 New translations strings.xml (Japanese) 2023-05-03 16:47:22 +02:00
Eugen Rochko
f73072d95e New translations strings.xml (Spanish) 2023-05-03 01:08:32 +02:00
Eugen Rochko
95cb9b5079 New translations strings.xml (Thai) 2023-05-02 21:12:14 +02:00
Eugen Rochko
c6684d3c9b New translations strings.xml (Thai) 2023-05-02 19:41:48 +02:00
Eugen Rochko
5c5989d8c0 New translations strings.xml (Chinese Traditional) 2023-05-02 18:13:38 +02:00
Eugen Rochko
60e92d30b0 New translations strings.xml (Italian) 2023-05-02 14:58:27 +02:00
Eugen Rochko
8bf8e3f86b New translations strings.xml (Slovenian) 2023-05-02 00:17:51 +02:00
Eugen Rochko
891ee2d06b New translations strings.xml (Indonesian) 2023-05-01 21:04:03 +02:00
Eugen Rochko
b450bc7ae8 New translations strings.xml (Icelandic) 2023-05-01 21:04:02 +02:00
Eugen Rochko
4ca1e0d5db New translations strings.xml (Vietnamese) 2023-05-01 21:04:01 +02:00
Eugen Rochko
859213dd9e New translations strings.xml (Chinese Simplified) 2023-05-01 21:04:01 +02:00
Eugen Rochko
ad2857791d New translations strings.xml (Turkish) 2023-05-01 21:03:59 +02:00
Eugen Rochko
497827f2e2 New translations strings.xml (Slovenian) 2023-05-01 21:03:57 +02:00
Eugen Rochko
967e333022 New translations strings.xml (Japanese) 2023-05-01 21:03:54 +02:00
Eugen Rochko
8df1406006 New translations strings.xml (Dutch) 2023-05-01 21:03:46 +02:00
Eugen Rochko
4af42fafdc New translations strings.xml (Russian) 2023-05-01 21:03:45 +02:00
Eugen Rochko
a9e6a452c1 New translations strings.xml (Galician) 2023-05-01 21:03:43 +02:00
Eugen Rochko
a4a4632397 New translations strings.xml (Chinese Traditional) 2023-05-01 21:03:42 +02:00
Eugen Rochko
421f39e414 New translations strings.xml (Italian) 2023-05-01 21:03:41 +02:00
Eugen Rochko
f8121e2dc4 New translations strings.xml (German) 2023-05-01 21:03:41 +02:00
Eugen Rochko
b1784fc51c New translations strings.xml (Danish) 2023-05-01 21:03:40 +02:00
Eugen Rochko
96db0d7de7 New translations strings.xml (Greek) 2023-05-01 21:03:39 +02:00
Eugen Rochko
3837ed9cb1 New translations strings.xml (Thai) 2023-05-01 21:03:38 +02:00
Eugen Rochko
2be789a43c New translations strings.xml (Spanish) 2023-05-01 21:03:37 +02:00
Grishka
fd8d96169a Update string 2023-05-01 21:38:16 +03:00
Eugen Rochko
1562dc32c1 New translations strings.xml (Dutch) 2023-05-01 13:44:56 +02:00
Eugen Rochko
38f377ca09 New translations full_description.txt (Armenian) 2023-04-28 20:21:00 +02:00
Eugen Rochko
cc28bba884 New translations strings.xml (Armenian) 2023-04-28 20:20:59 +02:00
Eugen Rochko
beb3081918 New translations strings.xml (Armenian) 2023-04-28 19:06:20 +02:00
Eugen Rochko
1b3c9106b5 New translations strings.xml (Russian) 2023-04-28 09:05:19 +02:00
Eugen Rochko
385b91761b New translations strings.xml (Portuguese, Brazilian) 2023-04-28 02:45:25 +02:00
Eugen Rochko
43600756c0 New translations strings.xml (Chinese Traditional) 2023-04-25 18:41:49 +02:00
Eugen Rochko
3c3e0633ad New translations strings.xml (Danish) 2023-04-25 12:23:29 +02:00
Eugen Rochko
f819ad6917 New translations strings.xml (Danish) 2023-04-25 11:26:19 +02:00
Eugen Rochko
e7ad396fc6 New translations strings.xml (Italian) 2023-04-22 19:15:42 +02:00
Eugen Rochko
b1cb4d4257 New translations strings.xml (German) 2023-04-22 16:44:30 +02:00
Eugen Rochko
100bd4b062 New translations strings.xml (Galician) 2023-04-19 07:36:52 +02:00
Eugen Rochko
7da09d9b37 New translations strings.xml (Spanish) 2023-04-19 07:36:51 +02:00
Eugen Rochko
f46eb07228 New translations strings.xml (Galician) 2023-04-19 06:04:49 +02:00
Eugen Rochko
7627b5eb25 New translations strings.xml (Greek) 2023-04-17 15:01:08 +02:00
Eugen Rochko
c710448c6b New translations strings.xml (Greek) 2023-04-17 13:59:43 +02:00
Eugen Rochko
1ad270b1d6 New translations strings.xml (Chinese Simplified) 2023-04-16 18:13:11 +02:00
Eugen Rochko
099e253b2b New translations strings.xml (Chinese Simplified) 2023-04-16 17:11:48 +02:00
Eugen Rochko
66de4a5b91 New translations strings.xml (Thai) 2023-04-16 09:19:23 +02:00
Eugen Rochko
41437d91d5 New translations strings.xml (Icelandic) 2023-04-15 11:54:07 +02:00
Eugen Rochko
d33d5a6efa New translations strings.xml (Icelandic) 2023-04-15 10:45:31 +02:00
Eugen Rochko
4f9248d040 New translations strings.xml (Vietnamese) 2023-04-15 05:15:40 +02:00
Eugen Rochko
f40c0e41f3 New translations strings.xml (Japanese) 2023-04-14 20:26:49 +02:00
Eugen Rochko
deeb03ff2b New translations strings.xml (Indonesian) 2023-04-13 21:36:15 +02:00
Eugen Rochko
5c2a09e243 New translations strings.xml (Indonesian) 2023-04-13 20:38:20 +02:00
Eugen Rochko
2473c999db New translations strings.xml (German) 2023-04-13 14:38:33 +02:00
Eugen Rochko
ea2cc265e3 New translations strings.xml (Turkish) 2023-04-13 05:12:38 +02:00
Eugen Rochko
a0cd2d42cf New translations strings.xml (Turkish) 2023-04-13 04:16:05 +02:00
Grishka
0a17ceb984 Merge branch 'l10n_master' 2023-04-12 19:20:42 +03:00
Grishka
4ef18f1f4a Add touch interaction for the SplashFragment art 2023-04-12 19:20:23 +03:00
Grishka
0de227ab9c Use fixed colors for SplashFragment
fixes #561
2023-04-12 18:47:02 +03:00
Eugen Rochko
19cb8703a6 New translations strings.xml (Kabyle) 2023-04-12 17:37:10 +02:00
Eugen Rochko
e18567dd82 New translations strings.xml (Filipino) 2023-04-12 17:37:06 +02:00
Eugen Rochko
bfb3bcdbfb New translations strings.xml (Portuguese, Brazilian) 2023-04-12 17:37:02 +02:00
Eugen Rochko
565cd14d88 New translations strings.xml (Galician) 2023-04-12 17:37:00 +02:00
Eugen Rochko
ebc37eac75 New translations strings.xml (Vietnamese) 2023-04-12 17:36:59 +02:00
Eugen Rochko
c3702db577 New translations strings.xml (Chinese Traditional) 2023-04-12 17:36:59 +02:00
Eugen Rochko
e15c4fa342 New translations strings.xml (Chinese Simplified) 2023-04-12 17:36:58 +02:00
Eugen Rochko
8330b9f1c5 New translations strings.xml (Turkish) 2023-04-12 17:36:57 +02:00
Eugen Rochko
f759150982 New translations strings.xml (Swedish) 2023-04-12 17:36:56 +02:00
Eugen Rochko
6af177b596 New translations strings.xml (Slovenian) 2023-04-12 17:36:55 +02:00
Eugen Rochko
657bb94975 New translations strings.xml (Russian) 2023-04-12 17:36:54 +02:00
Eugen Rochko
3c946212b1 New translations strings.xml (Polish) 2023-04-12 17:36:52 +02:00
Eugen Rochko
b4e80f7fca New translations strings.xml (Norwegian) 2023-04-12 17:36:51 +02:00
Eugen Rochko
c9efc2cb2b New translations strings.xml (Korean) 2023-04-12 17:36:50 +02:00
Eugen Rochko
0d62e33dc7 New translations strings.xml (Japanese) 2023-04-12 17:36:49 +02:00
Eugen Rochko
ac88b9e19c New translations strings.xml (Italian) 2023-04-12 17:36:48 +02:00
Eugen Rochko
871dfda79e New translations strings.xml (Hungarian) 2023-04-12 17:36:47 +02:00
Eugen Rochko
e0c2c208ae New translations strings.xml (Basque) 2023-04-12 17:36:44 +02:00
Eugen Rochko
22ac112bdb New translations strings.xml (German) 2023-04-12 17:36:43 +02:00
Eugen Rochko
afd0cca176 New translations strings.xml (Danish) 2023-04-12 17:36:42 +02:00
Eugen Rochko
c083c8bce5 New translations strings.xml (Arabic) 2023-04-12 17:36:41 +02:00
Eugen Rochko
63bde032b3 New translations strings.xml (French) 2023-04-12 17:36:40 +02:00
Eugen Rochko
49492c0788 New translations strings.xml (Belarusian) 2023-04-12 17:36:38 +02:00
Eugen Rochko
b439c64add New translations strings.xml (Greek) 2023-04-12 17:36:37 +02:00
Eugen Rochko
1868bfe8e3 New translations strings.xml (Thai) 2023-04-12 17:36:36 +02:00
Eugen Rochko
f240a3d996 New translations strings.xml (Indonesian) 2023-04-12 17:36:35 +02:00
Eugen Rochko
788e5bd12e New translations strings.xml (Icelandic) 2023-04-12 17:36:34 +02:00
Eugen Rochko
a55fed4502 New translations strings.xml (Ukrainian) 2023-04-12 17:36:33 +02:00
Eugen Rochko
a8fdaf1a47 New translations strings.xml (Dutch) 2023-04-12 17:36:32 +02:00
Eugen Rochko
4a758bd488 New translations strings.xml (Czech) 2023-04-12 17:36:31 +02:00
Eugen Rochko
2c9731ec2a New translations strings.xml (Spanish) 2023-04-12 17:36:30 +02:00
Grishka
eef33266fc Remove unused code and strings 2023-04-12 18:34:28 +03:00
Eugen Rochko
58d2c3e5a6 New translations strings.xml (Indonesian) 2023-04-11 17:28:22 +02:00
Eugen Rochko
9e6a355db0 New translations strings.xml (Slovenian) 2023-04-10 00:54:45 +02:00
Eugen Rochko
0d10e09fd6 New translations strings.xml (Slovenian) 2023-04-09 23:47:00 +02:00
Eugen Rochko
f85bb995ba New translations strings.xml (Greek) 2023-04-09 17:56:44 +02:00
Eugen Rochko
268e5639f6 New translations strings.xml (Greek) 2023-04-09 16:26:19 +02:00
Eugen Rochko
51809df8ca New translations strings.xml (Thai) 2023-04-09 07:25:51 +02:00
Eugen Rochko
94fb676b0c New translations strings.xml (Chinese Traditional) 2023-04-09 04:29:35 +02:00
Eugen Rochko
a47106594b New translations strings.xml (Chinese Traditional) 2023-04-09 03:10:02 +02:00
Grishka
d93d66f702 Prepare new release 2023-04-09 01:59:13 +03:00
Eugen Rochko
b2f9f7ae54 New translations strings.xml (Italian) 2023-04-09 00:51:05 +02:00
Grishka
de7b908c78 Merge branch 'l10n_master' 2023-04-09 01:50:55 +03:00
Eugen Rochko
75d3c2fdce New translations strings.xml (Italian) 2023-04-08 23:55:36 +02:00
Eugen Rochko
ea1b6c5835 New translations strings.xml (Greek) 2023-04-08 22:51:05 +02:00
Eugen Rochko
cb7887da41 New translations strings.xml (Greek) 2023-04-08 21:38:06 +02:00
Eugen Rochko
a80313ee6b New translations strings.xml (Thai) 2023-04-07 23:53:35 +02:00
Eugen Rochko
e1a821bc43 New translations strings.xml (Thai) 2023-04-07 22:56:50 +02:00
Grishka
924ea2d03a Fix #557 2023-04-07 22:58:04 +03:00
Grishka
55270fe654 Fix 2023-04-07 22:55:29 +03:00
Eugen Rochko
a125fab57b New translations strings.xml (Kabyle) 2023-04-07 21:48:05 +02:00
Eugen Rochko
395ee0aa99 New translations strings.xml (Scottish Gaelic) 2023-04-07 21:48:03 +02:00
Eugen Rochko
0f50fa6ba1 New translations strings.xml (Bosnian) 2023-04-07 21:48:01 +02:00
Eugen Rochko
adb7df3c71 New translations strings.xml (Filipino) 2023-04-07 21:48:00 +02:00
Eugen Rochko
5d7bcb629b New translations strings.xml (Burmese) 2023-04-07 21:47:59 +02:00
Eugen Rochko
a00f1417d2 New translations strings.xml (Hindi) 2023-04-07 21:47:59 +02:00
Eugen Rochko
8efd7e8ebf New translations strings.xml (Croatian) 2023-04-07 21:47:58 +02:00
Eugen Rochko
b016d277e0 New translations strings.xml (Bengali) 2023-04-07 21:47:57 +02:00
Eugen Rochko
fdb39617d1 New translations strings.xml (Persian) 2023-04-07 21:47:56 +02:00
Eugen Rochko
89f83fbf62 New translations strings.xml (Portuguese, Brazilian) 2023-04-07 21:47:55 +02:00
Eugen Rochko
ecee9e01a6 New translations strings.xml (Galician) 2023-04-07 21:47:54 +02:00
Eugen Rochko
20dc9bb8b9 New translations strings.xml (Vietnamese) 2023-04-07 21:47:53 +02:00
Eugen Rochko
2c47d0e9ed New translations strings.xml (Chinese Traditional) 2023-04-07 21:47:52 +02:00
Eugen Rochko
8e13d52e51 New translations strings.xml (Chinese Simplified) 2023-04-07 21:47:51 +02:00
Eugen Rochko
cc40198c9e New translations strings.xml (Turkish) 2023-04-07 21:47:50 +02:00
Eugen Rochko
290897ea41 New translations strings.xml (Swedish) 2023-04-07 21:47:49 +02:00
Eugen Rochko
b9e1c84304 New translations strings.xml (Slovenian) 2023-04-07 21:47:48 +02:00
Eugen Rochko
3c44c80e2e New translations strings.xml (Russian) 2023-04-07 21:47:47 +02:00
Eugen Rochko
dffa4e4594 New translations strings.xml (Portuguese) 2023-04-07 21:47:46 +02:00
Eugen Rochko
fa2d9fec58 New translations strings.xml (Polish) 2023-04-07 21:47:45 +02:00
Eugen Rochko
09c1a2cfa0 New translations strings.xml (Norwegian) 2023-04-07 21:47:44 +02:00
Eugen Rochko
d1f90eb231 New translations strings.xml (Korean) 2023-04-07 21:47:42 +02:00
Eugen Rochko
1f7d97134b New translations strings.xml (Japanese) 2023-04-07 21:47:42 +02:00
Eugen Rochko
79be91784d New translations strings.xml (Italian) 2023-04-07 21:47:41 +02:00
Eugen Rochko
de2654def3 New translations strings.xml (Hungarian) 2023-04-07 21:47:39 +02:00
Eugen Rochko
56343dacff New translations strings.xml (Hebrew) 2023-04-07 21:47:38 +02:00
Eugen Rochko
0e677f8ce7 New translations strings.xml (Basque) 2023-04-07 21:47:36 +02:00
Eugen Rochko
aa911896d6 New translations strings.xml (German) 2023-04-07 21:47:35 +02:00
Eugen Rochko
c62a8635b9 New translations strings.xml (Danish) 2023-04-07 21:47:34 +02:00
Eugen Rochko
4e900247c5 New translations strings.xml (Catalan) 2023-04-07 21:47:33 +02:00
Eugen Rochko
b3bd62bc6c New translations strings.xml (Arabic) 2023-04-07 21:47:32 +02:00
Eugen Rochko
8e5fd48ecd New translations strings.xml (French) 2023-04-07 21:47:31 +02:00
Eugen Rochko
b2bca9dd2c New translations strings.xml (Romanian) 2023-04-07 21:47:30 +02:00
Eugen Rochko
b8c0dc3181 New translations strings.xml (Belarusian) 2023-04-07 21:47:29 +02:00
Eugen Rochko
cccdc5292e New translations strings.xml (Greek) 2023-04-07 21:47:28 +02:00
Eugen Rochko
76d77a0e7a New translations strings.xml (Thai) 2023-04-07 21:47:27 +02:00
Eugen Rochko
e737f4bf9a New translations strings.xml (Indonesian) 2023-04-07 21:47:26 +02:00
Eugen Rochko
391db2f1c9 New translations strings.xml (Icelandic) 2023-04-07 21:47:25 +02:00
Eugen Rochko
359d61183c New translations strings.xml (Ukrainian) 2023-04-07 21:47:24 +02:00
Eugen Rochko
46fd05d88e New translations strings.xml (Dutch) 2023-04-07 21:47:23 +02:00
Eugen Rochko
cde22a0945 New translations strings.xml (Czech) 2023-04-07 21:47:22 +02:00
Eugen Rochko
111b7e25c5 New translations strings.xml (Spanish) 2023-04-07 21:47:21 +02:00
Grishka
4f8d8f0c8d Welcome fragment redesign again
# Conflicts:
#	mastodon/src/main/res/values/strings.xml
#	mastodon/src/main/res/values/styles.xml
2023-04-07 22:44:28 +03:00
Grishka
915b0603d0 Reblog -> boost 2023-04-07 22:42:16 +03:00
Eugen Rochko
075aab8074 New translations strings.xml (Greek) 2023-04-07 16:16:35 +02:00
Eugen Rochko
6ebe4c86af New translations strings.xml (Greek) 2023-04-07 15:16:19 +02:00
Eugen Rochko
0925c8c582 New translations strings.xml (Spanish) 2023-04-06 21:52:50 +02:00
Eugen Rochko
a683fdce62 New translations strings.xml (Greek) 2023-04-06 18:46:34 +02:00
Eugen Rochko
b958299446 New translations strings.xml (Greek) 2023-04-06 17:45:19 +02:00
Eugen Rochko
3f80be8377 New translations strings.xml (Greek) 2023-04-05 16:29:26 +02:00
Eugen Rochko
ced0accde5 New translations strings.xml (Belarusian) 2023-04-05 12:06:47 +02:00
Eugen Rochko
b454ff5ec7 New translations strings.xml (Belarusian) 2023-04-05 11:07:06 +02:00
Eugen Rochko
45af198f32 New translations strings.xml (Greek) 2023-04-05 02:04:08 +02:00
Eugen Rochko
ff374f8899 New translations strings.xml (Greek) 2023-04-05 00:46:17 +02:00
Eugen Rochko
faecb3bc4b New translations strings.xml (Greek) 2023-04-04 20:21:01 +02:00
Eugen Rochko
6b893fadef New translations short_description.txt (Greek) 2023-04-04 17:47:01 +02:00
Eugen Rochko
c328467a41 New translations strings.xml (Greek) 2023-04-04 17:47:00 +02:00
Eugen Rochko
182325470b New translations full_description.txt (Greek) 2023-04-04 17:46:59 +02:00
Eugen Rochko
f330ad71ac New translations full_description.txt (Greek) 2023-04-04 16:06:32 +02:00
Eugen Rochko
ba0c064f36 New translations full_description.txt (Chinese Traditional) 2023-04-03 16:47:01 +02:00
Eugen Rochko
8d7aaee5b9 New translations strings.xml (Dutch) 2023-04-01 15:16:39 +02:00
Eugen Rochko
68cba2de63 New translations strings.xml (Icelandic) 2023-03-29 00:29:42 +02:00
Eugen Rochko
5a914f9c0e New translations strings.xml (Thai) 2023-03-28 21:06:33 +02:00
Eugen Rochko
b0e6805a20 New translations strings.xml (Czech) 2023-03-28 16:34:35 +02:00
Eugen Rochko
21e7e44c01 New translations strings.xml (Czech) 2023-03-28 15:36:30 +02:00
Eugen Rochko
f7df4abdae New translations strings.xml (Spanish) 2023-03-26 17:05:29 +02:00
Eugen Rochko
7674ceefe9 New translations strings.xml (Ukrainian) 2023-03-25 20:42:18 +01:00
Eugen Rochko
4be575c534 New translations strings.xml (Ukrainian) 2023-03-25 19:25:16 +01:00
Eugen Rochko
dd0f0a7d5a New translations strings.xml (Indonesian) 2023-03-25 04:22:02 +01:00
Eugen Rochko
759b44c224 New translations strings.xml (Indonesian) 2023-03-25 03:16:02 +01:00
Eugen Rochko
920384b26c New translations strings.xml (Dutch) 2023-03-24 16:26:08 +01:00
Eugen Rochko
193a2c4f70 New translations strings.xml (German) 2023-03-23 13:42:28 +01:00
Eugen Rochko
793dec98b2 New translations strings.xml (Vietnamese) 2023-03-23 07:36:02 +01:00
Eugen Rochko
11ddf8015d New translations strings.xml (Galician) 2023-03-23 05:17:18 +01:00
Eugen Rochko
1753bdbd8b New translations strings.xml (Thai) 2023-03-22 17:21:08 +01:00
Grishka
d6e563486b Fix alt text button 2023-03-22 02:46:48 +03:00
Grishka
0112bfa9c4 Fix #547 2023-03-22 02:38:58 +03:00
Grishka
5951611fb0 Fix #551 2023-03-22 02:34:25 +03:00
Eugen Rochko
cc8c818e13 New translations strings.xml (Slovenian) 2023-03-21 11:52:06 +01:00
Eugen Rochko
2e1f273d78 New translations strings.xml (Chinese Traditional) 2023-03-21 06:38:54 +01:00
Eugen Rochko
35d6800877 New translations strings.xml (Chinese Traditional) 2023-03-21 05:17:21 +01:00
Eugen Rochko
91e154bbee New translations strings.xml (Italian) 2023-03-20 20:01:49 +01:00
Eugen Rochko
0c02b0cb68 New translations strings.xml (Dutch) 2023-03-20 18:49:16 +01:00
Gregory K
b0aaa58fa7 Merge pull request #550 from sk22/fix/header-follow-protected-account
Fix following protected account from header
2023-03-20 20:36:11 +03:00
sk
8ca33b552d fix following protected account from header
closes mastodon#549
2023-03-20 18:23:49 +01:00
Gregory K
5e4e56bd2c Merge pull request #545 from FineFindus/fix/empty-search-query
fix(search): check for empty queries
2023-03-17 20:10:02 +03:00
FineFindus
82fac1d4e7 fix(search): check for empty queries
Fixes an error message, which would appear, if the search query was blank.
2023-03-17 16:19:38 +01:00
Grishka
d6bcc9c156 Fix button color 2023-03-14 07:31:01 +03:00
Grishka
fc67c82040 Fix #544 2023-03-13 20:46:29 +03:00
Eugen Rochko
a9b828001c New translations strings.xml (Burmese) 2023-03-13 15:08:41 +01:00
Eugen Rochko
be050abf7e New translations strings.xml (Burmese) 2023-03-13 14:01:13 +01:00
Eugen Rochko
2d071ca252 New translations strings.xml (Burmese) 2023-03-13 12:53:22 +01:00
Eugen Rochko
abf94e1e70 New translations strings.xml (Burmese) 2023-03-13 10:01:18 +01:00
Eugen Rochko
2991c7421c New translations strings.xml (Burmese) 2023-03-13 08:59:13 +01:00
Eugen Rochko
834f84f995 New translations strings.xml (Burmese) 2023-03-13 07:58:41 +01:00
Eugen Rochko
6bf713c96c New translations strings.xml (Polish) 2023-03-13 00:35:08 +01:00
Eugen Rochko
72b16be297 New translations strings.xml (Swedish) 2023-03-12 21:53:57 +01:00
Eugen Rochko
0c7f27b3ac New translations strings.xml (Swedish) 2023-03-12 20:47:06 +01:00
Eugen Rochko
ca101748eb New translations strings.xml (Belarusian) 2023-03-11 23:37:17 +01:00
Eugen Rochko
3584c123d6 New translations strings.xml (Belarusian) 2023-03-11 22:33:13 +01:00
Eugen Rochko
a2fd4be339 New translations title.txt (Urdu (India)) 2023-03-11 14:05:49 +01:00
Eugen Rochko
656364db60 New translations short_description.txt (Urdu (India)) 2023-03-11 14:05:48 +01:00
Eugen Rochko
884347da12 New translations full_description.txt (Urdu (India)) 2023-03-11 14:05:47 +01:00
Eugen Rochko
675c49a922 New translations strings.xml (Urdu (India)) 2023-03-11 14:05:46 +01:00
Eugen Rochko
a3146d6cdd New translations full_description.txt (Belarusian) 2023-03-11 09:12:18 +01:00
Eugen Rochko
d769f757ed New translations full_description.txt (Belarusian) 2023-03-11 08:04:43 +01:00
Eugen Rochko
654e3eb36b New translations strings.xml (Japanese) 2023-03-09 23:29:35 +01:00
Eugen Rochko
f62ba685d1 New translations strings.xml (Japanese) 2023-03-09 14:07:24 +01:00
Grishka
c3aa3af650 Fix #540 2023-03-08 22:46:24 +03:00
Eugen Rochko
8cc5678b38 New translations strings.xml (Japanese) 2023-03-08 11:02:08 +01:00
Eugen Rochko
592eb2d589 New translations strings.xml (Japanese) 2023-03-08 02:55:58 +01:00
Eugen Rochko
0bf31de1f1 New translations strings.xml (Japanese) 2023-03-06 21:23:36 +01:00
Eugen Rochko
7fd32cab3d New translations strings.xml (Japanese) 2023-03-06 19:38:06 +01:00
Grishka
4a695b2a83 Use a single display item for the image attachment grid 2023-03-06 02:25:13 +03:00
Grishka
a8ba50e762 Merge branch 'dev_clickable_links_hold_to_copy' 2023-03-05 22:33:35 +03:00
Grishka
f79fc66578 Fix 2023-03-05 22:33:18 +03:00
Eugen Rochko
0c63b99e6c New translations strings.xml (Japanese) 2023-03-05 02:15:44 +01:00
Eugen Rochko
5881f5fa05 New translations strings.xml (Japanese) 2023-03-05 01:20:11 +01:00
Eugen Rochko
575ca6251c New translations strings.xml (Arabic) 2023-03-03 20:35:51 +01:00
Eugen Rochko
9c83a5aaeb New translations strings.xml (Portuguese, Brazilian) 2023-03-02 15:21:36 +01:00
Eugen Rochko
bc3e46eae1 New translations strings.xml (Portuguese, Brazilian) 2023-03-02 14:20:26 +01:00
Eugen Rochko
0303e59fc1 New translations strings.xml (Bengali) 2023-02-28 16:38:40 +01:00
Eugen Rochko
0c0d36da62 New translations strings.xml (Bengali) 2023-02-28 13:32:43 +01:00
Eugen Rochko
e7e0b8841c New translations strings.xml (Bengali) 2023-02-28 12:21:52 +01:00
Eugen Rochko
79d9abe7f7 New translations full_description.txt (Turkish) 2023-02-27 17:26:40 +01:00
Eugen Rochko
684fbc0050 New translations strings.xml (Turkish) 2023-02-27 17:26:39 +01:00
Eugen Rochko
03973d41be New translations strings.xml (Turkish) 2023-02-27 16:25:31 +01:00
Eugen Rochko
06c533bf5a New translations full_description.txt (Japanese) 2023-02-27 08:35:37 +01:00
Eugen Rochko
cc64a20e53 New translations full_description.txt (Japanese) 2023-02-27 07:28:37 +01:00
Torge Rosendahl
4144639b75 docu 2023-02-26 13:59:39 -05:00
Eugen Rochko
d633b6f1d4 New translations strings.xml (Bengali) 2023-02-25 16:06:21 +01:00
Eugen Rochko
7b68baef0d New translations strings.xml (Bengali) 2023-02-25 13:06:26 +01:00
Eugen Rochko
fb5ef921f7 New translations strings.xml (Spanish) 2023-02-24 21:22:35 +01:00
Eugen Rochko
da44e50679 New translations strings.xml (Spanish) 2023-02-24 19:50:53 +01:00
Eugen Rochko
93d89f93b2 New translations strings.xml (Bengali) 2023-02-24 09:17:38 +01:00
Eugen Rochko
cce64f9a76 New translations strings.xml (Bengali) 2023-02-24 08:19:59 +01:00
Eugen Rochko
afb396acd8 New translations strings.xml (Chinese Traditional) 2023-02-22 18:07:34 +01:00
Eugen Rochko
0943908173 New translations strings.xml (Kabyle) 2023-02-20 08:34:11 +01:00
Eugen Rochko
b018788cd1 New translations strings.xml (Galician) 2023-02-19 22:35:48 +01:00
Eugen Rochko
4a315e73eb New translations strings.xml (Galician) 2023-02-19 21:34:24 +01:00
Eugen Rochko
b01ef6d5a7 New translations short_description.txt (Russian) 2023-02-17 10:01:43 +01:00
Eugen Rochko
604e581139 New translations full_description.txt (Russian) 2023-02-17 10:01:42 +01:00
Eugen Rochko
082f697b40 New translations strings.xml (Russian) 2023-02-17 10:01:41 +01:00
Torge Rosendahl
0a8d73dc0b cleanup, resolved some warnings 2023-02-15 20:19:10 -05:00
Torge Rosendahl
fd99f3caa1 changed url longclick implementation to GestureListener 2023-02-15 20:16:20 -05:00
Torge Rosendahl
794c4e5227 removed longClickHandler and moved to view itself 2023-02-15 19:54:08 -05:00
Torge Rosendahl
f5df8225d1 whitespace corrections 2023-02-15 18:20:02 -05:00
Torge Rosendahl
42c6446125 refactoring: moved runnable and made it private, added copy toast localization. 2023-02-15 18:04:52 -05:00
Torge Rosendahl
e3486ebf7c added clickable link type switch for copy, to not copy hashtags and user IDs 2023-02-15 18:00:45 -05:00
Torge Rosendahl
c0115f068c implemented copy service 2023-02-15 17:40:43 -05:00
Torge Rosendahl
41682d1147 added press-and-hold listener to ClickableLinks 2023-02-15 17:30:31 -05:00
Eugen Rochko
8c61660cfc New translations strings.xml (Arabic) 2023-02-15 15:17:22 +01:00
Eugen Rochko
d6933be3cd New translations strings.xml (Arabic) 2023-02-15 13:12:38 +01:00
Eugen Rochko
ca6cfd2b91 New translations strings.xml (French) 2023-02-14 20:11:52 +01:00
Eugen Rochko
20960bdd57 New translations strings.xml (Belarusian) 2023-02-14 14:14:56 +01:00
Grishka
dd582c4bee Update locales & bump version 2023-02-14 03:57:49 +03:00
Grishka
3a0d314af0 Merge branch 'l10n_master' 2023-02-14 03:49:36 +03:00
Eugen Rochko
3b26dd44a0 New translations strings.xml (Arabic) 2023-02-13 09:09:52 +01:00
Grishka
634408b8cb Minor onboarding tweaks 2023-02-12 14:25:03 +03:00
Grishka
f050e3f22d Fix #500 2023-02-12 04:03:09 +03:00
Grishka
8e9531b718 Fix #528 2023-02-12 03:58:24 +03:00
Grishka
64fbbb2f07 Minor onboarding stuff 2023-02-10 21:09:06 +03:00
Eugen Rochko
9003f690d1 New translations strings.xml (French) 2023-02-10 14:16:02 +01:00
Eugen Rochko
8ffaca61bd New translations strings.xml (Portuguese, Brazilian) 2023-02-08 22:57:10 +01:00
Eugen Rochko
f6c3b10c2b New translations strings.xml (Portuguese, Brazilian) 2023-02-08 20:46:53 +01:00
Eugen Rochko
d68a3a6ef5 New translations strings.xml (Polish) 2023-02-05 18:37:14 +01:00
Eugen Rochko
4475bd039a New translations strings.xml (Hungarian) 2023-02-05 10:32:04 +01:00
Eugen Rochko
98dc7d0524 New translations strings.xml (Hungarian) 2023-02-05 09:17:45 +01:00
Eugen Rochko
65948030a6 New translations strings.xml (Russian) 2023-02-04 14:07:29 +01:00
Eugen Rochko
89edfaaa6d New translations strings.xml (Russian) 2023-02-04 13:11:55 +01:00
Eugen Rochko
10372804e4 New translations strings.xml (Thai) 2023-02-04 09:10:51 +01:00
Eugen Rochko
d1dd7d203b New translations strings.xml (German) 2023-02-03 18:47:42 +01:00
Eugen Rochko
c6aed0b52e New translations strings.xml (French) 2023-02-03 16:09:58 +01:00
Eugen Rochko
5f902d25a9 New translations strings.xml (Basque) 2023-02-03 12:29:06 +01:00
Eugen Rochko
c43bed665d New translations strings.xml (Catalan) 2023-02-03 12:29:05 +01:00
Eugen Rochko
d70a2ae5b3 New translations strings.xml (Russian) 2023-02-03 10:03:24 +01:00
Eugen Rochko
1fdf36b4d8 New translations strings.xml (Portuguese, Brazilian) 2023-02-03 09:05:37 +01:00
Eugen Rochko
5d1cd0f4f6 New translations strings.xml (Vietnamese) 2023-02-02 07:01:44 +01:00
Eugen Rochko
3505460372 New translations strings.xml (Chinese Traditional) 2023-02-01 03:56:06 +01:00
Eugen Rochko
eeb91e867e New translations strings.xml (Chinese Traditional) 2023-02-01 02:54:48 +01:00
Eugen Rochko
c87062ee31 New translations strings.xml (Slovenian) 2023-01-31 21:33:54 +01:00
Eugen Rochko
fb66fa1c6f New translations strings.xml (Italian) 2023-01-31 20:07:33 +01:00
Eugen Rochko
f80af9f5bf New translations strings.xml (Italian) 2023-01-31 18:30:56 +01:00
Eugen Rochko
85157ffe25 New translations strings.xml (Thai) 2023-01-31 17:27:18 +01:00
Eugen Rochko
59f95159b7 New translations strings.xml (German) 2023-01-31 13:41:46 +01:00
Eugen Rochko
703dbd4c8a New translations strings.xml (Portuguese, Brazilian) 2023-01-31 07:47:05 +01:00
Eugen Rochko
1e75f9f1c2 New translations strings.xml (Dutch) 2023-01-30 23:35:25 +01:00
Eugen Rochko
d0860333a9 New translations strings.xml (Dutch) 2023-01-30 22:36:37 +01:00
Eugen Rochko
64b3951c25 New translations strings.xml (German) 2023-01-30 18:52:51 +01:00
Eugen Rochko
e89e6cc3f5 New translations strings.xml (Icelandic) 2023-01-30 11:40:53 +01:00
Eugen Rochko
3c2985fa6e New translations strings.xml (Icelandic) 2023-01-30 10:39:01 +01:00
Eugen Rochko
bee01429f2 New translations full_description.txt (Portuguese, Brazilian) 2023-01-30 05:41:59 +01:00
Eugen Rochko
a96431cc00 New translations strings.xml (Portuguese, Brazilian) 2023-01-30 05:41:58 +01:00
Eugen Rochko
bf9e6f54cf New translations strings.xml (Portuguese, Brazilian) 2023-01-30 04:35:45 +01:00
Eugen Rochko
63084857a3 New translations strings.xml (Kabyle) 2023-01-30 00:02:18 +01:00
Eugen Rochko
d8b7038972 New translations strings.xml (Occitan) 2023-01-30 00:02:18 +01:00
Eugen Rochko
976e71db25 New translations strings.xml (Scottish Gaelic) 2023-01-30 00:02:17 +01:00
Eugen Rochko
2b59c2c080 New translations strings.xml (Sinhala) 2023-01-30 00:02:16 +01:00
Eugen Rochko
5929b0c6b9 New translations strings.xml (Bosnian) 2023-01-30 00:02:15 +01:00
Eugen Rochko
e160a05411 New translations strings.xml (Filipino) 2023-01-30 00:02:14 +01:00
Eugen Rochko
78d8f075a9 New translations strings.xml (Burmese) 2023-01-30 00:02:13 +01:00
Eugen Rochko
3784873cad New translations strings.xml (Hindi) 2023-01-30 00:02:12 +01:00
Eugen Rochko
528f8aaead New translations strings.xml (Croatian) 2023-01-30 00:02:11 +01:00
Eugen Rochko
4ba9f1ecaf New translations strings.xml (Thai) 2023-01-30 00:02:10 +01:00
Eugen Rochko
697a666545 New translations strings.xml (Bengali) 2023-01-30 00:02:09 +01:00
Eugen Rochko
0ee6798424 New translations strings.xml (Persian) 2023-01-30 00:02:08 +01:00
Eugen Rochko
9a95deb346 New translations strings.xml (Indonesian) 2023-01-30 00:02:07 +01:00
Eugen Rochko
0155ef2675 New translations strings.xml (Icelandic) 2023-01-30 00:02:06 +01:00
Eugen Rochko
858195f813 New translations strings.xml (Vietnamese) 2023-01-30 00:02:06 +01:00
Eugen Rochko
b681c7dfeb New translations strings.xml (Chinese Traditional) 2023-01-30 00:02:05 +01:00
Eugen Rochko
b89f931ffd New translations strings.xml (Galician) 2023-01-30 00:02:04 +01:00
Eugen Rochko
1658e56729 New translations strings.xml (Igbo) 2023-01-30 00:02:03 +01:00
Eugen Rochko
2b7d8292ed New translations strings.xml (Portuguese, Brazilian) 2023-01-30 00:02:02 +01:00
Eugen Rochko
494abdfeee New translations strings.xml (Chinese Simplified) 2023-01-30 00:02:01 +01:00
Eugen Rochko
426f3fe95b New translations strings.xml (Ukrainian) 2023-01-30 00:02:00 +01:00
Eugen Rochko
b7a96778b8 New translations strings.xml (Swedish) 2023-01-30 00:01:59 +01:00
Eugen Rochko
125cd525bf New translations strings.xml (Slovenian) 2023-01-30 00:01:58 +01:00
Eugen Rochko
ed281a4619 New translations strings.xml (Russian) 2023-01-30 00:01:58 +01:00
Eugen Rochko
f418a5a2c4 New translations strings.xml (Portuguese) 2023-01-30 00:01:57 +01:00
Eugen Rochko
6d8971df64 New translations strings.xml (Dutch) 2023-01-30 00:01:56 +01:00
Eugen Rochko
8dd3343906 New translations strings.xml (Korean) 2023-01-30 00:01:55 +01:00
Eugen Rochko
f65fc9299a New translations strings.xml (Japanese) 2023-01-30 00:01:54 +01:00
Eugen Rochko
ac00889001 New translations strings.xml (Italian) 2023-01-30 00:01:53 +01:00
Eugen Rochko
7af0a3f351 New translations strings.xml (Armenian) 2023-01-30 00:01:52 +01:00
Eugen Rochko
2734f88206 New translations strings.xml (Hebrew) 2023-01-30 00:01:51 +01:00
Eugen Rochko
c6cd8ca14b New translations strings.xml (Irish) 2023-01-30 00:01:50 +01:00
Eugen Rochko
2fd61f738f New translations strings.xml (Finnish) 2023-01-30 00:01:50 +01:00
Eugen Rochko
d3575b60fe New translations strings.xml (Basque) 2023-01-30 00:01:49 +01:00
Eugen Rochko
dce8808d62 New translations strings.xml (Greek) 2023-01-30 00:01:48 +01:00
Eugen Rochko
db97dadb25 New translations strings.xml (German) 2023-01-30 00:01:47 +01:00
Eugen Rochko
34116d9914 New translations strings.xml (Danish) 2023-01-30 00:01:46 +01:00
Eugen Rochko
bc676e6eb3 New translations strings.xml (Catalan) 2023-01-30 00:01:45 +01:00
Eugen Rochko
ef2cb31b6c New translations strings.xml (Arabic) 2023-01-30 00:01:44 +01:00
Eugen Rochko
c45dc96316 New translations strings.xml (French) 2023-01-30 00:01:43 +01:00
Eugen Rochko
f9b34b53c1 New translations strings.xml (Romanian) 2023-01-30 00:01:42 +01:00
Eugen Rochko
e128e144b1 New translations strings.xml (Turkish) 2023-01-30 00:01:41 +01:00
Eugen Rochko
c68ed6088f New translations strings.xml (Spanish) 2023-01-30 00:01:40 +01:00
Eugen Rochko
b66ad0e6f5 New translations strings.xml (Polish) 2023-01-30 00:01:39 +01:00
Eugen Rochko
02a470bd7d New translations strings.xml (Belarusian) 2023-01-30 00:01:39 +01:00
Eugen Rochko
9407bd9e86 New translations strings.xml (Hungarian) 2023-01-30 00:01:38 +01:00
Eugen Rochko
825adda664 New translations strings.xml (Czech) 2023-01-30 00:01:37 +01:00
Eugen Rochko
0a22c14eec New translations strings.xml (Norwegian) 2023-01-30 00:01:35 +01:00
Gregory K
5c2f72a706 Merge pull request #521 from FineFindus/fix/typos
fix: typos
2023-01-30 01:54:30 +03:00
Grishka
b153a64373 Signup flow redesign WIP 2023-01-30 01:54:13 +03:00
Eugen Rochko
5452da6a65 New translations strings.xml (German) 2023-01-29 22:55:32 +01:00
Eugen Rochko
ffb321e36f New translations strings.xml (German) 2023-01-29 21:52:09 +01:00
Eugen Rochko
eaecff52c9 New translations strings.xml (Portuguese, Brazilian) 2023-01-29 21:52:08 +01:00
Eugen Rochko
b141a9ac74 New translations strings.xml (Portuguese, Brazilian) 2023-01-29 18:37:47 +01:00
Eugen Rochko
a890f21ace New translations strings.xml (Polish) 2023-01-28 23:17:50 +01:00
Eugen Rochko
4e72e5c234 New translations strings.xml (Polish) 2023-01-28 22:19:28 +01:00
Eugen Rochko
1def56057a New translations strings.xml (Vietnamese) 2023-01-28 15:42:21 +01:00
Eugen Rochko
d99f6c7167 New translations strings.xml (Vietnamese) 2023-01-28 14:39:22 +01:00
Eugen Rochko
0d5d169e5f New translations strings.xml (Korean) 2023-01-28 01:46:35 +01:00
Eugen Rochko
90e55c1043 New translations strings.xml (Korean) 2023-01-28 00:36:07 +01:00
Eugen Rochko
780c5c345c New translations strings.xml (Spanish) 2023-01-27 17:31:12 +01:00
Eugen Rochko
c2bc0a4055 New translations strings.xml (Dutch) 2023-01-27 14:07:08 +01:00
FineFindus
1124486f1f fix(Instance): typo langauges => languages 2023-01-26 20:56:15 +01:00
Eugen Rochko
8032de4595 New translations strings.xml (Ukrainian) 2023-01-26 19:50:28 +01:00
Eugen Rochko
bd3f5018ed New translations strings.xml (Ukrainian) 2023-01-26 18:48:15 +01:00
Eugen Rochko
91c4e5e51f New translations strings.xml (Thai) 2023-01-26 14:50:19 +01:00
Eugen Rochko
ca1cb668f3 New translations strings.xml (Chinese Traditional) 2023-01-26 06:12:30 +01:00
Eugen Rochko
a12ca697ed New translations strings.xml (Arabic) 2023-01-26 06:12:29 +01:00
Eugen Rochko
3ccb629a4e New translations strings.xml (Kabyle) 2023-01-25 23:45:26 +01:00
Eugen Rochko
4db041c28f New translations strings.xml (Occitan) 2023-01-25 23:45:25 +01:00
Eugen Rochko
bdcf4a5438 New translations strings.xml (Scottish Gaelic) 2023-01-25 23:45:24 +01:00
Eugen Rochko
c042050295 New translations strings.xml (Sinhala) 2023-01-25 23:45:23 +01:00
Eugen Rochko
f87a87aba1 New translations strings.xml (Bosnian) 2023-01-25 23:45:22 +01:00
Eugen Rochko
b3a88c4a7c New translations strings.xml (Filipino) 2023-01-25 23:45:21 +01:00
Eugen Rochko
9729663cb4 New translations strings.xml (Burmese) 2023-01-25 23:45:20 +01:00
Eugen Rochko
f66e6197d3 New translations strings.xml (Hindi) 2023-01-25 23:45:19 +01:00
Eugen Rochko
4ff940030d New translations strings.xml (Croatian) 2023-01-25 23:45:18 +01:00
Eugen Rochko
da8b88dfc6 New translations strings.xml (Thai) 2023-01-25 23:45:17 +01:00
Eugen Rochko
ed13b1074d New translations strings.xml (Bengali) 2023-01-25 23:45:16 +01:00
Eugen Rochko
c5e985f6a4 New translations strings.xml (Persian) 2023-01-25 23:45:15 +01:00
Eugen Rochko
160bb4e272 New translations strings.xml (Indonesian) 2023-01-25 23:45:14 +01:00
Eugen Rochko
f89a3e644a New translations strings.xml (Icelandic) 2023-01-25 23:45:13 +01:00
Eugen Rochko
4cfd0db899 New translations strings.xml (Vietnamese) 2023-01-25 23:45:12 +01:00
Eugen Rochko
c6cb992b92 New translations strings.xml (Chinese Traditional) 2023-01-25 23:45:11 +01:00
Eugen Rochko
1b3ea6cdbe New translations strings.xml (Chinese Simplified) 2023-01-25 23:45:10 +01:00
Eugen Rochko
79323e392b New translations strings.xml (Ukrainian) 2023-01-25 23:45:08 +01:00
Eugen Rochko
c6c985c1db New translations strings.xml (Swedish) 2023-01-25 23:45:07 +01:00
Eugen Rochko
8988b22a52 New translations strings.xml (Slovenian) 2023-01-25 23:45:06 +01:00
Eugen Rochko
692ede503c New translations strings.xml (Russian) 2023-01-25 23:45:05 +01:00
Eugen Rochko
3be04343b8 New translations strings.xml (Portuguese) 2023-01-25 23:45:04 +01:00
Eugen Rochko
521157315b New translations strings.xml (Dutch) 2023-01-25 23:45:03 +01:00
Eugen Rochko
b4d7b34767 New translations strings.xml (Korean) 2023-01-25 23:45:02 +01:00
Eugen Rochko
f912e90691 New translations strings.xml (Japanese) 2023-01-25 23:45:01 +01:00
Eugen Rochko
61ff2ce7e4 New translations strings.xml (Italian) 2023-01-25 23:45:00 +01:00
Eugen Rochko
0316ec340a New translations strings.xml (Armenian) 2023-01-25 23:44:59 +01:00
Eugen Rochko
3975e8c280 New translations strings.xml (Hebrew) 2023-01-25 23:44:58 +01:00
Eugen Rochko
37c40e4a8d New translations strings.xml (Irish) 2023-01-25 23:44:57 +01:00
Eugen Rochko
7dc691deae New translations strings.xml (Finnish) 2023-01-25 23:44:56 +01:00
Eugen Rochko
ab5dfe6f62 New translations strings.xml (Basque) 2023-01-25 23:44:55 +01:00
Eugen Rochko
b445e6f79f New translations strings.xml (Greek) 2023-01-25 23:44:54 +01:00
Eugen Rochko
5f0cd72303 New translations strings.xml (German) 2023-01-25 23:44:53 +01:00
Eugen Rochko
53dfa08300 New translations strings.xml (Danish) 2023-01-25 23:44:53 +01:00
Eugen Rochko
321c23c52e New translations strings.xml (Catalan) 2023-01-25 23:44:51 +01:00
Eugen Rochko
dd6cb4af74 New translations strings.xml (Arabic) 2023-01-25 23:44:50 +01:00
Eugen Rochko
54b6aaec09 New translations strings.xml (French) 2023-01-25 23:44:50 +01:00
Eugen Rochko
624d21d18b New translations strings.xml (Romanian) 2023-01-25 23:44:49 +01:00
Eugen Rochko
5c27155507 New translations strings.xml (Galician) 2023-01-25 23:44:48 +01:00
Eugen Rochko
35552cfbef New translations strings.xml (Turkish) 2023-01-25 23:44:46 +01:00
Eugen Rochko
31bbeef24e New translations strings.xml (Spanish) 2023-01-25 23:44:46 +01:00
Eugen Rochko
5ee42c0294 New translations strings.xml (Igbo) 2023-01-25 23:44:45 +01:00
Eugen Rochko
3d08f768f8 New translations strings.xml (Polish) 2023-01-25 23:44:44 +01:00
Eugen Rochko
603e3d7d65 New translations strings.xml (Belarusian) 2023-01-25 23:44:43 +01:00
Eugen Rochko
eb8f71aa31 New translations strings.xml (Portuguese, Brazilian) 2023-01-25 23:44:42 +01:00
Eugen Rochko
c7b5b41128 New translations strings.xml (Hungarian) 2023-01-25 23:44:41 +01:00
Eugen Rochko
98dbff38ff New translations strings.xml (Czech) 2023-01-25 23:44:40 +01:00
Eugen Rochko
d9317f6eb1 New translations strings.xml (Norwegian) 2023-01-25 23:44:39 +01:00
Grishka
bcb3e217cd More onboarding updates 2023-01-26 01:38:29 +03:00
Eugen Rochko
4b5dff8742 New translations short_description.txt (Danish) 2023-01-25 22:14:11 +01:00
Eugen Rochko
2256ef6232 New translations full_description.txt (Danish) 2023-01-25 22:14:10 +01:00
Eugen Rochko
182bc09023 New translations strings.xml (Danish) 2023-01-25 22:14:09 +01:00
Eugen Rochko
a60e5040ea New translations strings.xml (Portuguese, Brazilian) 2023-01-25 22:14:08 +01:00
Eugen Rochko
c2a6e17fa5 New translations strings.xml (Thai) 2023-01-25 21:08:37 +01:00
Eugen Rochko
85931e2a65 New translations strings.xml (Portuguese, Brazilian) 2023-01-25 21:08:36 +01:00
Eugen Rochko
da94cd801b New translations strings.xml (Thai) 2023-01-25 18:24:53 +01:00
Eugen Rochko
594570f9a1 New translations strings.xml (Italian) 2023-01-25 10:10:05 +01:00
Eugen Rochko
548a14ab60 New translations strings.xml (Chinese Traditional) 2023-01-25 05:20:29 +01:00
Eugen Rochko
40016332ff New translations strings.xml (Chinese Traditional) 2023-01-25 04:16:16 +01:00
Eugen Rochko
2b9746232b New translations strings.xml (Kabyle) 2023-01-24 21:53:35 +01:00
Eugen Rochko
1fe31e9262 New translations strings.xml (Occitan) 2023-01-24 21:53:34 +01:00
Eugen Rochko
b2a152a728 New translations strings.xml (Scottish Gaelic) 2023-01-24 21:53:33 +01:00
Eugen Rochko
f93d9a0c35 New translations strings.xml (Sinhala) 2023-01-24 21:53:31 +01:00
Eugen Rochko
af9d9c3f48 New translations strings.xml (Bosnian) 2023-01-24 21:53:30 +01:00
Eugen Rochko
5cae41a500 New translations strings.xml (Filipino) 2023-01-24 21:53:29 +01:00
Eugen Rochko
d6c560e015 New translations strings.xml (Burmese) 2023-01-24 21:53:28 +01:00
Eugen Rochko
a2679a3841 New translations strings.xml (Hindi) 2023-01-24 21:53:27 +01:00
Eugen Rochko
d826e0172b New translations strings.xml (Croatian) 2023-01-24 21:53:26 +01:00
Eugen Rochko
f593f5eb58 New translations strings.xml (Thai) 2023-01-24 21:53:25 +01:00
Eugen Rochko
d29565af9c New translations strings.xml (Bengali) 2023-01-24 21:53:24 +01:00
Eugen Rochko
7c3cef32ed New translations strings.xml (Persian) 2023-01-24 21:53:23 +01:00
Eugen Rochko
2c15796108 New translations strings.xml (Indonesian) 2023-01-24 21:53:22 +01:00
Eugen Rochko
553a3ef7e1 New translations strings.xml (Icelandic) 2023-01-24 21:53:21 +01:00
Eugen Rochko
a7dfb671ce New translations strings.xml (Vietnamese) 2023-01-24 21:53:20 +01:00
Eugen Rochko
929218d74c New translations strings.xml (Chinese Traditional) 2023-01-24 21:53:19 +01:00
Eugen Rochko
a5ec9695df New translations strings.xml (Chinese Simplified) 2023-01-24 21:53:18 +01:00
Eugen Rochko
2784828a93 New translations strings.xml (Ukrainian) 2023-01-24 21:53:16 +01:00
Eugen Rochko
84657e9529 New translations strings.xml (Swedish) 2023-01-24 21:53:15 +01:00
Eugen Rochko
110375462e New translations strings.xml (Slovenian) 2023-01-24 21:53:14 +01:00
Eugen Rochko
09e385633e New translations strings.xml (Russian) 2023-01-24 21:53:14 +01:00
Eugen Rochko
f7410a510f New translations strings.xml (Portuguese) 2023-01-24 21:53:13 +01:00
Eugen Rochko
20511fd39d New translations strings.xml (Dutch) 2023-01-24 21:53:12 +01:00
Eugen Rochko
dbacbe0341 New translations strings.xml (Korean) 2023-01-24 21:53:11 +01:00
Eugen Rochko
bd8da39a19 New translations strings.xml (Japanese) 2023-01-24 21:53:09 +01:00
Eugen Rochko
675a353494 New translations strings.xml (Italian) 2023-01-24 21:53:08 +01:00
Eugen Rochko
7b23ca1c96 New translations strings.xml (Armenian) 2023-01-24 21:53:08 +01:00
Eugen Rochko
61e8c6f435 New translations strings.xml (Hebrew) 2023-01-24 21:53:07 +01:00
Eugen Rochko
a41b8dbb01 New translations strings.xml (Irish) 2023-01-24 21:53:06 +01:00
Eugen Rochko
fe525f9242 New translations strings.xml (Finnish) 2023-01-24 21:53:05 +01:00
Eugen Rochko
7cbae9c0a9 New translations strings.xml (Basque) 2023-01-24 21:53:04 +01:00
Eugen Rochko
93ac0a103f New translations strings.xml (Greek) 2023-01-24 21:53:03 +01:00
Eugen Rochko
3b11787984 New translations strings.xml (German) 2023-01-24 21:53:02 +01:00
Eugen Rochko
7b6fcaf3db New translations strings.xml (Danish) 2023-01-24 21:53:00 +01:00
Eugen Rochko
11b838f394 New translations strings.xml (Catalan) 2023-01-24 21:52:59 +01:00
Eugen Rochko
38bd5eb68e New translations strings.xml (Arabic) 2023-01-24 21:52:58 +01:00
Eugen Rochko
1dc8d66b3f New translations strings.xml (French) 2023-01-24 21:52:57 +01:00
Eugen Rochko
9f64e56923 New translations strings.xml (Romanian) 2023-01-24 21:52:56 +01:00
Eugen Rochko
a9e84678b3 New translations strings.xml (Galician) 2023-01-24 21:52:55 +01:00
Eugen Rochko
d7c5c0074d New translations strings.xml (Turkish) 2023-01-24 21:52:54 +01:00
Eugen Rochko
97e148f4c8 New translations strings.xml (Spanish) 2023-01-24 21:52:53 +01:00
Eugen Rochko
e83bd039b3 New translations strings.xml (Igbo) 2023-01-24 21:52:52 +01:00
Eugen Rochko
a30d288b13 New translations strings.xml (Polish) 2023-01-24 21:52:51 +01:00
Eugen Rochko
ded14711ac New translations strings.xml (Belarusian) 2023-01-24 21:52:50 +01:00
Eugen Rochko
cece9d4aa1 New translations strings.xml (Portuguese, Brazilian) 2023-01-24 21:52:49 +01:00
Eugen Rochko
f7f56c7a9b New translations strings.xml (Hungarian) 2023-01-24 21:52:48 +01:00
Eugen Rochko
613a9de40e New translations strings.xml (Czech) 2023-01-24 21:52:47 +01:00
Eugen Rochko
9ed8ad1382 New translations strings.xml (Norwegian) 2023-01-24 21:52:46 +01:00
Grishka
a1798b6666 Update onboarding 2023-01-24 23:43:56 +03:00
Gregory K
58ab0c0fc1 Merge pull request #516 from sk22/improve-compose-toolbar-hitbox
Bigger hitbox for items in compose toolbar
2023-01-23 17:17:20 +03:00
sk
32a8d38edf bigger hitbox for items in compose toolbar 2023-01-23 14:54:39 +01:00
Gregory K
a5c753a9f8 Merge pull request #515 from sk22/allow-notifications-toolbar-tab
Enable scrolling to top by tapping Notifications toolbar
2023-01-23 15:38:07 +03:00
Eugen Rochko
7498118800 New translations strings.xml (Belarusian) 2023-01-23 13:24:17 +01:00
sk
66cede567e enable scrolling to top via toolbar 2023-01-23 12:49:55 +01:00
Eugen Rochko
b894827607 New translations strings.xml (Belarusian) 2023-01-23 12:18:10 +01:00
Grishka
c67b2b35f3 Fix #509 2023-01-22 02:08:55 +03:00
Grishka
8588ca8ae3 Fix #510 2023-01-22 02:05:36 +03:00
Grishka
7bb280e8b8 Fix #69 (nice) 2023-01-22 02:04:12 +03:00
Grishka
ddfeaabd44 Fix #512 2023-01-22 01:12:39 +03:00
Gregory K
51219bf98a Merge pull request #513 from sk22/fix-has-spoiler-restore
Fix wrong "hasSpoiler" value on restore
2023-01-22 01:11:42 +03:00
sk
512cb70347 fix wrong "hasSpoiler" value on restore
closes sk22#324
2023-01-21 23:06:31 +01:00
Eugen Rochko
8788fb0b27 New translations full_description.txt (Galician) 2023-01-19 06:28:17 +01:00
Eugen Rochko
62d4c62888 New translations strings.xml (Galician) 2023-01-19 06:28:15 +01:00
Eugen Rochko
572d092f88 New translations strings.xml (Galician) 2023-01-19 05:18:11 +01:00
Eugen Rochko
2ff771391c New translations strings.xml (Turkish) 2023-01-17 21:00:59 +01:00
Eugen Rochko
087e55277c New translations strings.xml (Spanish) 2023-01-17 14:46:10 +01:00
Eugen Rochko
a2d45fbbc5 New translations full_description.txt (Spanish) 2023-01-17 13:50:33 +01:00
Eugen Rochko
59262fe345 New translations full_description.txt (Belarusian) 2023-01-17 08:34:46 +01:00
Eugen Rochko
ffc36f7346 New translations short_description.txt (Belarusian) 2023-01-16 16:05:34 +01:00
Eugen Rochko
549ace65f5 New translations full_description.txt (Belarusian) 2023-01-16 16:05:33 +01:00
Eugen Rochko
c76bec2298 New translations strings.xml (Belarusian) 2023-01-16 16:05:32 +01:00
Eugen Rochko
290e47386e New translations strings.xml (Belarusian) 2023-01-16 14:43:34 +01:00
Eugen Rochko
3d96475c21 New translations strings.xml (Belarusian) 2023-01-16 12:54:15 +01:00
Eugen Rochko
b62fe06187 New translations strings.xml (Belarusian) 2023-01-16 11:49:53 +01:00
Eugen Rochko
c0dc2b8392 New translations strings.xml (Belarusian) 2023-01-16 09:21:59 +01:00
Eugen Rochko
e777bbb215 New translations strings.xml (Belarusian) 2023-01-16 08:16:21 +01:00
Eugen Rochko
014f9f4d99 New translations strings.xml (Belarusian) 2023-01-15 22:22:23 +01:00
Eugen Rochko
86bfd3d09f New translations strings.xml (Igbo) 2023-01-15 14:40:38 +01:00
Eugen Rochko
21d6f6da4c New translations title.txt (Igbo) 2023-01-15 13:36:28 +01:00
Eugen Rochko
f826e0ceef New translations short_description.txt (Igbo) 2023-01-15 13:36:28 +01:00
Eugen Rochko
458ad0f51a New translations full_description.txt (Igbo) 2023-01-15 13:36:27 +01:00
Eugen Rochko
9a0ff42ec2 New translations strings.xml (Igbo) 2023-01-15 13:36:26 +01:00
Eugen Rochko
18dae448ec New translations full_description.txt (Portuguese) 2023-01-14 14:57:31 +01:00
Eugen Rochko
fc36a8cc8f New translations full_description.txt (Portuguese) 2023-01-14 13:59:38 +01:00
Eugen Rochko
a390df2b9e New translations full_description.txt (Polish) 2023-01-14 07:31:44 +01:00
Eugen Rochko
6f61d3f0e3 New translations strings.xml (Polish) 2023-01-14 07:31:43 +01:00
Eugen Rochko
3a4e8ebdf4 New translations strings.xml (Polish) 2023-01-14 06:36:08 +01:00
Eugen Rochko
537242b277 New translations strings.xml (Czech) 2023-01-13 17:24:51 +01:00
Eugen Rochko
97eece59ea New translations strings.xml (Belarusian) 2023-01-13 15:29:36 +01:00
Eugen Rochko
fc88d42e50 New translations strings.xml (Belarusian) 2023-01-13 14:21:42 +01:00
Eugen Rochko
ec74712e55 New translations strings.xml (Belarusian) 2023-01-13 11:50:08 +01:00
Eugen Rochko
12e1ccf439 New translations strings.xml (Belarusian) 2023-01-13 10:53:08 +01:00
Eugen Rochko
24b8d5ce7c New translations strings.xml (Belarusian) 2023-01-13 07:50:35 +01:00
Eugen Rochko
46c9c83b63 New translations strings.xml (Belarusian) 2023-01-13 06:47:00 +01:00
Eugen Rochko
526a9fec03 New translations strings.xml (Belarusian) 2023-01-13 05:47:47 +01:00
Eugen Rochko
ca20f3b906 New translations strings.xml (Portuguese, Brazilian) 2023-01-13 01:19:33 +01:00
Eugen Rochko
af8c8a6248 New translations strings.xml (Portuguese, Brazilian) 2023-01-12 22:31:03 +01:00
Eugen Rochko
2940e5d3d8 New translations strings.xml (Portuguese, Brazilian) 2023-01-12 03:45:12 +01:00
Eugen Rochko
c98b001c9f New translations strings.xml (Portuguese, Brazilian) 2023-01-12 02:45:05 +01:00
Eugen Rochko
1fc1c95d6e New translations full_description.txt (Czech) 2023-01-11 12:16:25 +01:00
Eugen Rochko
e4d0c4eda5 New translations strings.xml (Czech) 2023-01-11 12:16:23 +01:00
Eugen Rochko
801d11c8e6 New translations short_description.txt (Norwegian) 2023-01-11 11:15:30 +01:00
Eugen Rochko
8143374929 New translations full_description.txt (Norwegian) 2023-01-11 11:15:29 +01:00
Eugen Rochko
df2ff9f874 New translations strings.xml (Norwegian) 2023-01-11 11:15:28 +01:00
Eugen Rochko
4bac852d37 New translations strings.xml (Norwegian) 2023-01-11 08:30:29 +01:00
Eugen Rochko
862a173392 New translations title.txt (Norwegian) 2023-01-07 17:43:49 +01:00
Eugen Rochko
bd47b31c65 New translations short_description.txt (Norwegian) 2023-01-07 17:43:48 +01:00
Eugen Rochko
aefb7f2e23 New translations full_description.txt (Norwegian) 2023-01-07 17:43:48 +01:00
Eugen Rochko
e509b8afa4 New translations strings.xml (Norwegian) 2023-01-07 17:43:47 +01:00
Eugen Rochko
7b94f7258f New translations title.txt (Danish) 2023-01-07 17:43:46 +01:00
Eugen Rochko
8d81efae4e New translations short_description.txt (Danish) 2023-01-07 17:43:45 +01:00
Eugen Rochko
5b0b80277c New translations full_description.txt (Danish) 2023-01-07 17:43:44 +01:00
Eugen Rochko
60293d5a65 New translations strings.xml (Danish) 2023-01-07 17:43:43 +01:00
Eugen Rochko
09b4aff9f5 New translations strings.xml (Filipino) 2023-01-06 11:31:21 +01:00
Eugen Rochko
7326cbeb14 New translations strings.xml (Burmese) 2023-01-06 10:13:45 +01:00
Eugen Rochko
91bd3fa4ea New translations full_description.txt (Burmese) 2023-01-06 09:04:21 +01:00
Eugen Rochko
3cc6a9905e New translations strings.xml (Burmese) 2023-01-06 09:04:20 +01:00
Eugen Rochko
f01bfcd372 New translations full_description.txt (Burmese) 2023-01-06 06:45:57 +01:00
Eugen Rochko
81b4365a14 New translations full_description.txt (Swedish) 2023-01-03 12:40:32 +01:00
Eugen Rochko
7ab28a6db6 New translations strings.xml (Swedish) 2023-01-03 12:40:31 +01:00
Eugen Rochko
3bb548cf22 New translations full_description.txt (Burmese) 2023-01-03 08:43:34 +01:00
Eugen Rochko
ba788d1b34 New translations full_description.txt (Burmese) 2023-01-03 07:13:43 +01:00
Eugen Rochko
f51b01bcd9 New translations short_description.txt (Burmese) 2023-01-03 06:17:54 +01:00
Eugen Rochko
361c97a9df New translations full_description.txt (Burmese) 2023-01-03 06:17:53 +01:00
Eugen Rochko
f34153e601 New translations title.txt (Burmese) 2023-01-02 22:49:11 +01:00
Eugen Rochko
67240acb48 New translations short_description.txt (Burmese) 2023-01-02 22:49:11 +01:00
Eugen Rochko
4395dbfa7c New translations full_description.txt (Burmese) 2023-01-02 22:49:10 +01:00
Eugen Rochko
48b0207636 New translations strings.xml (Burmese) 2023-01-02 22:49:09 +01:00
Eugen Rochko
f7b8ed519c New translations strings.xml (Filipino) 2023-01-02 20:56:03 +01:00
Eugen Rochko
eba88f2c0a New translations strings.xml (Filipino) 2023-01-02 20:00:36 +01:00
Eugen Rochko
8d95355727 New translations short_description.txt (Filipino) 2023-01-01 17:18:41 +01:00
Eugen Rochko
e05a67c4ab New translations full_description.txt (Filipino) 2023-01-01 17:18:40 +01:00
Eugen Rochko
5db91627a1 New translations strings.xml (Filipino) 2023-01-01 17:18:39 +01:00
Eugen Rochko
7e473aa8a8 New translations strings.xml (Filipino) 2023-01-01 16:17:30 +01:00
Eugen Rochko
1e1edd698d New translations strings.xml (Vietnamese) 2023-01-01 09:16:11 +01:00
Eugen Rochko
aa42a0a4c4 New translations strings.xml (Filipino) 2022-12-29 06:02:04 +01:00
Eugen Rochko
ad61596f66 New translations strings.xml (Filipino) 2022-12-29 05:04:36 +01:00
Eugen Rochko
bd518b3038 New translations strings.xml (Filipino) 2022-12-28 14:31:07 +01:00
Eugen Rochko
db3129ab11 New translations strings.xml (Arabic) 2022-12-27 21:32:08 +01:00
Eugen Rochko
57a38a83e4 New translations strings.xml (Russian) 2022-12-24 14:52:14 +01:00
Eugen Rochko
c0de43e2f3 New translations strings.xml (Vietnamese) 2022-12-24 06:25:12 +01:00
Eugen Rochko
c6e29c9ce4 New translations strings.xml (Filipino) 2022-12-23 14:24:05 +01:00
Eugen Rochko
35e8f5eddf New translations strings.xml (Filipino) 2022-12-23 11:33:45 +01:00
Eugen Rochko
40ed72aeff New translations full_description.txt (Dutch) 2022-12-22 02:02:15 +01:00
Eugen Rochko
75033cf42e New translations strings.xml (Dutch) 2022-12-22 02:02:14 +01:00
Eugen Rochko
4a29a63d50 New translations short_description.txt (Dutch) 2022-12-21 23:28:34 +01:00
Eugen Rochko
595a6847dc New translations strings.xml (Dutch) 2022-12-21 23:28:33 +01:00
Eugen Rochko
64f403b644 New translations full_description.txt (Thai) 2022-12-19 21:15:22 +01:00
Eugen Rochko
314517c378 New translations full_description.txt (Hungarian) 2022-12-19 11:42:43 +01:00
Eugen Rochko
b90fc55b3f New translations strings.xml (Hungarian) 2022-12-19 11:42:42 +01:00
Eugen Rochko
cd57966810 New translations full_description.txt (Indonesian) 2022-12-18 00:52:58 +01:00
Eugen Rochko
8c0851e2b5 New translations strings.xml (Indonesian) 2022-12-18 00:52:57 +01:00
Eugen Rochko
b9efa434d2 New translations strings.xml (Thai) 2022-12-16 22:37:47 +01:00
Eugen Rochko
adc085a313 New translations strings.xml (Thai) 2022-12-16 21:27:39 +01:00
Eugen Rochko
a2a2f67239 New translations strings.xml (Catalan) 2022-12-16 17:40:43 +01:00
Eugen Rochko
c30fba61ca New translations strings.xml (Swedish) 2022-12-16 13:09:15 +01:00
Eugen Rochko
f09b37d28f New translations strings.xml (Persian) 2022-12-16 09:28:27 +01:00
Eugen Rochko
6cbc89b01d New translations strings.xml (Persian) 2022-12-16 08:22:43 +01:00
Eugen Rochko
ffd538fbd0 New translations strings.xml (Dutch) 2022-12-15 17:36:44 +01:00
Eugen Rochko
1f27f66432 New translations full_description.txt (Dutch) 2022-12-15 16:30:46 +01:00
Eugen Rochko
25f302f62f New translations strings.xml (Basque) 2022-12-14 13:39:14 +01:00
Eugen Rochko
d54eb6ed73 New translations strings.xml (Basque) 2022-12-14 12:41:52 +01:00
Eugen Rochko
24a6d77777 New translations strings.xml (Spanish) 2022-12-13 16:47:57 +01:00
Eugen Rochko
5cbebe7ec6 New translations strings.xml (Portuguese) 2022-12-13 13:29:44 +01:00
Eugen Rochko
a31c310ffa New translations full_description.txt (German) 2022-12-13 12:26:47 +01:00
Eugen Rochko
752d0b5ca9 New translations strings.xml (Korean) 2022-12-13 02:15:40 +01:00
Eugen Rochko
170131188a New translations title.txt (Persian) 2022-12-12 14:17:48 +01:00
Eugen Rochko
3269613139 New translations short_description.txt (Persian) 2022-12-12 14:17:47 +01:00
Eugen Rochko
52cc74fb85 New translations full_description.txt (Persian) 2022-12-12 14:17:46 +01:00
Eugen Rochko
d7d09b1d56 New translations strings.xml (Persian) 2022-12-12 14:17:45 +01:00
Eugen Rochko
797f2b5929 New translations strings.xml (Spanish) 2022-12-12 13:22:18 +01:00
Eugen Rochko
fa5053fe38 New translations full_description.txt (Spanish) 2022-12-12 11:19:07 +01:00
Eugen Rochko
c682c249bd New translations strings.xml (Spanish) 2022-12-12 11:19:06 +01:00
Eugen Rochko
01c229c7c1 New translations strings.xml (Spanish) 2022-12-12 10:19:26 +01:00
Eugen Rochko
83f39d6b22 New translations strings.xml (Thai) 2022-12-11 21:27:37 +01:00
Eugen Rochko
715ec6e7c6 New translations strings.xml (Thai) 2022-12-11 20:11:30 +01:00
Eugen Rochko
b6fa34e87f New translations strings.xml (Italian) 2022-12-11 17:31:10 +01:00
Eugen Rochko
6ff14cc7a1 New translations full_description.txt (Slovenian) 2022-12-11 15:55:38 +01:00
Eugen Rochko
d606ce89e0 New translations strings.xml (Slovenian) 2022-12-11 15:55:37 +01:00
Eugen Rochko
41e80f1d24 New translations full_description.txt (Hungarian) 2022-12-11 14:42:32 +01:00
Eugen Rochko
8decd66e26 New translations strings.xml (Hungarian) 2022-12-11 14:42:31 +01:00
Eugen Rochko
c033849fb4 New translations strings.xml (Thai) 2022-12-11 14:42:30 +01:00
Eugen Rochko
14054b2198 New translations strings.xml (Hungarian) 2022-12-11 13:46:42 +01:00
Eugen Rochko
3c3a6712bd New translations strings.xml (Icelandic) 2022-12-11 10:41:24 +01:00
Eugen Rochko
6a97ed41e0 New translations strings.xml (Icelandic) 2022-12-11 09:42:40 +01:00
Eugen Rochko
bfedd6c953 New translations full_description.txt (Vietnamese) 2022-12-11 06:15:06 +01:00
Eugen Rochko
23d72346b3 New translations strings.xml (Vietnamese) 2022-12-11 06:15:05 +01:00
Eugen Rochko
e9510875ea New translations strings.xml (Vietnamese) 2022-12-11 05:13:59 +01:00
Eugen Rochko
84d7b6c48f New translations strings.xml (Italian) 2022-12-11 01:14:30 +01:00
Eugen Rochko
5f4af7024d New translations full_description.txt (Portuguese, Brazilian) 2022-12-10 20:48:20 +01:00
Eugen Rochko
3b16eb807e New translations strings.xml (Portuguese, Brazilian) 2022-12-10 20:48:19 +01:00
Eugen Rochko
ef6b52049f New translations strings.xml (German) 2022-12-10 17:34:19 +01:00
Eugen Rochko
a7b035bb8e New translations strings.xml (Chinese Simplified) 2022-12-10 16:11:51 +01:00
Eugen Rochko
645216b8eb New translations strings.xml (Chinese Simplified) 2022-12-10 15:10:07 +01:00
Eugen Rochko
2b1c18635e New translations strings.xml (Italian) 2022-12-10 11:42:34 +01:00
Eugen Rochko
bb7a76617e New translations full_description.txt (Korean) 2022-12-10 06:43:06 +01:00
Eugen Rochko
ab50e7861a New translations strings.xml (Korean) 2022-12-10 05:29:13 +01:00
Eugen Rochko
d52b88c816 New translations strings.xml (Korean) 2022-12-10 03:51:49 +01:00
Eugen Rochko
e5d0a2a14c New translations full_description.txt (Korean) 2022-12-10 02:44:45 +01:00
Eugen Rochko
11e9db7ded New translations strings.xml (Korean) 2022-12-10 02:44:44 +01:00
Eugen Rochko
23c1a78d01 New translations strings.xml (German) 2022-12-09 21:35:30 +01:00
Eugen Rochko
e524423191 New translations full_description.txt (Ukrainian) 2022-12-09 20:36:43 +01:00
Eugen Rochko
7286e71442 New translations strings.xml (Ukrainian) 2022-12-09 20:36:42 +01:00
Eugen Rochko
71681458a1 New translations strings.xml (French) 2022-12-09 19:20:25 +01:00
Eugen Rochko
4d4b3c8867 New translations strings.xml (French) 2022-12-09 17:51:26 +01:00
Eugen Rochko
681d808a74 New translations strings.xml (Kabyle) 2022-12-09 16:35:54 +01:00
Eugen Rochko
876a0b27a6 New translations strings.xml (French) 2022-12-09 16:35:53 +01:00
Eugen Rochko
9dce3b9a17 New translations full_description.txt (Arabic) 2022-12-09 14:48:38 +01:00
Eugen Rochko
f77b487520 New translations strings.xml (Arabic) 2022-12-09 14:48:37 +01:00
Eugen Rochko
f3c73a5c8a New translations strings.xml (Chinese Traditional) 2022-12-09 03:47:27 +01:00
Eugen Rochko
37502b3747 New translations strings.xml (Chinese Traditional) 2022-12-09 02:46:30 +01:00
Eugen Rochko
309e84d14c New translations strings.xml (Filipino) 2022-12-08 21:26:30 +01:00
Eugen Rochko
ff464bef9f New translations strings.xml (Hungarian) 2022-12-08 21:26:29 +01:00
Eugen Rochko
dfa5cd65f3 New translations strings.xml (Icelandic) 2022-12-08 21:26:28 +01:00
Eugen Rochko
ccba5969a5 New translations strings.xml (Belarusian) 2022-12-08 21:26:27 +01:00
Eugen Rochko
03baef713d New translations strings.xml (Slovenian) 2022-12-08 21:26:27 +01:00
Eugen Rochko
a3617349bb New translations strings.xml (Irish) 2022-12-08 21:26:26 +01:00
Eugen Rochko
e57b22d2fc New translations strings.xml (Romanian) 2022-12-08 21:26:25 +01:00
Eugen Rochko
6aabaa497d New translations strings.xml (Bengali) 2022-12-08 21:26:24 +01:00
Eugen Rochko
6caa142ead New translations strings.xml (Hindi) 2022-12-08 21:26:23 +01:00
Eugen Rochko
b01e6e30a4 New translations strings.xml (Scottish Gaelic) 2022-12-08 21:26:21 +01:00
Eugen Rochko
5e3a612828 New translations strings.xml (Sinhala) 2022-12-08 21:26:19 +01:00
Eugen Rochko
b498e7e83e New translations strings.xml (Indonesian) 2022-12-08 21:26:18 +01:00
Eugen Rochko
7508643c89 New translations strings.xml (Dutch) 2022-12-08 21:26:17 +01:00
Eugen Rochko
24d2189399 New translations strings.xml (Kabyle) 2022-12-08 21:26:17 +01:00
Eugen Rochko
4e470f34fd New translations strings.xml (Occitan) 2022-12-08 21:26:16 +01:00
Eugen Rochko
e3ca6448f2 New translations strings.xml (Bosnian) 2022-12-08 21:26:15 +01:00
Eugen Rochko
9dadac7d93 New translations strings.xml (Croatian) 2022-12-08 21:26:14 +01:00
Eugen Rochko
0715bd0aba New translations strings.xml (Thai) 2022-12-08 21:26:13 +01:00
Eugen Rochko
92772e7ee0 New translations strings.xml (Galician) 2022-12-08 21:26:12 +01:00
Eugen Rochko
f9f6c879e0 New translations strings.xml (Vietnamese) 2022-12-08 21:26:11 +01:00
Eugen Rochko
ec7623f5c5 New translations strings.xml (Chinese Simplified) 2022-12-08 21:26:10 +01:00
Eugen Rochko
0163242258 New translations strings.xml (Ukrainian) 2022-12-08 21:26:09 +01:00
Eugen Rochko
3f9c8247c6 New translations strings.xml (Turkish) 2022-12-08 21:26:08 +01:00
Eugen Rochko
20865ad202 New translations strings.xml (Swedish) 2022-12-08 21:26:06 +01:00
Eugen Rochko
b5ac895b15 New translations strings.xml (Russian) 2022-12-08 21:26:05 +01:00
Eugen Rochko
fbd550228b New translations strings.xml (Portuguese) 2022-12-08 21:26:04 +01:00
Eugen Rochko
238758fc0b New translations strings.xml (Korean) 2022-12-08 21:26:03 +01:00
Eugen Rochko
328a4339a4 New translations strings.xml (Japanese) 2022-12-08 21:26:02 +01:00
Eugen Rochko
747d958507 New translations strings.xml (Italian) 2022-12-08 21:26:01 +01:00
Eugen Rochko
8622160e62 New translations strings.xml (Armenian) 2022-12-08 21:26:00 +01:00
Eugen Rochko
df1042e87d New translations strings.xml (Hebrew) 2022-12-08 21:25:59 +01:00
Eugen Rochko
a5c6c11f09 New translations strings.xml (Finnish) 2022-12-08 21:25:58 +01:00
Eugen Rochko
7bd602cd45 New translations strings.xml (Basque) 2022-12-08 21:25:57 +01:00
Eugen Rochko
2065468f1f New translations strings.xml (Greek) 2022-12-08 21:25:56 +01:00
Eugen Rochko
7f9061d0c8 New translations strings.xml (Czech) 2022-12-08 21:25:55 +01:00
Eugen Rochko
00a638393e New translations strings.xml (Catalan) 2022-12-08 21:25:54 +01:00
Eugen Rochko
f21194f877 New translations strings.xml (Spanish) 2022-12-08 21:25:53 +01:00
Eugen Rochko
1772351fc5 New translations strings.xml (French) 2022-12-08 21:25:52 +01:00
Eugen Rochko
1030fc5e16 New translations strings.xml (Arabic) 2022-12-08 21:25:51 +01:00
Eugen Rochko
bef3ae96f6 New translations strings.xml (German) 2022-12-08 21:25:51 +01:00
Eugen Rochko
c9fa5b2104 New translations strings.xml (Chinese Traditional) 2022-12-08 21:25:50 +01:00
Eugen Rochko
79cd8c0805 New translations strings.xml (Polish) 2022-12-08 21:25:48 +01:00
Eugen Rochko
2b80420794 New translations strings.xml (Portuguese, Brazilian) 2022-12-08 21:25:47 +01:00
Eugen Rochko
b8e18613b1 New translations full_description.txt (French) 2022-12-08 18:43:26 +01:00
Eugen Rochko
87289e4804 New translations strings.xml (Ukrainian) 2022-12-08 18:43:25 +01:00
Eugen Rochko
ba3a06a782 New translations full_description.txt (Ukrainian) 2022-12-08 15:57:19 +01:00
Eugen Rochko
2764ef0417 New translations strings.xml (Ukrainian) 2022-12-08 15:57:18 +01:00
Eugen Rochko
ae0e89aa31 New translations full_description.txt (Catalan) 2022-12-08 13:36:42 +01:00
Eugen Rochko
d0e99cc517 New translations strings.xml (Catalan) 2022-12-08 13:36:41 +01:00
Eugen Rochko
604fb01d6c New translations strings.xml (Catalan) 2022-12-08 12:29:42 +01:00
Eugen Rochko
256a1687d1 New translations full_description.txt (Chinese Traditional) 2022-12-07 12:56:51 +01:00
Eugen Rochko
ea1ae58e54 New translations strings.xml (Chinese Traditional) 2022-12-07 12:56:50 +01:00
Eugen Rochko
fe9d119fe2 New translations strings.xml (Chinese Traditional) 2022-12-07 11:55:33 +01:00
Eugen Rochko
4a199533c1 New translations short_description.txt (Vietnamese) 2022-12-07 02:58:56 +01:00
Eugen Rochko
7e785f1b6c New translations strings.xml (Ukrainian) 2022-12-07 02:58:55 +01:00
Eugen Rochko
85b4824ea2 New translations strings.xml (Russian) 2022-12-07 02:58:54 +01:00
Eugen Rochko
d39af74bcc New translations strings.xml (Italian) 2022-12-07 00:52:19 +01:00
Eugen Rochko
bfb52af454 New translations full_description.txt (Italian) 2022-12-06 23:44:22 +01:00
Eugen Rochko
5630e5d488 New translations strings.xml (Italian) 2022-12-06 23:44:21 +01:00
Eugen Rochko
29780ecf22 New translations full_description.txt (Icelandic) 2022-12-06 19:46:01 +01:00
Eugen Rochko
a8b542feaa New translations full_description.txt (Kabyle) 2022-12-06 17:09:14 +01:00
Eugen Rochko
e85b182da7 New translations full_description.txt (Occitan) 2022-12-06 17:09:13 +01:00
Eugen Rochko
84e9195869 New translations full_description.txt (Scottish Gaelic) 2022-12-06 17:09:12 +01:00
Eugen Rochko
7a739457c9 New translations full_description.txt (Sinhala) 2022-12-06 17:09:11 +01:00
Eugen Rochko
30905a7c36 New translations full_description.txt (Bosnian) 2022-12-06 17:09:10 +01:00
Eugen Rochko
0326a6834a New translations full_description.txt (Hindi) 2022-12-06 17:09:09 +01:00
Eugen Rochko
7c75a67f9f New translations full_description.txt (Croatian) 2022-12-06 17:09:06 +01:00
Eugen Rochko
1aa0fbf7d5 New translations full_description.txt (Thai) 2022-12-06 17:09:04 +01:00
Eugen Rochko
9adce93645 New translations full_description.txt (Bengali) 2022-12-06 17:09:03 +01:00
Eugen Rochko
b7392ef62d New translations full_description.txt (Indonesian) 2022-12-06 17:09:02 +01:00
Eugen Rochko
6b55c90a93 New translations full_description.txt (Portuguese, Brazilian) 2022-12-06 17:09:00 +01:00
Eugen Rochko
9e9cd9ea4e New translations full_description.txt (Galician) 2022-12-06 17:08:59 +01:00
Eugen Rochko
ef91fb9e06 New translations full_description.txt (Vietnamese) 2022-12-06 17:08:57 +01:00
Eugen Rochko
2f49c525b6 New translations full_description.txt (Chinese Traditional) 2022-12-06 17:08:56 +01:00
Eugen Rochko
f78f179071 New translations full_description.txt (Chinese Simplified) 2022-12-06 17:08:55 +01:00
Eugen Rochko
6ed310f8ce New translations full_description.txt (Ukrainian) 2022-12-06 17:08:54 +01:00
Eugen Rochko
8da5a32b48 New translations full_description.txt (Turkish) 2022-12-06 17:08:53 +01:00
Eugen Rochko
74fcdaa223 New translations full_description.txt (Swedish) 2022-12-06 17:08:52 +01:00
Eugen Rochko
6b77b8fbbb New translations full_description.txt (Slovenian) 2022-12-06 17:08:51 +01:00
Eugen Rochko
9f9fdca53d New translations full_description.txt (Russian) 2022-12-06 17:08:50 +01:00
Eugen Rochko
540317017f New translations full_description.txt (Portuguese) 2022-12-06 17:08:47 +01:00
Eugen Rochko
567174fcde New translations full_description.txt (Polish) 2022-12-06 17:08:44 +01:00
Eugen Rochko
262bc1dcbe New translations full_description.txt (Dutch) 2022-12-06 17:08:43 +01:00
Eugen Rochko
b931928434 New translations full_description.txt (Korean) 2022-12-06 17:08:42 +01:00
Eugen Rochko
7e2057a847 New translations full_description.txt (Japanese) 2022-12-06 17:08:40 +01:00
Eugen Rochko
4a9b98f534 New translations full_description.txt (Italian) 2022-12-06 17:08:39 +01:00
Eugen Rochko
7bf45581e3 New translations full_description.txt (Armenian) 2022-12-06 17:08:38 +01:00
Eugen Rochko
61a7fe6217 New translations full_description.txt (Hebrew) 2022-12-06 17:08:37 +01:00
Eugen Rochko
efa1a3f14f New translations full_description.txt (Irish) 2022-12-06 17:08:36 +01:00
Eugen Rochko
925866c3f0 New translations full_description.txt (Finnish) 2022-12-06 17:08:35 +01:00
Eugen Rochko
7291ec6f88 New translations full_description.txt (Basque) 2022-12-06 17:08:34 +01:00
Eugen Rochko
16c9203956 New translations full_description.txt (Greek) 2022-12-06 17:08:33 +01:00
Eugen Rochko
b08f104663 New translations full_description.txt (Catalan) 2022-12-06 17:08:32 +01:00
Eugen Rochko
82b7c6c290 New translations full_description.txt (Arabic) 2022-12-06 17:08:31 +01:00
Eugen Rochko
63009a332f New translations full_description.txt (Spanish) 2022-12-06 17:08:29 +01:00
Eugen Rochko
95e56db159 New translations full_description.txt (French) 2022-12-06 17:08:28 +01:00
Eugen Rochko
48f981036b New translations full_description.txt (Romanian) 2022-12-06 17:08:27 +01:00
Eugen Rochko
79be77f986 New translations full_description.txt (Filipino) 2022-12-06 17:08:26 +01:00
Eugen Rochko
4fafab19fc New translations full_description.txt (Hungarian) 2022-12-06 17:08:25 +01:00
Eugen Rochko
cd71f6e858 New translations full_description.txt (Icelandic) 2022-12-06 17:08:24 +01:00
Eugen Rochko
63d5068c2c New translations full_description.txt (Belarusian) 2022-12-06 17:08:21 +01:00
Eugen Rochko
a9bc7fdeb7 New translations full_description.txt (Czech) 2022-12-06 17:08:20 +01:00
Eugen Rochko
89dc2608bc New translations full_description.txt (German) 2022-12-06 17:08:19 +01:00
203 changed files with 8063 additions and 2215 deletions

View File

@@ -13,4 +13,4 @@
• المشاركة: انشر مباشرة على ماستودون من أي لوح مُشاركة في أي تطبيق
• الجاذبية: جالب الحظ لدينا هو فيل رائع، سَتراه يظهر فجأة في السطح بين الفينة والأُخرى
مَاستودُون هي مُنَظَّمَةُ غَيرُ رِبحِيَّةٍ مُسَجَّلَة. مُساهَمَاتُكَ هِي الدَّاعِمُ المُباشِرُ لعَمَلِيَّةِ التَّطوير. لا توجد إعلانات، لا تسييل ولا رأس مال استثماري، نحن نخطط للبقاء على هذا النحو.
مَاستودُون هي مُنَظَّمَةُ غَيرُ رِبحِيَّةٍ مُسَجَّلَة. مُساهَمَاتُكَ هِي الدَّاعِمُ المُباشِرُ لعَمَلِيَّةِ التَّطوير. لا توجد إعلانات، لا تسييل ولا رأس مال استثماري، نحن نخطط للبقاء على هذا النحو.

View File

@@ -1,16 +1,16 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Mastodon - гэта найбуйнейшая дэцэнтралізаваная сацыяльная сетка ў Інтэрнэце. Замест аднаго вэб-сайта, гэта сетка з незалежных супольнасцяў з мільёнамі карыстальнікаў, якія могуць бесперашкодна ўзаемадзейнічаць адно з адным. Незалежна ад таго, чым вы захапляецеся, вы знойдзеце людзей, якія пішуць пра гэта ў Mastodon!
Join a community and create your profile. Find and and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Далучайцеся да супольнасці і стварыце свой профіль. Знаходзьце цікавых людзей, сачыце за імі і чытайце іх допісы ў храналагічнай стужцы без рэкламы. Выяўляйце сябе з дапамогай карыстальніцкіх эмодзі, малюнкаў, GIF-файлаў, відэа і аўдыя ў допісах на 500 знакаў. Удзельнічайце ў абмеркаваннях і прасоўвайце выдатныя допісы ад іншых людзей. Знаходзьце новыя ўліковыя запісы, на якія можна падпісацца, і папулярныя хэштэгі, каб пашырыць сваю сетку.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
Mastodon створаны з акцэнтам на прыватнасць і бяспеку. Вырашайце з кім абагульваць вашы допісы: з вашымі падпісчыкамі, толькі з людзьмі, якіх вы згадваеце або з усім светам. Папярэджанні аб змесціве дазваляюць схаваць допісы, якія змяшчаюць канфідэнцыяльны або правакацыйны матэрыял, пакуль вы не будзеце гатовыя да яго. Кожная суполка мае ўласныя правілы і мадэратараў, якія забяспечваюць бяспеку яе ўдзельнікаў, а надзейныя інструменты блакіроўкі і сістэма скарг дапамагаюць прадухіліць злоўжыванні.
More features:
Больш функцый:
Dark Mode: Read posts in light, dark, or true black mode
Polls: Ask followers for their opinion and tally the votes
Explore: Trending hashtags and accounts are a tap away
Notifications: Get notified about new follows, replies, and reblogs
Sharing: Post directly to Mastodon from any share sheet in any app
Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Цёмны рэжым: чытайце допісы ў светлым, цёмным або сапраўдным чорным рэжыме
Апытанні: пытайцеся ў падпісчыкаў іх меркаванне і падлічвайце галасы
Даследуйце: папулярныя хэштэгі і ўліковыя запісы — адным дотыкам
Апавяшчэнні: атрымлівайце апавяшчэнні аб новых падпісчыках, адказах і рэпостах
Абагульванне: публікуйце непасрэдна ў Mastodon з любога меню абагульвання ў любой праграме
Прывабнасць: нашым талісманам з'яўляецца чароўны слон, і час ад часу ён будзеце з'яўляцца перад вамі
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
Mastodon з'яўляецца зарэгістраванай некамерцыйнай арганізацыяй і яго развіццё падтрымліваецца непасрэдна вашымі ахвяраваннямі. У нас няма рэкламы, манетызацыі і венчурнага капіталу, і мы плануем так і працягваць.

View File

@@ -1 +1 @@
Decentralized social network
Дэцэнтралізаваная сацыяльная сетка

View File

@@ -1,6 +1,6 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Join a community and create your profile. Find and and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Join a community and create your profile. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
@@ -13,4 +13,4 @@ More features:
• Sharing: Post directly to Mastodon from any share sheet in any app
• Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.

View File

@@ -1,6 +1,6 @@
Mastodon je največa decentralizovana socijalna mreža na internetu. Umjesto jednog websajta, ovo je netvork od nekoliko miliona korisnika na zasebnim platformama / zajednicama koje komuniciraju medjusobno i prenose podatke. Bez obzira čime se bavite, uvijek možete naći osobe sa slićnim interesima na Mastodonu!
Učlani se i napravi svoj profil. Potraži i prati osobe koje te zanimaju i gledaj njihove objave bez reklama. Izrazi svoja osjećanja odadtno koristeći smajlije, slike, GIF-ove, videa ili audio snimke. Limit je 500 znakova. Komentiraj ili prenesi objave na svoj profil od bilo koga ako vam se dopada sadrzaj. Potraži nove osobe ili popularne haštagove da obogatiš svoj netvork.
Učlani se i napravi svoj profil. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Izrazi svoja osjećanja odadtno koristeći smajlije, slike, GIF-ove, videa ili audio snimke. Limit je 500 znakova. Komentiraj ili prenesi objave na svoj profil od bilo koga ako vam se dopada sadrzaj. Potraži nove osobe ili popularne haštagove da obogatiš svoj netvork.
Mastodon je gradjen sa ciljem za bolju sigurnost i privatnost. Odluči da li objavljuješ nešto javno, samo prijateljima, samo osobama koje spomeneš ili cijelom svijetu. Napomene o osjetljivom sadrzaju vas obavjestavaju i pitaju za odobrenje ako zelite da ih vidite. Svaka platforma / zajednica ima svoja zasebna pravila koristenja i moderatore koji cuvaju platformu sigurnom,. Uz to imate opcije za blokadu bilo koga ili bilo cega sto vam se ne svidja.
@@ -13,4 +13,4 @@ Obavijesti: Primajte obavijesti o novim pratiocima, komentarima ili re-objavama
Dijeljenje: Objavljujte na Mastodonu sa bilo koje kompatibilne aplikacije
Ljepota: Nasa maskota je slon i vidjet cete ga s vremena na vrijeme
Mastodon je registrovan kao neprofitabilan i dalje finansiranje razvijanja direkntno zavisi od donacija. Nema reklamnog sadrzaja, nema monetizacije. Sve je besplatno i tako treba i da ostane.
Mastodon je registrovan kao neprofitabilan i dalje finansiranje razvijanja direkntno zavisi od donacija. Nema reklamnog sadrzaja, nema monetizacije. Sve je besplatno i tako treba i da ostane.

View File

@@ -13,4 +13,4 @@ Més funcionalitats:
• Compartir: Publica directament a Mastodon des de qualsevol full compartit de qualsevol aplicació
• Tendresa: La nostra mascota és un elefant adorable i veuràs que apareix de tant en tant
Mastodon és una organització sense ànim de lucre registrada i el desenvolupament se sosté directament amb les teves donacions. No hi ha publicitat, cap monetització i cap capital de risc, i planegem mantenir-ho així.
Mastodon és una organització sense ànim de lucre registrada i el desenvolupament se sosté directament amb les teves donacions. No hi ha publicitat, cap monetització i cap capital de risc, i planegem mantenir-ho així.

View File

@@ -1,6 +1,6 @@
Mastodon je největší decentralizovanou sociální sítí na internetu. Místo jediné webové stránky je to síť pro miliony uživatelů v nezávislých komunitách, ve kterých mohou všichni vzájemně a bezproblémově komunikovat. Bez ohledu na to, co vás baví, můžete se setkat s vášnivými lidmi, kteří o tom přispívají na Mastodon!
Připojte se ke komunitě a vytvořte svůj profil. Najděte a sledujte fascinující lidi a přečtěte si jejich příspěvky v chronologické časové ose bez reklam. Vyjádřete se pomocí vlastních emoji, obrázků, GIFů, videí a zvuku v 500-znakových příspěvcích. Odpovězte na vlákna a boostujte příspěvky od kohokoliv, abyste mohli sdílet skvělé věci. Najděte nové účty pro sledování a populární hashtagy pro rozšíření vaší sítě.
Připojte se ke komunitě a vytvořte svůj profil. Najděte a sledujte fascinující lidi a přečtěte si jejich příspěvky v bezreklamní chronologické časové linii. Vyjádřete se pomocí vlastních emoji, obrázků, GIFů, videí a zvuku v 500-znakových příspěvcích. Odpovězte na vlákna a boostujte příspěvky od kohokoliv, abyste mohli sdílet skvělé věci. Najděte nové účty pro sledování a populární hashtagy pro rozšíření vaší sítě.
Mastodon je postaven se zaměřením na soukromí a bezpečnost. Rozhodněte, zda jsou vaše příspěvky sdíleny se vašimi sledujícími, jen s lidmi, které zmíníte, nebo s celým světem. Upozornění na obsah vám umožní skrýt příspěvky obsahující citlivý nebo spouštěcí materiál, dokud se s nimi nezačnete zabývat. Každá komunita má vlastní pokyny a moderátory, aby udržela své členy v bezpečí, a robustní blokování a nahlašovací nástroje pomáhácí předcházení zneužití.
@@ -13,4 +13,4 @@ Více funkcí:
• Sdílení: Odesílání přímo do Mastodonu z libovolného seznamu sdílení v jakékoliv aplikaci
• Roztomilost: Naším maskotem je roztomilý slon, kterého čas od času uvidíte
Mastodon je registrovaný neziskový projekt a vývojový program je podporován přímo vašimi dary. Neexistuje žádná reklama, žádná monetizace a žádný rizikový kapitál a máme v plánu to udržet.
Mastodon je registrovaný neziskový projekt a vývojový program je podporován přímo vašimi dary. Neexistuje žádná reklama, žádná monetizace a žádný rizikový kapitál a máme v plánu to udržet.

View File

@@ -0,0 +1,16 @@
Mastodon er det største decentraliserede sociale netværk på internettet. I stedet for et enkelt website, er det et netværk af millioner af brugere i uafhængige fællesskaber som alle sammen kan interagere med hinanden. Uanset hvad du interesserer dig for, kan du møde engagerede mennesker som skriver om det på Mastodon!
Find et fællesskab og opret din profil. Find og følg fascinerende mennesker og læs deres indlæg i en reklamefri, kronologisk tidslinje. Udtryk dig selv med emojis, billeder, GIFs, videoer og lyd i indlæg på op til 500 tegn. Svar på tråde og del alt det gode ved at booste indlæg fra andre. Find nye brugere at følge og aktuelle hashtags så dit netværk udvides.
Mastodon er bygget med fokus på privatliv og sikkerhed. Beslut om dine indlæg skal deles med dine følgere, bare dem du nævner eller hele verden. Indholdsadvarsler giver dig mulighed for at gemme indlæg med sensitivt eller triggende indhold indtil du er klar til at læse dem. Hvert fællesskab har sine egne regler og moderatorer som holder øje og sikrer medlemmerne mod spam og trolde. De har robuste blokerings- og rapporteringsredskaber til deres rådighed.
Flere funktioner:
• Mørk Mode: Læs indlæg i lys, mørk eller ægte sort tilstand
• Afstemninger: Spørg tilhængere om deres mening og stemme
• Udforsk: Populære hashtags og konti er et tryk væk
• Notifikationer: Få besked om nye følgere, svar og boosts
• Deling: Send direkte til Mastodon fra en hvilken som app
• Nuttethedsfaktor: Vores maskot er en yndig elefant, og du vil se dem dukke op fra tid til anden
Mastodon er en registreret nonprofit og udvikling understøttes direkte af dine donationer. Der er ingen reklame, ingen indtægtsgenerering og ingen risikovillig kapital, og sådan forbliver det.

View File

@@ -0,0 +1 @@
Decentraliseret socialt netværk

View File

@@ -0,0 +1 @@
Mastodon

View File

@@ -1,6 +1,6 @@
Mastodon ist das größte dezentralisierte soziale Netzwerk im Internet. Statt einer einzigen Webseite ist es ein Netzwerk von Millionen von Benutzer*innen in unabhängigen Gemeinschaften, die alle miteinander interagieren können. Egal, was du magst, auf Mastodon kannst du begeisterte Menschen treffen, die darüber schreiben!
Tritt einer Gemeinschaft bei und erstelle dein Profil. Finde und folge faszinierenden Leuten und lies ihre Beiträge in einer werbefreien, chronologischen Zeitachse. Drücke dich mit eigenen Emojis, Bildern, GIFs, Videos und Klängen in 500-Zeichen-Beiträgen aus. Antworte auf Themen und teile Beiträge von anderen, um tolle Dinge zu verbreiten. Finde neue Konten zum Folgen und angesagte Hashtags, um dein Netzwerk zu erweitern.
Tritt einer Gemeinschaft bei und erstelle dein Profil. Entdecke und folge faszinierenden Menschen und lese ihre Beiträge in einer Werbefreien, chronologischen Timeline. Drücke dich mit eigenen Emojis, Bildern, GIFs, Videos und Klängen in 500-Zeichen-Beiträgen aus. Antworte auf Themen und teile Beiträge von anderen, um tolle Dinge zu verbreiten. Finde neue Konten zum Folgen und angesagte Hashtags, um dein Netzwerk zu erweitern.
Mastodon wurde mit einem Schwerpunkt auf Privatsphäre und Sicherheit gebaut. Entscheide, ob du deine Beiträge mit deinen Followern, nur mit den Menschen, die du erwähnst, oder mit der ganzen Welt teilen möchtest. Mit Inhaltswarnungen kannst du Beiträge mit sensiblem oder bedenklichen Inhalten ausblenden, bis du bereit bist, dich damit auseinanderzusetzen. Jede Gemeinschaft hat ihre eigenen Regeln und Moderator*innen, um die Sicherheit ihrer Mitglieder zu gewährleisten, sowie robuste Sperr- und Meldewerkzeuge, um Missbrauch vorzubeugen.
@@ -13,4 +13,4 @@ Weitere Funktionen:
• Teilen: veröffentliche auf Mastodon aus jeder beliebigen anderen App
• Niedlichkeit: unser Maskottchen ist ein entzückender Elefant und du wirst ihn von Zeit zu Zeit auftauchen sehen
Mastodon ist eine eingetragene gemeinnützige Organisation und die Entwicklung wird direkt durch deine Spenden unterstützt. Es gibt keine Werbung, keine Monetarisierung und kein Risikokapital und so soll es auch bleiben.
Mastodon ist eine eingetragene gemeinnützige Organisation und die Entwicklung wird direkt durch deine Spenden unterstützt. Es gibt keine Werbung, keine Monetarisierung und kein Risikokapital und so soll es auch bleiben.

View File

@@ -1,16 +1,16 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Το Mastodon είναι το μεγαλύτερο αποκεντρωμένο κοινωνικό δίκτυο στο διαδίκτυο. Αντί για μία ενιαία ιστοσελίδα, είναι ένα δίκτυο εκατομμυρίων χρηστών σε ανεξάρτητες κοινότητες που μπορούν όλοι να αλληλεπιδράσουν μεταξύ τους, απρόσκοπτα. Δεν έχει σημασία τί σας αρέσει, μπορείτε να συναντήσετε παθιασμένους ανθρώπους να μιλάνε γι' αυτό στο Mastodon!
Join a community and create your profile. Find and and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Εγγραφείτε σε μια κοινότητα και δημιουργήστε το προφίλ σας. Βρείτε και ακολουθήστε συναρπαστικούς ανθρώπους και διαβάσετε τις αναρτήσεις τους σε μία χωρίς διαφημίσεις, χρονολογική ροή. Εκφραστείτε με προσαρμοσμένα emoji, εικόνες, GIF, βίντεο και ήχο σε αναρτήσεις 500 χαρακτήρων. Απαντήστε σε νήματα και παραθέστε αναρτήσεις από οποιονδήποτε για να μοιραστείτε μεγάλα πράγματα. Βρείτε νέους λογαριασμούς για να ακολουθήσετε και δημοφιλείς ετικέτες για να επεκτείνετε το δίκτυό σας.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
Το Mastodon είναι κατασκευασμένο με έμφαση στην ιδιωτικότητα και την ασφάλεια. Αποφασίστε αν οι αναρτήσεις σας μοιράζονται με τους ακόλουθούς σας, μόνο τα άτομα που αναφέρετε ή ολόκληρο τον κόσμο. Προειδοποιήσεις περιεχομένου σας επιτρέπουν να κρύψετε αναρτήσεις που περιέχουν ευαίσθητο ή ανησυχητικό υλικό μέχρι να είστε έτοιμοι να συμμετάσχετε μαζί τους. Κάθε κοινότητα έχει τις δικές της οδηγίες και συντονιστές για να κρατήσει τα μέλη της ασφαλή και ισχυρά εργαλεία αποκλεισμού και αναφοράς βοηθούν στην πρόληψη της κατάχρησης.
More features:
Περισσότερα χαρακτηριστικά:
Dark Mode: Read posts in light, dark, or true black mode
Polls: Ask followers for their opinion and tally the votes
Explore: Trending hashtags and accounts are a tap away
Notifications: Get notified about new follows, replies, and reblogs
Sharing: Post directly to Mastodon from any share sheet in any app
Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Σκοτεινή λειτουργία: Διαβάστε αναρτήσεις σε φωτεινή, σκοτεινή ή την απόλυτα μαύρη λειτουργία
Δημοσκοπήσεις: Ρωτήστε τους ακόλουθους για τη γνώμη τους και συγκεντρώστε ψήφους
Εξερεύνηση: Δημοφιλείς ετικέτες και λογαριασμοί είναι ένα άγγιγμα μακριά
Ειδοποιήσεις: Ενημερωθείτε για νέους ακόλουθους, απαντήσεις και παραθέσεις
Κοινοποίηση: Αναρτήστε απευθείας στο Mastodon από οποιαδήποτε καρτέλα κοινής χρήσης σε οποιαδήποτε εφαρμογή
Χάρη: Η μασκότ μας είναι ένας αξιολάτρευτος ελέφαντας και θα τον δείτε να εμφανίζεται πού και πού
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
Το Mastodon είναι μη κερδοσκοπική και η ανάπτυξη υποστηρίζεται άμεσα από τις δωρεές σας. Δεν υπάρχουν διαφημίσεις, δεν γίνεται δημιουργία εσόδων και χωρίς επιχειρηματικά κεφάλαια και σκοπεύουμε να το διατηρήσουμε έτσι.

View File

@@ -1 +1 @@
Decentralized social network
Αποκεντρωμένο κοινωνικό δίκτυο

View File

@@ -1,8 +1,8 @@
Mastodon es la red social descentralizada más grande de internet. En lugar de ser una sola web, es una red de millones de usuarios en comunidades independientes que pueden interactuar entre ellas de forma transparente. No importa qué es lo que hagas, podrás encontrar gente apasionada escribiendo sobre ello en Mastodon!
Mastodon es la red social descentralizada más grande de internet. En lugar de ser una sola web, es una red de millones de usuarios en comunidades independientes que pueden interactuar entre ellas de forma transparente. Sin importar qué es lo que hagas, ¡podrás encontrar gente apasionada escribiendo sobre ello en Mastodon!
Únete a una comunidad y crea tu perfil. Encuentra y sigue a gente fascinante y lee sus publicaciones sin anuncios y de forma cronológica. Exprésate con emoticonos personalizados, imágenes, GIFs, vídeos y audio en publicaciónes de 500 caracteres. Responde a hilos e rebloguea publicaciones de cualquiera para compartir contenido genial. Encuentra nuevas cuentas para seguir y los hashtags de actualidad para expandir tu red.
Únete a una comunidad y crea tu perfil. Encuentra y sigue a gente fascinante y lea sus publicaciones sin anuncios y de forma cronológica. Exprésate con emojis personalizados, imágenes, GIFs, vídeos y audio en publicaciónes de 500 caracteres. Responde a hilos e rebloguea publicaciones de cualquiera para compartir contenido genial. Encuentra nuevas cuentas para seguir y los hashtags en tendencia para expandir tu red.
Mastodon está construída con un enfoque en la privacidad y la seguridad. Decide si tus publicaciones se comparten con tus seguidores, solo a la gente que menciones, o a todo el mundo. Las advertencias de contenido te permiten esconder publicaciones con contenido sensible o limitarlas de tu visión hasta que estés listo para interactuar con ellas. Cada comunidad tiene sus propias reglas y moderadores para mantener a salvo a sus miembros, además de herramientas robustas para bloquear y reportar contenido para prevenir el abuso.
Mastodon está construido con un enfoque en la privacidad y la seguridad. Decide si tus publicaciones se comparten con tus seguidores, solo a la gente que menciones, o a todo el mundo. Las advertencias de contenido te permiten esconder publicaciones con contenido sensible o limitarlas de tu visión hasta que estés listo para interactuar con ellas. Cada comunidad tiene sus propias directrices y moderadores para mantener la seguridad de sus miembros, y unas sólidas herramientas de bloqueo y denuncia que ayudan a evitar los abusos.
Más características:
@@ -13,4 +13,4 @@ Más características:
• Compartir: Publica directamente a Mastodon desde cualquier hoja de acción en cualquier aplicación
• Preciosidad: Nuestra mascota es un elefante adorable, y verás que aparece de vez en cuando
Mastodon es una organización sin ánimo de lucro registrada y su desarrollo se financia directamente con tus donaciones. No hay publicidad, ni monetización, ni capital de riesgo, y tenemos previsto mantenerlo así.
Mastodon es una organización sin ánimo de lucro registrada y su desarrollo se financia directamente con tus donaciones. No hay publicidad, ni monetización, ni capital de riesgo, y tenemos previsto mantenerlo así.

View File

@@ -1,6 +1,6 @@
Mastodon Interneteko sare sozial deszentralizatu handiena da. Webgune bakar bat izan ordez, beren artean elkarreragin dezaketen komunitate independenteetako milioika erabiltzailek osatutako sarea da. Zure interesak direnak direla ere, jende interesgarria aurkituko duzu Mastodonen!
Batu komunitate batera eta sortu zure profila. Bilatu eta jarraitu jende zoragarria eta irakurri beren bidalketak, publizitaterik gabeko denbora-lerro kronologikoan. Adierazi nahi duzuna 500 karaktereko bidalketetan emoji pertsonalizatuak, irudiak, GIFak, bideoak eta audioak erabiliz. Erantzun edozeinen hariak eta eman bultzada bidalketei edukiak partekatzeko. Bilatu jarraitzeko kontu berriak eta traolen joerak zure sarea zabaltzeko.
Batu komunitate batera eta sortu zure profila. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Adierazi nahi duzuna 500 karaktereko bidalketetan emoji pertsonalizatuak, irudiak, GIFak, bideoak eta audioak erabiliz. Erantzun edozeinen hariak eta eman bultzada bidalketei edukiak partekatzeko. Bilatu jarraitzeko kontu berriak eta traolen joerak zure sarea zabaltzeko.
Mastodon pribatutasunean eta segurtasunean arreta jarriz eraikia dago. Erabaki zure bidalketak norekin partekatu: zure jarraitzaileekin, aipatzen dituzunekin edo mundu osoarekin. Edukiaren abisuek aukera ematen dute eduki sentibera edo zuregan eragina izan dezaketen bidalketak zuk erabaki arte ezkutatzeko. Komunitate bakoitzak bere gidalerro eta moderatzaileak ditu, bertako kideak seguru mantentzeko. Baita blokeatzeko eta salatzeko tresna sendoak ere abusuak galarazteko.
@@ -13,4 +13,4 @@ Ezaugarri gehiago:
• Partekatzea: Argitaratu zuzenean Mastodonen edozein aplikaziotako partekatze-orritik
• Edertasuna: Gure maskota elefante maitagarri bat da eta tarteka agertuko zaizu
Mastodon erregistratutako irabazi asmorik gabeko elkartea da eta zure dohaintzen bidez babesten da garapena. Ez dago iragarkirik, irabazi asmorik eta inbertsio kapitalik, eta horrela jarraitzeko asmoa dugu.
Mastodon erregistratutako irabazi asmorik gabeko elkartea da eta zure dohaintzen bidez babesten da garapena. Ez dago iragarkirik, irabazi asmorik eta inbertsio kapitalik, eta horrela jarraitzeko asmoa dugu.

View File

@@ -0,0 +1,16 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Join a community and create your profile. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
More features:
• Dark Mode: Read posts in light, dark, or true black mode
• Polls: Ask followers for their opinion and tally the votes
• Explore: Trending hashtags and accounts are a tap away
• Notifications: Get notified about new follows, replies, and reblogs
• Sharing: Post directly to Mastodon from any share sheet in any app
• Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.

View File

@@ -0,0 +1 @@
Decentralized social network

View File

@@ -0,0 +1 @@
Mastodon

View File

@@ -1,6 +1,6 @@
Mastodon on internetin suurin hajautettu sosiaalinen verkosto. Yhden verkkopalvelun sijaan, se on miljoonien itsenäisissä yhteisöissä olevien käyttäjien verkosto, jotka voivat olla vuorovaikutuksessa toistensa kanssa saumattomasti. Riippumatta siitä, mistä olet kiinnostunut, voit tavata intohimoisia ihmisiä, jotka julkaisevat aiheesta Mastodonissa!
Liity yhteisöön ja luo itsellesi tili. Löydä ja seuraa kiehtovia ihmisiä ja lue heidän julkaisunsa ilman mainoksia, kronologisella aikajanalla. Ilmaise itseäsi mukautetuilla emojeilla, kuvilla, videoilla ja audiolla 500 merkin pituisissa julkaisuissa. Vastaa viestiketjuihin ja edelleen jaa julkaisuja keneltä tahansa, jakaaksesi hienoja juttuja. Löydä uusia tilejä seurattavaksi ja trendaavia hashtageja laajentaaksesi verkostoasi.
Liity yhteisöön ja luo itsellesi tili. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Ilmaise itseäsi mukautetuilla emojeilla, kuvilla, videoilla ja audiolla 500 merkin pituisissa julkaisuissa. Vastaa viestiketjuihin ja edelleen jaa julkaisuja keneltä tahansa, jakaaksesi hienoja juttuja. Löydä uusia tilejä seurattavaksi ja trendaavia hashtageja laajentaaksesi verkostoasi.
Mastodon on rakennettu keskittyen yksityisyyteen ja turvallisuuteen. Päätä, jaetaanko julkaisusi seuraajille, vain mainitsemillesi ihmisille vai koko maailmalle. Sisältövaroitusten avulla, voit piilottaa julkaisut, jotka sisältävät arkaluontoista tai laukaisevaa materiaalia, kunnes olet valmis käsittelemään niitä. Jokaisella yhteisöllä on omat ohjeistonsa ja valvojansa, jotka pitävät jäsenensä turvassa, ja tehokkaat esto- ja ilmiantotyökalut auttavat torjumaan väärinkäytöksiä.
@@ -13,4 +13,4 @@ Lisää ominaisuuksia:
• Jakaminen: Julkaise suoraan Mastodoniin minkä tahansa sovelluksen jakovalikon kautta
• Suloisuus: Maskottimme on ihastuttava mastodontti ja näet sen ajoittain
Mastodon on rekisteröity voittoa tavoittelematon organisaatio ja kehitystä tuetaan suoraan lahjoituksillasi. Ei mainontaa, kaupallistamista eikä riskipääomaa, ja aiomme pitää sen sellaisena.
Mastodon on rekisteröity voittoa tavoittelematon organisaatio ja kehitystä tuetaan suoraan lahjoituksillasi. Ei mainontaa, kaupallistamista eikä riskipääomaa, ja aiomme pitää sen sellaisena.

View File

@@ -1,16 +1,16 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Ang Mastodon ay ang pinakamalaking desentralisadong social network sa internet. Sa halip na isang solong website, ito ay isang network ng milyun-milyong mga gumagamit sa mga independiyenteng komunidad na lahat ay maaaring makipag-ugnay sa isa ' t isa, nang walang putol. Hindi mahalaga kung ano ang iyong naroroon, maaari mong matugunan ang mga madamdaming tao na nagpo-post tungkol dito sa Mastodon!
Join a community and create your profile. Find and and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Sumali sa isang komunidad at lumikha ng iyong profile. Hanapin at sundin ang mga kamangha-manghang mga tao at basahin ang kanilang mga post sa isang ad-free, magkakasunod na timeline. Ipahayag ang iyong sarili gamit ang pasadyang emoji, mga imahe, GIF, Video, at audio sa 500-character na mga post. Tumugon sa mga thread at reblog post mula sa sinuman para magbahagi ng magagandang bagay. Maghanap ng mga bagong account na susundan at nagte-trend na mga hashtag para mapalawak ang iyong network.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
Ang Mastodon ay binuo na may pagtuon sa pribado at kaligtasan. Magpasya ka kung ang iyong mga post ay ibinabahagi sa iyong mga tagasunod, ang mga taong binanggit mo lamang, o ang buong mundo. Hinahayaan ka ng mga babala sa nilalaman na itago ang mga post na naglalaman ng sensitibo o nakaka-trigger na materyal hanggang sa handa ka nang makisali sa kanila. Ang bawat komunidad ay may sariling mga alituntunin at moderator para mapanatiling ligtas ang mga miyembro nito, at ang matatag na mga tool sa pag-block at pag-uulat ay makakatulong na maiwasan ang pang-aabuso.
More features:
Higit pang mga tampok:
• Dark Mode: Read posts in light, dark, or true black mode
• Polls: Ask followers for their opinion and tally the votes
• Explore: Trending hashtags and accounts are a tap away
• Notifications: Get notified about new follows, replies, and reblogs
• Sharing: Post directly to Mastodon from any share sheet in any app
Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
* Madilim na Mode: Basahin ang mga post sa liwanag, madilim, o maitim na mode
* Mga botohan: hilingin sa mga tagasunod ang kanilang opinyon at tally ang mga boto
* Galugarin: nagte-trend hashtags at mga account ay isang tap ang layo
* Mga Abiso: Maabisuhan tungkol sa mga bagong sumusunod, tugon, at reblogs
* Pagbabahagi: Mag-Post nang direkta sa Mastodon mula sa anumang share sheet sa anumang app
* Cuteness: ang aming maskot ay isang kaibig-ibig na elepante, at makikita mo silang pop up paminsan-minsan
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
Mastodon ay isang rehistradong nonprofit at pag-unlad ay suportado nang direkta sa pamamagitan ng iyong mga donasyon. Walang advertising, walang monetization, at walang venture capital, at plano naming panatilihin ito sa ganoong paraan.

View File

@@ -1 +1 @@
Decentralized social network
Desentralisadong social network

View File

@@ -1,6 +1,6 @@
Mastodon est le plus grand réseau social décentralisé sur Internet. Au lieu dun site Web unique, cest un réseau de millions dutilisateurs dans des communautés indépendantes qui peuvent tous interagir les uns avec les autres, de manière transparente. Peu importe ce que vous êtes, vous pouvez rencontrer des gens passionnés qui publient à ce sujet sur Mastodon !
Rejoignez une communauté et créez votre profil. Trouvez et suivez des gens fascinants et lisez leurs messages dans une chronologie chronologique sans publicité. Exprimez-vous avec des émojis personnalisés, des images, des GIFs, des vidéos et de laudio dans des messages de 500 caractères. Répondez aux sujets de discussions et aux reblogues de nimporte qui pour partager des choses géniales. Trouvez de nouveaux comptes à suivre et des hashtags tendance pour étendre votre réseau.
Rejoignez une communauté et créez votre profil. Trouvez et suivez des personnes fascinantes et lisez leurs messages chronologiquement et sans publicité. Exprimez-vous avec des émojis personnalisés, des images, des GIFs, des vidéos et de laudio dans des messages de 500 caractères. Répondez aux sujets de discussions et aux reblogues de nimporte qui pour partager des choses géniales. Trouvez de nouveaux comptes à suivre et des hashtags tendance pour étendre votre réseau.
Mastodon est construit en mettant laccent sur la vie privée et la sécurité. Décidez si vos messages sont partagés avec vos abonnés, les personnes que vous mentionnez, ou le monde entier. Les avertissements de contenu vous permettent de masquer les messages au contenu sensible jusquà ce que vous soyez prêt à vous engager avec eux. Chaque communauté a ses propres directives et modérateurs pour assurer la sécurité de ses membres, et de solides outils de blocage et de signalement aident à prévenir les abus.
@@ -13,4 +13,4 @@ Plus de fonctionnalités :
• Partage : Publiez directement sur Mastodon à partir de nimporte quelle feuille de partage dans nimporte quelle application
• Cuteness : Notre mascotte est un adorable éléphant, et vous la verrez apparaître de temps en temps
Mastodon est un organisme sans but lucratif enregistré et le développement est soutenu directement par vos dons. Il ny a pas de publicité, pas de monétisation, pas de capital-risque, et nous prévoyons de continuer ainsi.
Mastodon est un organisme sans but lucratif enregistré et le développement est soutenu directement par vos dons. Il ny a pas de publicité, pas de monétisation, pas de capital-risque, et nous prévoyons de continuer ainsi.

View File

@@ -1,6 +1,6 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Join a community and create your profile. Find and and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Join a community and create your profile. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
@@ -13,4 +13,4 @@ More features:
• Sharing: Post directly to Mastodon from any share sheet in any app
• Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.

View File

@@ -1,6 +1,6 @@
S e an lìonra sòisealta sgaoilte as motha air an eadar-lìon a th ann am Mastodon. Seach aon làrach-lìn a-mhàin, s e lìonra de mhilleanan de dhaoine ann an coimhearsnachdan neo-eisimeileach a th ann agus s urrainn dhan a h-uile duine bruidhinn ri chèile fhathast gun duilgheadas. Ge b e dè na rudan a tha ùidh agad annta, coinnichidh tu ri daoine a sgrìobhas mun dèidhinn air Mastodon!
Faigh ballrachd ann an coimhearsnachd s cruthaich pròifil dhut. Lorg is lean daoine inntinneach agus leugh na postaichean aca air loidhne-ama cheart gun sanasachd. Cuir thu fhèin an cèill le Emojis gnàthaichte, dealbhan, GIFs, videothan is fuaimean ann am postaichean le 500 caractar. Freagair ri snàithleanan is brosnaich postaichean le neach sam bith airson deagh rudan a cho-roinneadh. Lorg cunntasan ùra ri leantainn is tagaichean hais a treandadh airson an lìonra agad a leudachadh.
Faigh ballrachd ann an coimhearsnachd s cruthaich pròifil dhut. Lorg is lean daoine inntinneach leugh na postaichean aca air loidhne-ama cheart gun sanasachd. Cuir thu fhèin an cèill le Emojis gnàthaichte, dealbhan, GIFs, videothan is fuaimean ann am postaichean le 500 caractar. Freagair ri snàithleanan is brosnaich postaichean le neach sam bith airson deagh rudan a cho-roinneadh. Lorg cunntasan ùra ri leantainn is tagaichean hais a treandadh airson an lìonra agad a leudachadh.
Chaidh Mastodon a thogail leis an aire air prìobhaideachd is sàbhailteachd. Tha e an urra riut fhèin an co-roinn thu post leis an luchd-leantainn agad, leis na daoine air an doir thu iomradh a-mhàin no leis an t-saoghal mhòr. Leigidh rabhaidhean susbainte leat postaichean sa bheil susbaint fhrionasach fhalach is cha leig daoine leas coimhead air ach nuair a bhios iad deònach. Tha riaghailtean is maoir fa leth aig gach coimhearsnachd airson a buill a chumail sàbhailte agus cuidichidh innealan bacaidh is gearain le dìon o dhroch-dhìol.
@@ -13,4 +13,4 @@ Gleusan eile:
• Co-roinn: Postaich gu Mastodon gu dìreach o shiota co-roinnidh ann an aplacaid sam bith
• Stampachd: S e ailbhean ealanta a tha san t-suaichnean againn is nochdaidh e o àm gu àm
S e bhuidheann neo-phrothaideach clàraichte a th ann am Mastodon a gheibh taic dhìreach o na tabhartasan agad. Chan eil sanasachd, airgeadachadh no calpa iomairte sam bith ann agus tha fainear dhuinn ga chumail mar sin.
S e bhuidheann neo-phrothaideach clàraichte a th ann am Mastodon a gheibh taic dhìreach o na tabhartasan agad. Chan eil sanasachd, airgeadachadh no calpa iomairte sam bith ann agus tha fainear dhuinn ga chumail mar sin.

View File

@@ -1,6 +1,6 @@
Mastodon é a rede social descentralizada máis grande de internet. Non é unha soa web, é unha rede de millóns de persoas en comunidades independentes que poden interactuar entre elas, sen problema. Sexan cales fosen os teus intereses, podes atopar persoas comentando ese tema en Mastodon!
Únete a unha comunidade e crea un perfil. Atopa e segue a persoas interesantes e le o que publican, nunha cronoloxía limpa de publicidade e ordenada. Exprésate usando emojis personalizados, imaxes, GIFs, vídeos e audio con publicacións de 500 caracteres. Responde aos fíos e promove publicacións doutras persoas que creas relevantes. Atopa novas contas e segue os cancelos en voga para facer medrar a túa rede.
Únete a unha comunidade e crea un perfil. Atopa e sigue a persoas abraiantes lendo as súas publicacións en cronoloxías sen publicidade e orde cronolóxica. Exprésate usando emojis personalizados, imaxes, GIFs, vídeos e audio con publicacións de 500 caracteres. Responde aos fíos e promove publicacións doutras persoas que creas relevantes. Atopa novas contas e segue os cancelos en voga para facer medrar a túa rede.
Mastodon está creado pensando na privacidade e seguridade. Decide con quen compartes as túas publicacións, só coas seguidoras ou persoas que mencionas, ou con todo o mundo. Os avisos sobre o contido permiten agochar contido sensible ou material que podería crear ansiedade ata que estás preparada para velo. Cada comunidade ten as súas normas e a moderación coida da seguridade das persoas da instancia, con ferramentas para denunciar e bloquear e así evitar abusos.
@@ -13,4 +13,4 @@ Máis características:
• Compartir: publica directamente en Mastodon desde o menú de calquera app
• Fermosura: a nosa mascota é un elefante moi feitiño, que verás a miúdo por aquí
Mastodon é unha organización rexistrada sen ánimo de lucro cuxo desenvolvemento está financiado por doazóns. Non hai publicidade, nen monetización, sen inversións de capital risco, e pretendemos seguir así.
Mastodon é unha organización rexistrada sen ánimo de lucro cuxo desenvolvemento está financiado por doazóns. Non hai publicidade, nen monetización, sen inversións de capital risco, e pretendemos seguir así.

View File

@@ -1,6 +1,6 @@
מסטודון היא הרשת החברתית המבוזרת הגדולה ביותר באינטרנט. במקום אתר אחד, מסטודון היא רשת של מיליוני משתמשים בקהילות עצמאיות שיכולות לפעול ביחד באופן חלק. לא משנה מה הקטע שלכם, אתם יכולים לפגוש אנשים שמתעניינים בו וכותבים עליו במסטודון!
הצטרפו לקהילה וצרו את המשתמש שלכם. גלו ועקבו אחר אנשים מרתקים וקראו את הרשומות שלהם על גבי ציר זמן כרונולוגי וללא פרסומות. הביעו את עצמכם באמצעות אמוג׳ים מעוצבים, תמונות, גיפים, סרטונים, ושמע ברשומות של עד 500 תווים. הגיבו לשרשורים ועשו ״ריבלוג״ לרשומות של כל מי שאתם רוצים כדי לשתף דברים מגניבים. מצאו חשבונות חדשים לעקוב אחריהם והאשטגים טרנדיים כדי להרחיב את רשתותיכם.
הצטרפו לקהילה וצרו את המשתמש שלכם. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. הביעו את עצמכם באמצעות אמוג׳ים מעוצבים, תמונות, גיפים, סרטונים, ושמע ברשומות של עד 500 תווים. הגיבו לשרשורים ועשו ״ריבלוג״ לרשומות של כל מי שאתם רוצים כדי לשתף דברים מגניבים. מצאו חשבונות חדשים לעקוב אחריהם והאשטגים טרנדיים כדי להרחיב את רשתותיכם.
מסטודון בנויה עם פוקוס על פרטיות ובטיחות. קבעו האם הרשומות יתפרסמו עבור העוקבים שלכם, רק האנשים שאתם מציינים, או כל העולם. אזהרות תוכן מאפשרות לכם להסתיר רשומות המכילות תוכן רגיש או שעלול להוות טריגר עד שתהיו מוכנים להתמודד איתן. לכל קהילה כללים ומנהלים משלה שמטרתם לשמור על כך שכל חבריה יהיו בטוחים, וכלי חסימה ודיווח ענפים כדי לעזור למנוע שימוש לרעה.
@@ -13,4 +13,4 @@
• שיתוף: העלו ישירות למסטודון מכל עמוד שיתוף בכל אפליקציה
• חמידות: הקמע שלנו הוא פיל מקסים, ואתם תראו אותם מופיעים פה ושם
מסטודון רשומה כארגון ללא מטרות רווח והפיתוח ממומן ישירות מתרומותכם. אין שום פרסומות, שום תרגום מובנה של הצלחה לכסף, ושום הון־סיכון, ואנחנו מתכננים לשמור על זה כך.
מסטודון רשומה כארגון ללא מטרות רווח והפיתוח ממומן ישירות מתרומותכם. אין שום פרסומות, שום תרגום מובנה של הצלחה לכסף, ושום הון־סיכון, ואנחנו מתכננים לשמור על זה כך.

View File

@@ -1,6 +1,6 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Join a community and create your profile. Find and and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Join a community and create your profile. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
@@ -13,4 +13,4 @@ More features:
• Sharing: Post directly to Mastodon from any share sheet in any app
• Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.

View File

@@ -1,6 +1,6 @@
Mastodon je najveća decentralizirana društvena mreža na internetu. Umjesto jedne web stranice, to je mreža milijuna korisnika u neovisnim zajednicama koje sve mogu međusobno komunicirati. Bez obzira na to što te zanima, možeš upoznati strastvene ljude koji o tome objavljuju na Mastodonu!
Pridruži se zajednici i kreiraj svoj profil. Pronađi i prati fascinantne ljude i čitaj njihove postove u kronološkoj vremenskoj liniji bez oglasa. Izrazi se prilagođenim emojijima, slikama, GIF-ovima, videozapisima i zvukom u objavama od 500 znakova. Odgovori na teme i reblogaj postove od bilo koga da podijeliš sjajne stvari. Pronađi nove račune koje ćeš pratiti i popularne hashtagove kako bi proširio/la svoju mrežu.
Pridruži se zajednici i kreiraj svoj profil. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Izrazi se prilagođenim emojijima, slikama, GIF-ovima, videozapisima i zvukom u objavama od 500 znakova. Odgovori na teme i reblogaj postove od bilo koga da podijeliš sjajne stvari. Pronađi nove račune koje ćeš pratiti i popularne hashtagove kako bi proširio/la svoju mrežu.
Mastodon je izgrađen s fokusom na privatnost i sigurnost. Odluči hoće li se tvoje objave dijeliti s tvojim sljedbenicima, samo s osobama koje spominjete ili s cijelim svijetom. Upozorenja o sadržaju omogućuju ti da sakriješ postove koji sadrže osjetljivi ili izazovni materijal dok ne budeš spreman za interakciju s njima. Svaka zajednica ima vlastite smjernice i moderatore kako bi zaštitili svoje članove, a robusni alati za blokiranje i prijavljivanje pomažu u sprječavanju zlouporabe.
@@ -13,4 +13,4 @@ Više značajki:
• Dijeljenje: objavi izravno na Mastodonu s bilo kojeg lista za dijeljenje u bilo kojoj aplikaciji
• Slatkoća: Naša maskota je ljupki slon i vidjet ćeš ih kako iskaču s vremena na vrijeme
Mastodon je registrirana neprofitna organizacija i razvoj je podržan izravno vašim donacijama. Nema oglašavanja, nema monetizacije i rizičnog kapitala, a planiramo takvi i ostati.
Mastodon je registrirana neprofitna organizacija i razvoj je podržan izravno vašim donacijama. Nema oglašavanja, nema monetizacije i rizičnog kapitala, a planiramo takvi i ostati.

View File

@@ -1,16 +1,16 @@
A Mastodon a legnagyobb decentralizált közösségi hálózat az interneten. Egyetlen weboldal helyett, ez több millió felhasználóból álló, független közösségek hálózata, amelyek egymással kapcsolatba tudnak lépni, zökkenőmentesen. Nem számít, mi a hobbid, a Mastodonon találkozhatsz róla posztoló lelkes emberekkel!
A Mastodon a legnagyobb decentralizált közösségi hálózat az interneten. Egyetlen weboldal helyett, ez több millió felhasználóból álló, független közösségek hálózata, amelyek egymással kapcsolatba tudnak lépni, zökkenőmentesen. Nem számít, mi az érdeklődésed, a Mastodonon találkozhatsz róla posztoló lelkes emberekkel!
Csatlakozz egy közösséghez és készítsd el a profilodat. Keress és kövess lenyűgöző embereket, és olvasd egy reklámmentes, kronologikus idővonalon a bejegyzéseiket. Fejezd ki magad egyedi hangulatjelekkel, képekkel, GIFekkel, videókkal és hanggal, 500 karakter hosszúságú posztokban. Reply to threads and reblog posts from anyone to share great stuff. Fedezz fel új fiókokat amiket követhetsz és felkapott hashtageket, hogy bővíthesd a kapcsolataidat.
Csatlakozz egy közösséghez és készítsd el a profilodat. Találj meg és kövess be fantasztikus embereket, olvasd el a bejegyzéseiket reklámmentesen, időrendben. Fejezd ki magad egyedi hangulatjelekkel, képekkel, GIFekkel, videókkal és hanggal, 500 karakter hosszúságú bejegyzésekben. Válaszolj szálakban, told meg bárki bejegyzését, hogy megoszthass szuper dolgokat. Fedezz fel új fiókokat amiket követhetsz és felkapott hashtageket, hogy bővíthesd a kapcsolataidat.
A Mastodon az adatvédelemre és a biztonságra összpontosítva épült. Döntsd el, hogy a posztjaidat csak a követőiddel, csak azokkal akiket megemlítesz, vagy az egész világgal osztod meg. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
A Mastodon az adatvédelemre és a biztonságra összpontosítva épült. Döntsd el, hogy a bejegyzéseidet csak a követőiddel, csak azokkal akiket megemlítesz, vagy az egész világgal osztod meg. A tartalomfigyelmeztetések elrejthetővé teszik az érzékeny vagy ingerlő tartalmakat addig, amíg nem vagy kész azok megtekintésére. Minden közösségnek saját irényelvei és moderátorai vannak arra, hogy biztonságban tudják a tagjaikat. Erőteljes letiltási és bejelentési eszközök segítik a visszaélések megelőzését.
More features:
További funkciók:
Dark Mode: Read posts in light, dark, or true black mode
Polls: Ask followers for their opinion and tally the votes
Explore: Trending hashtags and accounts are a tap away
Notifications: Get notified about new follows, replies, and reblogs
Sharing: Post directly to Mastodon from any share sheet in any app
• Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Sötét mód: Olvasd a bejegyzéseket világos, sötét vagy teljesen fekete módban
Szavazás: Kérd ki a követőid véleményét és összesítsd a szavazataikat
Felfedezés: A felkapott hashtagek és fiókok egyetlen kattintásra vannak
Értesítések: Értesülj az új követőidről, válaszokról, megtolásokról
Megosztás: Írj bejegyzést Mastodonra bármely app megosztási funkciójával
• Cukiság: A kabalánk egy cuki elent, mely fel fog bukkanni időről időre
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
A Mastodon egy bejegyzett non-profit szervezet, a fejlesztés közvetlenül a te adományaidból történik. Nincs hirdetés, se monetizáció, se kockázati tőke, és ez így is fog maradni.

View File

@@ -1,16 +1,16 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Մաստոդոնը համացանցի ամենամեծ ապակենտրոնացված սոցցանցն է։ Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Join a community and create your profile. Find and and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Join a community and create your profile. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
More features:
Ավելին՝
Dark Mode: Read posts in light, dark, or true black mode
Polls: Ask followers for their opinion and tally the votes
Մուգ տարբերակ՝ կարդացեք գրառումներ մուգ, բաց կամ իսկական սև տարբերակներում
Հարցումներ՝ իմացեք ձեր հետևորդների կարծիքը և հաշվեք քվեները
• Explore: Trending hashtags and accounts are a tap away
• Notifications: Get notified about new follows, replies, and reblogs
• Sharing: Post directly to Mastodon from any share sheet in any app
• Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.

View File

@@ -1,6 +1,6 @@
Mastodon adalah jejaring sosial terdesentralisasi terbesar di internet. Daripada sebuah satu situs web, ini adalah jaringan dari jutaan pengguna dalam komunitas tersendiri yang dapat berinteraksi antar sesama, tanpa masalah. Tanpa memedulikan apa yang Anda minat, Anda dapat bertemu orang-orang yang mengirimkan apa yang mereka minat di Mastodon!
Bergabung sebuah komunitas dan buat profil Anda. Temukan dan ikuti orang-orang menarik dan lihat kiriman mereka dalam linimasa kronologis tanpa iklan. Ekspresikan diri Anda dengan emoji kustom, gambar, GIF, video, dan audio dalam kiriman dengan batasan 500 karakter. Balas ke utasan dan bagikan kiriman dari siapa pun ke pengikut Anda untuk membagikan hal-hal yang keren. Temukan akun baru untuk diikuti dan tagar yang sedang tren untuk memperluas jejaring Anda.
Bergabung sebuah komunitas dan buat profil Anda. Temukan dan ikuti orang-orang yang menarik dan baca postingan mereka dalam lini masa yang kronologis dan bebas iklan. Ekspresikan diri Anda dengan emoji kustom, gambar, GIF, video, dan audio dalam kiriman dengan batasan 500 karakter. Balas ke utasan dan bagikan kiriman dari siapa pun ke pengikut Anda untuk membagikan hal-hal yang keren. Temukan akun baru untuk diikuti dan tagar yang sedang tren untuk memperluas jejaring Anda.
Mastodon dibuat dengan fokus pada privasi dan keamanan. Tentukan apakah kiriman Anda dibagikan kepada pengikut, hanya orang yang disebut, atau seluruh dunia. Peringatan konten memungkinkan Anda untuk menyembunyikan kiriman yang berisi material sensitif atau memicu sampai Anda siap untuk terlibat dengan mereka. Setiap komunitas memiliki pedoman dan moderator sendiri-sendiri untuk menjaga anggotanya aman, dan alat pemblokiran dan pelaporan yang kokoh membantu mencegah pelecehan.
@@ -13,4 +13,4 @@ Fitur lainnya:
• Pembagian: Kirim langsung ke Mastodon dari lembar pembagian apa pun dalam aplikasi apa pun
• Kelucuan: Maskot kami adalah seekor gajah yang lucu, dan Anda akan melihat dia muncul dari waktu ke waktu
Mastodon adalah nirlaba yang terdaftar dan pengembangan didukung secara langsung dari donasi Anda. Tanpa periklanan, tanpa monetisasi, dan tanpa kapitalisme ventura, dan kami berencana untuk tetap seperti itu.
Mastodon adalah nirlaba yang terdaftar dan pengembangan didukung secara langsung dari donasi Anda. Tanpa periklanan, tanpa monetisasi, dan tanpa kapitalisme ventura, dan kami berencana untuk tetap seperti itu.

View File

@@ -0,0 +1,16 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Join a community and create your profile. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
More features:
• Dark Mode: Read posts in light, dark, or true black mode
• Polls: Ask followers for their opinion and tally the votes
• Explore: Trending hashtags and accounts are a tap away
• Notifications: Get notified about new follows, replies, and reblogs
• Sharing: Post directly to Mastodon from any share sheet in any app
• Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.

View File

@@ -0,0 +1 @@
Decentralized social network

View File

@@ -0,0 +1 @@
Mastodon

View File

@@ -27,4 +27,4 @@ forriti sem er
Mastodon er skráð óhagnaðardrifin sjálfseignarstofnun og er þróun þess
drifin áfram með styrkjum frá þér. Það eru engar auglýsingar, engin gjaldtaka og engir áhættufjárfestar - við
höfum hugsað okkur að halda því þannig.
höfum hugsað okkur að halda því þannig.

View File

@@ -1,6 +1,6 @@
Mastodon è il più grande social network decentralizzato su Internet. Invece di un singolo sito web, è una rete di milioni di utenti in comunità indipendenti che possono interagire tra loro, senza soluzione di continuità. Non importa cosa ti piaccia, puoi incontrare persone appassionate pubblicando a riguardo su Mastodon!
Unisciti a una comunità e crea il tuo profilo. Trova e segui persone affascinanti e leggi i loro messaggi in una timeline cronologica senza pubblicità. Esprimiti con emoji personalizzate, immagini, GIF, filmati e audio in 500 caratteri. Rispondi a thread e post condivisi da chiunque per condividere grandi cose. Trova nuovi account da seguire e hashtags in tendenza per espandere la tua rete.
Unisciti a una comunità e crea il tuo profilo. Trova e segui persone affascinanti e leggi i loro post in una timeline cronologica senza pubblicità. Esprimiti con emoji personalizzate, immagini, GIF, filmati e audio in 500 caratteri. Rispondi a thread e post condivisi da chiunque per condividere grandi cose. Trova nuovi account da seguire e hashtags in tendenza per espandere la tua rete.
Mastodon è costruito con attenzione sulla privacy e sulla sicurezza. Decidi se i tuoi post saranno visibili solo ai tuoi seguaci, alle persone che menzioni o al mondo intero. Gli avvertimenti sul contenuto ti permettono di nascondere i post contenenti materiale sensibile o provocatorio fino a quando non sarai pronto a interagire con loro. Ogni comunità ha le proprie linee guida e moderatori per mantenere i propri membri sicuri. Robusti strumenti di blocco e segnalazione aiutano a prevenire gli abusi.
@@ -13,4 +13,4 @@ Altre caratteristiche:
• Condivisione: Pubblica direttamente su Mastodon da qualsiasi foglio di condivisione in qualsiasi app
• Bellezza: La nostra mascotte è un elefante adorabile, e lo vedrete apparire di tanto in tanto
Mastodon è una no-profit registrata e lo sviluppo è supportato direttamente dalle vostre donazioni. Non c'è pubblicità, monetizzazione e capitale di rischio, e abbiamo intenzione di mantenerlo in quel modo.
Mastodon è una no-profit registrata e lo sviluppo è supportato direttamente dalle vostre donazioni. Non c'è pubblicità, monetizzazione e capitale di rischio, e abbiamo intenzione di mantenerlo in quel modo.

View File

@@ -1,8 +1,8 @@
Mastodonは、インターネット上で最大の分散型ソーシャルネットワークです。 Mastodonは単一のウェブサイトではなく、それぞれ独立したコミュニティに参加している何百万人ものユーザーによって構成されたネットワークなのです。ユーザーたちはその中で、誰もがお互いとシームレスにやり取りできます。 あなたの興味関心がどんな分野にあっても、きっとMastodonのどこかで同じ情熱を投稿している仲間がいますよ!
Mastodonは、インターネット上で最大の分散型ソーシャルネットワークです。 Mastodonは単一のウェブサイトではなく、それぞれ独立したコミュニティに参加している何百万人ものユーザーによって構成されたネットワークなのです。ユーザーたちはその中で、誰もがお互いとシームレスにやり取りできます。 あなたの興味関心がどんな分野にあっても、きっとMastodonのどこかで同じ情熱を投稿している仲間がいることでしょう。
まずはコミュニティに参加して、自分のプロフィールを作成しましょう。 そして素敵なユーザーを見つけ、フォローしてタイムラインで投稿を見てみましょう。タイムラインに広告なんてありませんし、順番も時系列順ですのでご安心を。 あるいは、500文字まで使える投稿で自分を表現してみましょう。カスタム絵文字や画像、GIF、動画、音声も使用できます。 スレッドに返事したり、他の誰かの面白い投稿をブーストして共有したりすることもできます。 新しいアカウントとホットなタグを見つけて、あなた自身のネットワークを広げていきましょう
まずはコミュニティに参加して、自分のプロフィールを作成しましょう。 魅力的なユーザーを見つけたら、フォローしてタイムラインで投稿を見てみましょう。タイムラインに広告は出てきません順番も時系列順です。 そして、500文字まで使える投稿で自分を表現してみましょう。カスタム絵文字や画像、GIF、動画、音声も使用できます。 スレッドに返事したり、他の誰かの面白い投稿をブーストして共有したりすることもできます。 興味のあるアカウントとホットなハッシュタグをどんどん見つけて、あなた自身のネットワークを広げていきましょう
Mastondonはプライバシーと安全性を重視しています。 自分の投稿をフォロワー限定公開にするのか、メンションした特定のユーザーだけ共有するのか、全世界に放流するのかは、すべてあなた次第。 また、入力中の投稿について「ちょっとセンシティブな内容だな」と思ったら、閲覧注意機能で内容を伏せることで、見たくない人に配慮した投稿が作成できます。 そして、各コミュニティにはそれぞれのガイドラインと管理者・モデレーターが存在し、コミュニティメンバーの安全を守っています。強力なブロック・通報機能も、不正利用の防止をお手伝いします。
Mastondonはプライバシーと安全性を重視しています。 自分の投稿をフォロワーだけに限定公開にするのか、メンションした特定のユーザーだけ共有するのか、全世界に放流するのか、自由に決められます。 また、入力中の投稿について「ちょっとセンシティブな内容だな」と思ったら、閲覧注意機能で内容を伏せることで、見たくない人に配慮した投稿が作成できます。 そして、各コミュニティにはそれぞれのガイドラインと管理者・モデレーターが存在し、コミュニティメンバーの安全を守っています。強力なブロック・通報機能も、不正利用の防止をお手伝いします。
その他の機能:
@@ -13,4 +13,4 @@ Mastondonはプライバシーと安全性を重視しています。 自分の
• 共有どのアプリからでも、「共有」メニューを通じてMastodonへ直接投稿
• 癒しMastodonが誇る象のマスコットかわいいが、画面にお邪魔したり、しなかったり
Mastodonは公認の非営利アプリです。開発は全てユーザーの寄付から成り立っています。 広告なし、アフィリエイトなし、第三者組織による出資なし。今でも、そしてこれからもそんなアプリであり続けるために、我々は日々努力し続けています。
Mastodonは公認の非営利アプリです。開発は全てユーザーの寄付から成り立っています。 広告なし、アフィリエイトなし、第三者組織による出資なし。今でも、そしてこれからもそんなアプリであり続けるために、我々は日々努力し続けています。

View File

@@ -1,6 +1,6 @@
Mastodon d azeṭṭa anmetti asrummsan meqqren deg internet. Ideg ara yili d asmel web asuf, d azeṭṭa n yimelyan n yiseqdacen deg temɣiwin tilelliyin i izemren ad myigwent gar-asent, s wudem afrawan. Akken ibɣu yili usentel i tḥemmleḍ, tzemreḍ ad temlileḍ imdanen i d-isuffuɣen ɣef usentel-nni ɣef Mastodon!
Rnu ɣer temɣiwent syen snulfu-d amaɣnu-inek. Af, rnu ḍfer imdanen yelhan. Teɣreḍ tisuffaɣ-nsen deg yizirig n wakud war adellel. Mmel iḥulfan-ik s yimujiten, tugniwin, GIFs, tividyutin d yimeslawen udmawanen deg tsuffaɣ n 500 yisekkilen. Ttekki deg usqerdec, talseḍ asuffeɣ n tsuffaɣ n yimdanen i beṭṭu n taktiwin igerrzen. Af imiḍanen ara tḍefreḍ akked hashtags mucaεen i wakken ad tesnerniḍ azeṭṭa-inek.
Rnu ɣer temɣiwent syen snulfu-d amaɣnu-inek. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Mmel iḥulfan-ik s yimujiten, tugniwin, GIFs, tividyutin d yimeslawen udmawanen deg tsuffaɣ n 500 yisekkilen. Ttekki deg usqerdec, talseḍ asuffeɣ n tsuffaɣ n yimdanen i beṭṭu n taktiwin igerrzen. Af imiḍanen ara tḍefreḍ akked hashtags mucaεen i wakken ad tesnerniḍ azeṭṭa-inek.
Mastodon yettwabna s tikci n wazal i tbaḍnit d tɣellist. Gzem-itt deg ṛṛay ma yella tisuffaɣ-inek·inem ad ttwabḍunt akked yineḍfaren-ik·im, akked yimdanen kan i d-tbedreḍ neɣ akked yimdanen meṛṛa. Ilɣa n ugbur ad ak·akem-yeǧǧ d teffreḍ tisuffaɣ ideg yella ugbur amḥalfu neɣ yir agbur alamma d asmi ara twejdeḍ ad tkecmeḍ ɣer-sen. Yal tamɣiwent ɣur-s ilugan-ines d yiseɣyaden-is i wakken ad teḍmentaɣellist n yiεeggalen-is, akked yifecka iǧehden i usewḥel d tummla n yineqqisen mgal yir aseqdec.
@@ -13,4 +13,4 @@ Ugar n temahilin:
• Beṭṭu: Azen srid ɣer Mastodon seg kra n tferkit n beṭṭu deg kra n usnas
• Ucbiḥ: Lfal-nneɣ d ilu icebḥen aṭas, ad t-tetttwaliḍ yettban-d sya ɣer da
Mastodon d takebbanit ur nettnadi ara ɣef tedrimt, asnerni-ines yettili-d s tewsa-nni i as-tettmuddum. Ulac adellel, ur njemmeε tadrimt, ur nesεi win aɣ-d-yettakken tadrimt. Akka i nettxemmim ad nkemmel abrid-nneɣ.
Mastodon d takebbanit ur nettnadi ara ɣef tedrimt, asnerni-ines yettili-d s tewsa-nni i as-tettmuddum. Ulac adellel, ur njemmeε tadrimt, ur nesεi win aɣ-d-yettakken tadrimt. Akka i nettxemmim ad nkemmel abrid-nneɣ.

View File

@@ -1,6 +1,6 @@
마스토돈은 인터넷에서 가장 큰 분산 소셜 네트워크입니다. 단 하나의 통일된 웹사이트 대신, 수백만 명의 사용자들이, 서로 경계 없이 소통할 수 있는 독립적인 커뮤니티의 네트워크입니다. 당신이 어디에 속하든간에, 마스토돈에 열정적으로 게시물을 남기는 사람들을 만날 수 있습니다!
커뮤니티에 가입하고 프로필을 생성하세요. 매력적인 사람들을 찾아 팔로우하고 그들의 글을 광고가 없고, 시간순으로 정렬된 타임라인에서 읽으세요. 커스텀 에모지, 그림, 움짤, 동영상, 소리와 함께 500자의 글로 당신을 표현하세요. 아무에게나 글타래에 답장을 하고 게시물을 리블로그하여 멋진 것들을 공유하세요. 새로 팔로우 할 계정이나 유행 중인 해시태그를 찾아 당신의 인맥을 넓히세요.
커뮤니티에 가입하고 프로필을 생성하세요. 매력적인 사람들을 찾아 팔로우하고 그들의 게시물을 최신 순으로 정렬된 타임라인에서 광고 없이 확인하세요. 커스텀 에모지, 그림, 움짤, 동영상, 소리와 함께 500자의 글로 당신을 표현하세요. 아무에게나 글타래에 답장을 하고 게시물을 리블로그하여 멋진 것들을 공유하세요. 새로 팔로우 할 계정이나 유행 중인 해시태그를 찾아 당신의 인맥을 넓히세요.
마스토돈은 개인정보 보호와 안전에 중점을 두고 만들어졌습니다. 당신의 게시물을 팔로워들에게만 공개할지, 언급한 사람들에게만 공유할지, 아니면 전세계에 공유할 지 선택하세요. 열람주의는 민감하거나 남들에게 껄끄러울 수 있는 게시물을 마음의 준비가 된 사람들만 열람하도록 숨길 수 있도록 해줍니다. 각각의 커뮤니티는 구성원들을 안전하게 지키기 위한 각자의 규정과 중재자들을 가지고 있으며, 남용을 방지하기 위한 강력한 차단 도구와 신고 도구를 가지고 있습니다.
@@ -13,4 +13,4 @@
• 공유: 어떤 앱에서든 공유 기능으로 바로 마스토돈에 게시하세요
• 귀여움: 우리의 마스코트는 귀여운 코끼리입니다, 때때로 이들을 볼 수 있습니다
마스토돈은 등록된 상호이며 여러분들의 직접적인 기부를 통해 개발되고 있습니다. 광고도, 유료화도, 벤처 캐피탈도 없습니다, 그리고 계속 그렇게 할 생각입니다.
마스토돈은 등록된 상호이며 여러분들의 직접적인 기부를 통해 개발되고 있습니다. 광고도, 유료화도, 벤처 캐피탈도 없습니다, 그리고 계속 그렇게 할 생각입니다.

View File

@@ -0,0 +1,16 @@
Mastodon (မက်စ်စတိုဒွန်) ဟာ အင်တာနက်ပေါ်မှာ ဗဟိုထိန်းချုပ်မှုကင်းမဲ့တဲ့ အကြီးမားဆုံးသော လူမှုကွန်ရက်တစ်ခုဖြစ်ပါတယ်။ ဝက်ဘ်ဆိုဒ်တစ်ခုတည်းဖြစ်မယ့်အစား Mastodon ဟာ လွတ်လပ်တဲ့လူမှုအသိုက်အဝန်း (community) တေွက သုံးစွဲသူသန်းချီကို တစ်ယောက်နဲ့တစ်ယောက် လွယ်လွယ်ကူကူ၊ ချောချောမွေ့မွေ့နဲ့ အပြန်အလှန် ဆက်သွယ်ချိတ်ဆက်ပေးတဲ့ ကွန်ရက်တစ်ခုဖြစ်ပါတယ်။ သင်ဘာကိုပဲ စိတ်ဝင်စားနေပါစေ Mastodon ပေါ်မှာ သင်စိတ်ဝင်စားတာနဲ့ပတ်သက်ပြီး စိတ်အားထက်သန်တဲ့လူတွေနဲ့ တေွ့ဆုံနိုင်မှာဖြစ်ပါတယ်။
လူမှုအသိုက်အဝန်းတစ်ခုကိုချိတ်ဆက်ပြီး ပရိုဖိုင်းတစ်ခုဖန်တီးပါ။ ပြီးနောက် စွဲမက်ဖွယ်ကောင်းသူတေွကို ရှာဖွေဖော်လိုးလုပ်ပြီး သူတို့ရဲ့ပို့စ်တွေကို ကြော်ငြာကင်းမဲ့ပြီး အချိန်နှင့်တပြေးညီရှိတဲ့ တိုင်းမ်လိုင်းမှာ ဖတ်ရှုလိုက်ပါ။ သင့်ကိုယ်သင် စိတ်ကြိုက်အီမိုဂျီတွေ၊ ရုပ်ပုံတွေ၊ ဂစ်ဖ်တွေ၊ ဗီဒီယိုတွေ၊ အသံဖိုင်တွေသုံးပြီး အလုံးရေ ၅၀၀ ဆန့်တဲ့ ပို့စ်တွေနဲ့ ဖော်ပြနိုင်သလို စာတွဲ (thread) တွေကို ရီပလိုင်းပြန်လိုက်၊ တခြားသူတွေရဲ့ပို့စ်မိုက်မိုက်လေးတွေကို ရီဘလော့လုပ်လိုက်လည်း လုပ်နိုင်ပါသေးတယ်။ သင့်ကွန်ရက်ကိုဖြန့်ကျက်ဖို့ရာအတွက် အကောင့်အသစ်တွေနဲ့ ရေပန်းစားနေတဲ့ ဟက်ရှ်တက်တွေကို ရှာဖွေဖော်လိုးလုပ်လိုက်ပါ။
Mastodon ဟာ ကိုယ်ရေးအချက်အလက်လုံခြုံမှုနဲ့ ဘေးကင်းစိတ်ချရမှုတို့ကို အာရုံစိုက်ပြီး တည်ဆောက်ထားတာဖြစ်ပါတယ်။ သင့်ပို့စ်တွေကို ဖော်လိုဝါတွေဆီကိုပဲ မျှဝေမလား၊ ဒါမှမဟုတ် မန်းရှင်းလုပ်ထားတဲ့သူတွေကိုပဲ မျှဝေမလား၊ ဒါမှမဟုတ် တစ်ကမ္ဘာလုံးကိုမျှဝေမလားဆိုတာ ဆုံးဖြတ်နိုင်ပါတယ်။ အကြောင်းအရာသတိပေးချက်တွေက ထိလွယ်ရှလွယ်အကြောင်းအရာတွေနဲ့ လှုံ့ဆော်မှုဖြစ်စေတဲ့အကြောင်းအရာတွေ ပါဝင်တဲ့ပို့စ်တွေကို သင်ထိတွေ့ဆက်ဆံဖို့ အဆင်သင့်ဖြစ်သည်အထိ ဖျောက်ထားပေးမှာပါ။ အဖွဲ့ဝင်တွေကို လုံလုံခြုံခြုံဖြစ်စေဖို့အတွက် လူမှုအသိုက်အဝန်းတစ်ခုစီမှာ သူတို့ကိုယ်ပိုင်လမ်းညွှန်ချက်တွေနဲ့ စီမံကွပ်ကဲသူတွေရှိကြပြီး လူမှုကွန်ရက်ပေါ် အလွဲသုံးစားလုပ်မှုကို ကာကွယ်ဖို့အတွက် ခိုင်မာအားကောင်းတဲ့ ပိတ်ပင်မှုစနစ်တွေနဲ့ သတင်းပို့ကိရိယာတွေလည်း ရှိပါတယ်။
နောက်ထပ် feature များ -
• အမှောင်မုဒ် - ပို့စ်တွေကို အလင်း၊ အမှောင်နဲ့ အနက်စစ်စစ်မုဒ်တွေမှာ ဖတ်ရှုလိုက်ပါ
• စစ်တမ်းများ - ဖော်လိုဝါတွေရဲ့ အမြင်တွေကိုမေးမြန်းပြီး စစ်တမ်းကောက်ပါ
• စူးစမ်းရှာဖွေခြင်း - ရေပန်းစားနေတဲ့ ဟက်ရှ်တက်တွေနဲ့ အကောင့်တွေဟာ တစ်ချက်နှိပ်ရုံပဲရှိပါတယ်
• နိုတီများ - ဖောလိုးအသစ်တွေ၊ ရီပလိုင်းအသစ်တွေနဲ့ ရီဘလော့အသစ်တွေကို သိရှိလိုက်ပါ
• မျှဝေခြင်း - မည်သည့်အက်ပ်မျှဝေလွှာကပဲဖြစ်ဖြစ် Mastodon ဆီကို တိုက်ရိုက်ပို့စ်တင်လိုက်ပါ
• ချစ်စရာကောင်းမှု - ကျွန်တော်တို့ရဲ့လာဘ်ကောင်လေးက ချစ်ဖို့ကောင်းတဲ့ဆင်လေးဖြစ်ပြီး တစ်ခါတစ်ခါပေါ်ပေါ်လာတာကို တွေ့ရမှာပါ
Mastodon ဟာ မှတ်ပုံတင်ပြီးသား အကျိုးအမြတ်မယူတဲ့ လူမှုကွန်ရက်တစ်ခုဖြစ်ပြီး Mastodon ရဲ့ ဖွံ့ဖြိုးတိုးတက်မှုကိုလည်း သင့်ရဲ့လှူဒါန်းမှုတွေက တိုက်ရိုက်ထောက်ပံ့ပေးထားပါတယ်။ Mastodon မှာ ကြော်ငြာ၊ ပိုက်ဆံရှာဖွေတာနဲ့ အကျိုးတူရင်းနှီးငွေတွေမရှိသလို ဒီအတိုင်းပဲဆက်သွားဖို့လည်း စီစဉ်ထားပါတယ်။

View File

@@ -0,0 +1 @@
ဗဟိုထိန်းချုပ်မှုကင်းမဲ့သော လူမှုကွန်ရက်

View File

@@ -0,0 +1 @@
Mastodon

View File

@@ -1,16 +1,16 @@
Mastodon is het grootste gedecentraliseerde sociale netwerk op het internet. In plaats van één enkele website is het een netwerk van miljoenen gebruikers in onafhankelijke gemeenschappen die allemaal naadloos met elkaar kunnen communiceren. Waar je ook mee bezig bent, je kunt gepassioneerde mensen ontmoeten die erover berichten op Mastodon!
Mastodon is het grootste gedecentraliseerde sociale netwerk op het internet. In plaats van één enkele website is het een netwerk van miljoenen gebruikers in onafhankelijke gemeenschappen die allemaal naadloos met elkaar kunnen communiceren. Wat je ook leuk vindt, je kunt gepassioneerde mensen volgen die het met je willen delen op Mastodon!
Word lid van een gemeenschap en maak je profiel aan. Vind en volg fascinerende mensen en lees hun berichten in een advertentievrije, chronologische tijdlijn. Druk jezelf uit met aangepaste emoji, afbeeldingen, GIFs, videos en audio in berichten van 500 karakters. Antwoord op berichten en boost iedereens berichten om geweldige dingen te delen. Vind nieuwe accounts om te volgen en hashtags om je netwerk uit te breiden.
Meld je aan bij een community en maak je profiel aan. Vind en volg fascinerende mensen en lees hun berichten in een advertentievrije, chronologische tijdlijn. Druk jezelf uit met aangepaste emoji, afbeeldingen, GIFs, videos en audio in berichten van 500 karakters. Reageer op discussies en boost berichten van anderen om geweldige dingen te delen. Vind nieuwe accounts om te volgen en hashtags om je netwerk uit te breiden.
Mastodon is gebouwd met een focus op privacy en veiligheid. Bepaal zelf of je berichten met je volgers, alleen de mensen die je noemt, of de hele wereld worden gedeeld. Inhoudswaarschuwingen laten je berichten verbergen die gevoelig of aanmatigend materiaal bevatten, totdat je er klaar voor bent om ermee ze te bekijken. Elke gemeenschap heeft haar eigen richtlijnen en moderators om haar leden veilig te houden, en robuuste blokkerings- en rapportagetools helpen misbruik te voorkomen.
Mastodon is gebouwd met een focus op privacy en veiligheid. Bepaal zelf of je berichten met je volgers, alleen de mensen die je noemt, of de hele wereld worden gedeeld. Inhoudswaarschuwingen laten je berichten verbergen die gevoelig of aanmatigend materiaal bevatten, totdat je er klaar voor bent om ze te bekijken. Iedere community heeft zijn eigen richtlijnen en beheerders om de leden een veilige omgeving te bieden. Met goede blokkeertools en mogelijkheden om berichten te rapporteren voorkomen we misbruik.
Meer mogelijkheden:
• Donkere Modus: Berichten lezen in licht, donker of echt zwart
• Polls: Vraag volgers om hun mening en tel de stemmen
• Ontdekken: Trending hashtags en accounts zijn een tik weg
• Meldingen: Krijg een melding over nieuwe volgers, reacties en boosts
• Delen: Deel vanuit elke app direct op Mastodon
• Schattigheid: Onze mascotte is een schattige olifant, en je zult ze van tijd tot tijd zien verschijnen
• Donkere modus: berichten lezen in lichte modus, donker modus of echt zwarte modus
• Polls: vraag je volgers om hun mening en tel de stemmen
• Ontdekken: trending hashtags en accounts onder handbereik
• Meldingen: ontvang een melding bij nieuwe volgers, reacties en boosts
• Delen: deel direct op Mastodon vanuit elke app
• Superschattig: onze mascotte is een schattige olifant die af en toe in beeld komt
Mastodon is een geregistreerde non-profit en de ontwikkeling wordt direct ondersteund door jouw donaties. Er is geen reclame, geen geldelijk gewin en geen durfkapitaal en we zijn van plan het zo te houden.
Mastodon is een geregistreerde non-profit en de ontwikkeling wordt direct ondersteund door jouw donaties. Er zijn geen advertenties, geen pogingen om geld te verdienen, geen investeerders en we willen dat zo houden.

View File

@@ -1 +1 @@
Gedecentraliseerd sociaal netwerk
Decentraal sociaal netwerk

View File

@@ -0,0 +1,16 @@
Mastodon er det største desentraliserte sosiale nettverket på internett. I stedet for en nettside, er det et nettverk av millioner av brukere i uavhengige samfunn som alle kan samhandle med hverandre, sømløst. Uansett hva du er, kan du møte lidenskapelige folk som legger ut om det på Mastodon!
Bli med i et samfunn og opprett profilen din. Finn og følg fascinerende mennesker og les deres innlegg i en reklamefri, kronologisk tidslinje. Uttrykk deg selv med egendefinerte emoji, bilder, GIFs, videoer og lyd i innlegg på 500 tegn. Svar på tråder og fremhev fra alle til alle å dele gode ting. Finn nye kontoer å følge og trendende emneknagger for å utvide nettverket ditt.
Mastodon er bygget med fokus på personvern og sikkerhet. Bestem om innleggene dine er delt med dine tilhengere, bare personene du nevner, eller hele verden. Innholdsadvarsler lar deg skjule innlegg som inneholder følsomt eller utløsende materiale, inntil du er klar til å engasjere deg med dem. Hvert samfunn har egne retningslinjer og moderatorer for å holde medlemmene trygge, og å blokkere å rapporterings verktøy for å forhindre misbruk.
Flere funksjoner:
• Mørk modus: Lese innlegg i lys, mørkt eller svart modus
• Avstemminger: Be følgende om deres mening og alliert stemmene
• Utforske: Trendende emneknagger og kontoer er et trykk unna
• Varslinger: Få beskjed om nye følgere, svar og fremhevinger
• Deling: Post direkte til Mastodon fra et hvilket som helst delingsark i en app
• Nytten: Vår maskot er en eventyrlig elefant, og du vil se den poppe fra tid til annen
Mastodon er en registrert nonprofit, og utvikling støttes direkte av dine donasjoner. Det er ikke reklame, ingen investorer, og vi har tenkt å holde det på denne måten.

View File

@@ -0,0 +1 @@
Desentralisert sosialt nettverk

View File

@@ -0,0 +1 @@
Mastodon

View File

@@ -1,6 +1,6 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Join a community and create your profile. Find and and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Join a community and create your profile. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
@@ -13,4 +13,4 @@ More features:
• Sharing: Post directly to Mastodon from any share sheet in any app
• Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.

View File

@@ -1,6 +1,6 @@
Mastodon to największa zdecentralizowana sieć społecznościowa w Internecie. Zamiast jednej strony internetowej, jest to sieć milionów użytkowników w niezależnych społecznościach, które mogą ze sobą wchodzić w interakcje. Niezależnie od swoich zainteresowań, momżesz poznać interesujących ludzi piszących o nich na Mastodonie!
Dołącz do społeczności i utwórz swój profil. Poznaj i obserwuj fascynujących ludzi i czytaj ich wpisy w chronologicznym osi czasu. Wyrażaj siebie za pomocą niestandardowych emoji, obrazów, GIFów, filmów i audio w 500-znakowych wpisach. Odpowiadaj na wątki i podawaj dalej posty od każdego, aby dzielić się wspaniałymi rzeczami. Odnajduj nowe konta do obserwowania i zyskujące popularność hashtagi, by poszerzać swoją sieć.
Dołącz do społeczności i utwórz swój profil. Znaj i obserwuj fascynujących ludzi i przeczytaj ich posty w bezreklamowej, chronologicznej osi czasu. Wyrażaj siebie za pomocą niestandardowych emoji, obrazów, GIFów, filmów i audio w 500-znakowych wpisach. Odpowiadaj na wątki i podawaj dalej posty od każdego, aby dzielić się wspaniałymi rzeczami. Odnajduj nowe konta do obserwowania i zyskujące popularność hashtagi, by poszerzać swoją sieć.
Mastodon został zaprojektowany z myślą o prywatności i bezpieczeństwie. Decyduj, czy Twoje wpisy są udostępniane osobom obserwującym Cię, tylko wzmiankowanym, czy całemu światu. Ostrzeżenia dotyczące zawartości pozwalają ukrywać posty zawierające wrażliwe lub wyzywające materiały, dopóki nie będziesz gotów się z nimi pogodzić. Każda społeczność ma własne wytyczne i moderatorów, aby zapewniać swoim członkom bezpieczeństwo, a także solidne narzędzia blokowania i raportowania pomagające zapobiegać nadużyciom.
@@ -13,4 +13,4 @@ Więcej funkcji:
• Udostępnianie: Publikuj bezpośrednio na Mastodonie z menu udostępniania w dowolnej aplikacji
• Słodycz: Nasza maskotka to uroczy słoń i zobaczysz go pojawiającego się od czasu do czasu
Mastodon to zarejestrowana organizacja non-profit, a rozwój jest wspierany bezpośrednio przez darowizny. Nie ma reklam, monetyzacji, ani kapitału inwestycyjnego i planujemy, by tak pozostało.
Mastodon to zarejestrowana organizacja non-profit, a rozwój jest wspierany bezpośrednio przez darowizny. Nie ma reklam, monetyzacji, ani kapitału inwestycyjnego i planujemy, by tak pozostało.

View File

@@ -1,16 +1,16 @@
Mastodon é a maior rede social descentralizada na internet. Ao invés de ser um website, é uma rede de milhões de usuários em comunidades independentes que podem comunicar-se uma à outra, de forma transparente. Independente do que você gostar, você pode encontrar pessoas dedicadas a isso no Mastodon!
Junte-se a uma comunidade e crie o seu perfil. Encontre e siga pessoas fascinantes e leia seus posts em uma linha cronológica sem publicidade. Se expresse com emojis personalizados, imagens, GIFs, vídeos e áudio em publicações de 500 caracteres. Responda a tópicos e reblogue publicações de qualquer um para compartilhar coisas ótimas. Encontre contas novas para seguir e hashtags em alta para expandir sua rede.
Junte-se a uma comunidade e crie o seu perfil. Encontre e siga pessoas fascinantes e leia seus posts em uma linha cronológica sem anúncios. Se expresse com emojis personalizados, imagens, GIFs, vídeos e áudio em publicações de 500 caracteres. Responda a tópicos e reblogue publicações de qualquer um para compartilhar coisas ótimas. Encontre contas novas para seguir e hashtags em alta para expandir sua rede.
O Mastodon foi construído com foco em privacidade e segurança. Decida se seus posts serão compartilhados com seus seguidores, apenas com as pessoas que você menciona, ou com o mundo inteiro. Avisos de conteúdo permitem que você oculte mensagens que contenham conteúdo sensível até você estar pronto para interagir com elas. Cada comunidade tem suas próprias diretrizes e moderadores para manter seus membros seguros, e ferramentas robustas de bloqueio e denúncias ajudam a prevenir abusos.
Mais detalhes:
• Modo escuro: Leia as postagens no modo claro, escuro ou preto de verdade
• Modo escuro: Leia as publicações no modo claro, escuro ou preto verdadeiro
• Enquetes: Peça as opiniões de seus seguidores e registre os resultados
• Explorar: Hashtags e contas em destaque estão a um toque de distância
• Notificações: Seja notificado sobre novos seguidores, respostas e reblogs
• Compartilhar: Poste diretamente ao Mastodon pela página de compartilhamento de qualquer aplicativo
• Fofura: Nossa mascote é um elefante fofinho, e você vai vê-lo por aí ocasionalmente
Mastodon é uma instituição sem fins lucrativos e o desenvolvimento é suportado diretamente pelas suas doações. Não há publicidade, não há monetização, nem capital de risco, e planejamos manter-se assim.
Mastodon é uma instituição sem fins lucrativos e o desenvolvimento é suportado diretamente pelas suas doações. Não há publicidade, não há monetização, nem capital de risco, e planejamos manter-se assim.

View File

@@ -1,16 +1,16 @@
O Mastodon é a maior rede social descentralizada da Internet. Em vez de ser um único site, é uma rede de milhões de utilizadores em comunidades independentes que podem facilmente interagir uns com os outros. Independemente dos teus gostos, consegues encontrar pessoas que os partilhem no Mastodon!
Junta-te a uma comunidade e cria o teu perfil. Encontra, segue gente fascinante e lê as suas publicações numa cronologia sem anúncios. Expressa-te com emojis personalizados imagens, GIFs, vídeos e áudio em publicações com até 500 caracteres. Responde a tópicos e promove publicações de qualquer pessoa para partilhares ótimas coisas. Encontra novas contas e tendências a seguir para expandires a tua rede.
Junta-te a uma comunidade e cria o teu perfil. Encontra e segue gente fascinante, e lê as suas publicações numa cronologia sem anúncios. Expressa-te com emojis personalizados imagens, GIFs, vídeos e áudio em publicações com até 500 caracteres. Responde a tópicos e promove publicações de qualquer pessoa para partilhares ótimas coisas. Encontra novas contas e tendências a seguir para expandires a tua rede.
O Mastodon é construído com foco na privacidade e segurança. Decide se as tuas publicações são partilhadas com os teus seguidores, apenas com as pessoas mencionadas, ou com o mundo inteiro. Avisos de conteúdo permitem-te esconder publicações que contenham material sensível ou provocatório até estares pronto(a) para o veres. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
O Mastodon é construído com foco na privacidade e segurança. Decide se as tuas publicações são partilhadas com os teus seguidores, apenas com as pessoas mencionadas, ou com o mundo inteiro. Avisos de conteúdo permitem-te esconder publicações que contenham material sensível ou provocatório até estares pronto(a) para o veres. Cada comunidade tem as suas regras e moderadores que mantêm os seus membros seguros, bem como ferramentas robustas de bloqueio e denúncias que ajudam a prevenir abusos.
More features:
Mais funcionalidades:
Dark Mode: Read posts in light, dark, or true black mode
Polls: Ask followers for their opinion and tally the votes
• Explore: Trending hashtags and accounts are a tap away
• Notifications: Get notified about new follows, replies, and reblogs
Sharing: Post directly to Mastodon from any share sheet in any app
Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Modo escuro: Lê as publicações no modo claro, escuro ou preto absoluto
Sondagens: Pede aos teus seguidores a sua opinião e conta os votos
• Explorar: “hashtags” e contas em destaque estão a um toque de distância
• Notificações: Recebe notificações sobre novos seguidores, respostas e partilhas
Partilhar: Publica diretamente no Mastodon a partir de qualquer aplicação
Fofura: A nossa mascote é um elefante adorável, e vais vê-lo aparecer de vez em quando
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
A Mastodon é uma instituição sem fins lucrativos e o desenvolvimento é apoiado diretamente pelas tuas doações. Não existe publicidade, monetização nem capital de risco, e pretendemos que se mantenha assim.

View File

@@ -1,6 +1,6 @@
Mastodon este cea mai mare rețea socială descentralizată de pe internet. În loc de un singur site, este o rețea de milioane de utilizatori din comunități independente care pot interacționa cu ceilalți, fără nici o întrerupere. Indiferent în ce te afli, poți întâlni oameni pasionați care postează despre asta pe Mastodon!
Alătură-te unei comunități și creează-ți profilul. Găsește și urmărește oameni fascinanți și citește postările lor într-un calendar cronologic fără reclame. Exprimă-te cu emoji-uri personalizate, imagini, GIF-uri, videoclipuri și audio în postări de 500 de caractere. Răspunde la subiectele de discuție și impulsionează postările de la oricine pentru a împărtăși lucruri minunate. Găsește conturi noi de urmărit și haștag-uri populare pentru a-ți extinde rețeaua.
Alătură-te unei comunități și creează-ți profilul. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Exprimă-te cu emoji-uri personalizate, imagini, GIF-uri, videoclipuri și audio în postări de 500 de caractere. Răspunde la subiectele de discuție și impulsionează postările de la oricine pentru a împărtăși lucruri minunate. Găsește conturi noi de urmărit și haștag-uri populare pentru a-ți extinde rețeaua.
Mastodon a fost construit cu accent pe confidențialitate și siguranță. Decide dacă postările tale sunt partajate cu urmăritorii tăi, doar cu cei pe care îi menționezi sau cu întreaga lume. Avertismentele de conținut vă permit să ascundeți postările care conțin materiale sensibile sau declanșatoare până când sunteți gata să le implicați. Fiecare comunitate are propriile sale orientări și proprii moderatori pentru a-și menține membrii în siguranță, iar instrumentele solide de blocare și raportare contribuie la prevenirea abuzurilor.
@@ -13,4 +13,4 @@ Mai multe caracteristici:
• Distribuire: Postează direct pe Mastodon din orice foaie de partajare în orice aplicație
• Drăgălășenie: Mascota noastră este un elefant adorabil, și îi veți vedea apărând din când în când
Mastodon este o organizație non-profit înregistrată, iar dezvoltarea este sprijinită direct de donațiile tale. Nu există publicitate, monetizare și capital de risc, și intenționăm să păstrăm lucrurile astfel.
Mastodon este o organizație non-profit înregistrată, iar dezvoltarea este sprijinită direct de donațiile tale. Nu există publicitate, monetizare și capital de risc, și intenționăm să păstrăm lucrurile astfel.

View File

@@ -7,10 +7,10 @@ Mastodon создан с акцентом на конфиденциальнос
Ещё больше возможностей:
• Темы на любой вкус: читайте посты в светлом, тёмном или OLED режимах
Спрашивайте мнение подписчиков и подсчитывайте их голоса с опросами
Найдите актуальные хэштеги, интересные посты и профили во вкладке «Обзор»
Будьте в курсе происходящего с уведомлениями о новых подписчиках, ответах и продвижениях
Опросы: спрашивайте мнение подписчиков и подсчитывайте их голоса
Обзор: в одно касание найдите актуальные хэштеги, посты и профили
Уведомления: узнавайте о новых подписках, ответах и продвижениях
• Делитесь в Mastodon содержимым из любого приложения
Умиляйтесь с нашим талисманом, восхитительным слонёнком, которого можно встретить и тут и там
Милота: Наш талисман является восхитительным слоном, и вы будете видеть его время от времени
Mastodon является зарегистрированной некоммерческой организацией, его разработка поддерживается непосредственно вашими пожертвованиями. У нас нет рекламы, монетизации и венчурного капитала, и мы не планируем это менять.
Mastodon является зарегистрированной некоммерческой организацией, его разработка поддерживается непосредственно вашими пожертвованиями. У нас нет рекламы, монетизации и венчурного капитала, и мы не планируем это менять.

View File

@@ -1 +1 @@
Распределённая социальная сеть
Децентрализованная социальная сеть

View File

@@ -1,6 +1,6 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Join a community and create your profile. Find and and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Join a community and create your profile. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
@@ -13,4 +13,4 @@ More features:
• Sharing: Post directly to Mastodon from any share sheet in any app
• Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.

View File

@@ -13,4 +13,4 @@ Dodatne funkcionalnosti:
• Skupna raba: objavljajte neposredno v Mastodon s poljubne preglednice v skupni rabi;
• Srčkano: naša maskota je ljubek slon in videli boste, kako se sem ter tja pojavi.
Mastodon je registrirana neprofitna organizacija, razvoj pa podpirajo neposredno vaše donacije. Je brez oglaševanja, monetizacije in brez rizičnega kapitala; nameravamo ga takšnega tudi obdržati.
Mastodon je registrirana neprofitna organizacija, razvoj pa podpirajo neposredno vaše donacije. Je brez oglaševanja, monetizacije in brez rizičnega kapitala; nameravamo ga takšnega tudi obdržati.

View File

@@ -1,6 +1,6 @@
Mastodon är det största decentraliserade sociala nätverket på internet. I stället för en enda webbplats är det ett nätverk av miljontals användare på oberoende servrar som alla kan interagera med varandra, sömlöst. Oavsett vad du är intresserad av kan du träffa passionerade personer som diskuterar ämnet på Mastodon!
Gå med på en server och skapa din profil. Hitta och följ fascinerande människor och läsa deras inlägg i en annonsfri, kronologisk tidslinje. Uttryck dig med anpassade emoji, bilder, GIF:ar, videor och ljud i 500-teckensinlägg. Svara på trådar och boostar från vem som helst för att dela bra saker. Hitta nya konton att följa och trendande hashtaggar för att utöka ditt nätverk.
Gå med på en server och skapa din profil. Hitta och följ fascinerande människor och läs deras inlägg i en annonsfri, kronologisk tidslinje. Uttryck dig med anpassade emoji, bilder, GIF:ar, videor och ljud i 500-teckensinlägg. Svara på trådar och boostar från vem som helst för att dela bra saker. Hitta nya konton att följa och trendande hashtaggar för att utöka ditt nätverk.
Mastodon är byggt med fokus på integritet och trygghet. Bestäm om dina inlägg delas med dina följare, bara personer du omnämner, eller hela världen. Innehållsvarningar låter dig dölja inlägg som innehåller känsligt eller triggande material tills du är redo att interagera med dem. Varje server har sina egna riktlinjer och moderatorer för att hålla sina medlemmar trygga, och robusta blockerings- och rapporteringsverktyg för att förhindra missbruk.
@@ -13,4 +13,4 @@ Fler funktioner:
• Delning: Posta direkt till Mastodon från delningsbladet i alla appar
• Gullighet: Vår maskot är en bedårande elefant, och du kommer att se dem dyka upp då och då
Mastodon är en registrerad ideell förening och utvecklingen stöds direkt av dina donationer. Det finns ingen reklam, ingen monetarisering, och inget riskkapital, och vi planerar att behålla det på det sättet.
Mastodon är en registrerad ideell förening och utvecklingen stöds direkt av dina donationer. Det finns ingen reklam, ingen monetarisering, och inget riskkapital, och vi planerar att behålla det på det sättet.

View File

@@ -1,6 +1,6 @@
Mastodon เป็นเครือข่ายสังคมแบบกระจายศูนย์ที่ใหญ่ที่สุดบนอินเทอร์เน็ต ซึ่งไม่ได้เป็นเว็บไซต์เดียว แต่เป็นเครือข่ายของผู้ใช้หลายล้านคนในชุมชนอิสระที่ทุกคนสามารถโต้ตอบซึ่งกันและกันได้แบบไร้รอยต่อ ไม่ว่าคุณจะชอบอะไร คุณก็พบคนที่ชื่นชอบเหมือนกันโพสต์เกี่ยวกับสิ่งที่คุณชอบได้บน Mastodon! ซึ่งไม่ได้เป็นเว็บไซต์เดียว แต่เป็นเครือข่ายของผู้ใช้หลายล้านคนในชุมชนอิสระที่ทุกคนสามารถโต้ตอบซึ่งกันและกันได้แบบไร้รอยต่อ ไม่ว่าคุณจะชอบอะไร คุณก็พบคนที่ชื่นชอบเหมือนกันโพสต์เกี่ยวกับสิ่งที่คุณชอบได้บน Mastodon!
เข้าร่วมชุมชนและสร้างโปรไฟล์ ค้นหาและติดตามผู้คนที่น่าสนใจและอ่านโพสต์ของเขาในไทม์ไลน์ที่ไร้โฆษณาและเรียงตามลำดับเวลาล้วน ๆ แสดงความรู้สึกของตัวคุณเองด้วยอีโมจิที่กำหนดเอง รูปภาพ GIF วิดีโอ และเสียงในโพสต์ 500 ตัวอักษร ตอบกลับและดันโพสต์จากคนอื่น ๆ เพื่อแชร์สิ่งดี ๆ และค้นหาบัญชีใหม่ ๆ ที่จะติดตามและแฮชแท็กที่เป็นที่นิยมเพื่อขยายเครือข่ายของคุณ
เข้าร่วมชุมชนและสร้างโปรไฟล์ ค้นหาและติดตามผู้คนที่น่าสนใจและอ่านโพสต์ของเขาในเส้นเวลาที่ไม่มีโฆษณาและเรียงตามลำดับเวลา แสดงความรู้สึกของตัวคุณเองด้วยอีโมจิที่กำหนดเอง รูปภาพ GIF วิดีโอ และเสียงในโพสต์ 500 ตัวอักษร ตอบกลับและดันโพสต์จากคนอื่น ๆ เพื่อแชร์สิ่งดี ๆ และค้นหาบัญชีใหม่ ๆ ที่จะติดตามและแฮชแท็กที่เป็นที่นิยมเพื่อขยายเครือข่ายของคุณ
Mastodon สร้างขึ้นโดยเน้นความเป็นส่วนตัวและความปลอดภัยเป็นสำคัญ คุณสามารถตัดสินใจได้ว่าโพสต์ของคุณจะถูกแชร์กับผู้ติดตามของคุณ คนที่คุณกล่าวถึง หรือคนทั้งโลกก็ได้ ฟังก์ชั่นคำเตือนเนื้อหาช่วยให้คุณซ่อนโพสต์ที่มีเนื้อหาที่ละเอียดอ่อนจนกว่าคุณจะพร้อมเห็นเนื้อหานั้น แต่ละชุมชนจะมีหลักเกณฑ์และผู้ควบคุมเป็นของตนเองเพื่อรักษาความปลอดภัยของสมาชิก รวมถึงเครื่องมือการปิดกั้นและรายงานที่มีประสิทธิภาพเพื่อช่วยป้องกันการกระทำผิด
@@ -13,4 +13,4 @@ Mastodon สร้างขึ้นโดยเน้นความเป็
• การแชร์: โพสต์ลง Mastodon ได้โดยตรงจากแอปอื่น ๆ ที่อยู่ในเครื่อง
• ความน่ารัก: มาสคอตของเราเป็นช้างน่ารัก และคุณจะเห็นมันโผล่ออกมาเป็นระยะ ๆ
Mastodon เป็นองค์กรไม่แสวงหาผลกำไรที่จดทะเบียนแล้ว และการพัฒนาได้รับการสนับสนุนจากเงินบริจาคของคุณโดยตรง ดังนั้นจึงไม่มีโฆษณา ไม่มีการทำกำไร และไม่มีการร่วมลงทุน และเรามีแผนจะทำให้เป็นอย่างนี้ต่อไป ดังนั้นจึงไม่มีโฆษณา ไม่มีการทำกำไร และไม่มีการร่วมลงทุน และเรามีแผนจะทำให้เป็นอย่างนี้ต่อไป
Mastodon เป็นองค์กรไม่แสวงหาผลกำไรที่จดทะเบียนแล้ว และการพัฒนาได้รับการสนับสนุนจากเงินบริจาคของคุณโดยตรง ดังนั้นจึงไม่มีโฆษณา ไม่มีการทำกำไร และไม่มีการร่วมลงทุน และเรามีแผนจะทำให้เป็นอย่างนี้ต่อไป ดังนั้นจึงไม่มีโฆษณา ไม่มีการทำกำไร และไม่มีการร่วมลงทุน และเรามีแผนจะทำให้เป็นอย่างนี้ต่อไป

View File

@@ -1,6 +1,6 @@
Mastodon, internetteki merkezi olmayan en büyük sosyal ağdır. Tek bir web siteye bağlı kalmaksızın, milyonlarca kullanıcının bağımsız olarak birbiri ile kolayca etkileşebileceği bir ağdır. Hangi konuyla ilgili olduğun önemli değil, Mastodon'da onunla ilgili gönderi paylaşan tutkulu insanlarla tanışabilirsin!
Bir topluluğa katıl ve profilini oluştur. Olağanüstü kişileri bul ve takip et, gönderilerini kronolojik ve reklamsız sunan bir akışta oku. Gönderilerinde 500 karakter sınırlamasıyla kendini emojiler, görseller, GIFler, videolar ve sesler ile ifade et. Harika içerikler paylaşmak için başlıklara yanıt yaz, insanların gönderilerini yeniden paylaş. Ağınızı genişletmek için takip edilecek yeni hesaplar ve hashtagler bul.
Bir topluluğa katıl ve profilini oluştur. Olağanüstü kişileri bul ve takip et; gönderilerini reklamsız ve kronolojik bir akışta oku. Gönderilerinde 500 karakter sınırlamasıyla kendini emojiler, görseller, GIFler, videolar ve sesler ile ifade et. Harika içerikler paylaşmak için başlıklara yanıt yaz, insanların gönderilerini yeniden paylaş. Ağınızı genişletmek için takip edilecek yeni hesaplar ve hashtagler bul.
Mastodon gizlilik ve güvenlik odaklı yapılmıştır. Her postunuz için takipçilerinizle mi, bahsettiğiniz kişilerle mi ya da tüm dünyayla mı paylaşılacağına karar verin. Gönderi uyarıları, hassas ve tetikleyici olabilecek içerikleri kişi görmeyi hazır olana kadar gizler. Her topluluk, üyelerini güvende tutmak için kendi kurallarına ve moderatörlerine; istismarı önlemek için de güçlü engelleme ve bildirme araçlarına sahiptir.
@@ -13,4 +13,4 @@ Diğer özellikler:
• Paylaşım: Doğrudan Mastodon'a herhangi bir tipte gönderi paylaş
• Sevimlilik: Maskotumuz şirin bir fil ve onu uygulamada zaman zaman göreceksin
Mastodon kar amacı gütmeyen bir kuruluştur ve geliştirilmesi doğrudan bağışlarınızla sağlanmaktadır. Reklam, para kazanma amacı, risk sermayesi yoktur ve bunu böyle tutmayı planlıyoruz.
Mastodon kar amacı gütmeyen bir kuruluştur ve geliştirilmesi doğrudan bağışlarınızla sağlanmaktadır. Reklam, para kazanma amacı, risk sermayesi yoktur ve bunu böyle tutmayı planlıyoruz.

View File

@@ -1,8 +1,8 @@
Mastodon — найбільша децентралізована соціальна мережа в інтернеті. Замість одного сайту це мережа мільйонів користувачів у незалежних спільнотах, які можуть взаємодіяти один з одним. Незалежно від того, чим ви займаєтеся, ви можете зустріти захоплених людей, які пишуть про це на Mastodon!
Приєднуйтесь до спільноти і створіть свій профіль. Знайдіть і підпишіться на цікавих людей і читайте пости у вільний від реклами стрічці. Виразіть себе за допомогою користувацьких емоджі, зображень, GIF, відео й аудіо з 500-символьними постами. Відповідайте на теми й робіть репости постів від будь-кого, щоб ділитися з ними гарними матеріалами. Знаходьте нові облікові записи, щоб підписатися і популярні хештеги для розширення вашої мережі.
Приєднуйтесь до спільноти і створіть свій профіль. Знайдіть і підпишіться на цікавих людей і читайте пости у вільний від реклами стрічці. Виразіть себе за допомогою користувацьких емоджі, зображень, GIF, відео й аудіо з 500-символьними постами. Відповідайте на теми й робіть репости постів від будь-кого, щоб ділитися гарними матеріалами. Знаходьте нові облікові записи, щоб підписатися і популярні хештеги для розширення вашої мережі.
Mastodon будується з акцентом на конфіденційність та безпеці. Вирішіть, чи будуть ваші пости тільки для підписників, або ті люди, з яких ви згадали, чи цілий світ. Попередження щодо вмісту дозволяють приховати публікації, що містять конфіденційний або провокаційний матеріал, доки ви не будете готові до нього. Кожна спільнота має свої правила і модераторів, щоб залишити учасників в безпеці, а також надійне блокування та інструменти для скарг, щоб запобігти зловживання.
Mastodon будується з акцентом на конфіденційність та безпеці. Вирішіть, чи будуть ваші пости тільки для підписників, або для людей, яких ви згадали, чи для цілого світу. Попередження щодо вмісту дозволяють приховати публікації, що містять конфіденційний або провокаційний матеріал, доки ви не будете готові до нього. Кожна спільнота має свої правила і модераторів, щоб залишити учасників в безпеці, а також надійне блокування та інструменти для скарг, щоб запобігти зловживання.
Більше можливостей:
@@ -13,4 +13,4 @@ Mastodon будується з акцентом на конфіденційні
Діліться: Публікуйте безпосередньо в Mastodon з будь-якого меню "поділитися" в будь-якому додатку
• Привабливість: Нашим талісманом є чарівний слон, і ви побачите, як він з'являється час від часу
Mastodon є зареєстрованою некомерційною організацією і розробка підтримується безпосередньо вашими пожертвуваннями. Тут немає реклами, монетизації та венчурного капіталу, і плануємо так тримати.
Mastodon є зареєстрованою некомерційною організацією і розробка підтримується безпосередньо вашими пожертвуваннями. Тут немає реклами, монетизації та венчурного капіталу, і плануємо так тримати.

View File

@@ -0,0 +1,16 @@
Mastodon is the largest decentralized social network on the internet. Instead of a single website, its a network of millions of users in independent communities that can all interact with one another, seamlessly. No matter what youre into, you can meet passionate people posting about it on Mastodon!
Join a community and create your profile. Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. Express yourself with custom emoji, images, GIFs, videos, and audio in 500-character posts. Reply to threads and reblog posts from anyone to share great stuff. Find new accounts to follow and trending hashtags to expand your network.
Mastodon is built with a focus on privacy and safety. Decide whether your posts are shared with your followers, just the people you mention, or the whole world. Content warnings let you hide posts containing sensitive or triggering material until you're ready to engage with them. Each community has its own guidelines and moderators to keep its members safe, and robust blocking and reporting tools help prevent abuse.
More features:
• Dark Mode: Read posts in light, dark, or true black mode
• Polls: Ask followers for their opinion and tally the votes
• Explore: Trending hashtags and accounts are a tap away
• Notifications: Get notified about new follows, replies, and reblogs
• Sharing: Post directly to Mastodon from any share sheet in any app
• Cuteness: Our mascot is an adorable elephant, and you'll see them pop up from time to time
Mastodon is a registered nonprofit and development is supported directly by your donations. Theres no advertising, no monetization, and no venture capital, and we plan to keep it that way.

View File

@@ -0,0 +1 @@
Decentralized social network

View File

@@ -0,0 +1 @@
Mastodon

View File

@@ -13,4 +13,4 @@ Tính năng khác:
• Chia sẻ: Đăng trực tiếp lên Mastodon từ bất kỳ ứng dụng nào
• Đáng yêu: Linh vật của chúng tôi là một chú voi ma mút và bạn sẽ thấy anh ấy thỉnh thoảng xuất hiện
Mastodon là một tổ chức phi lợi nhuận đã đăng ký và được hỗ trợ trực tiếp bởi các khoản đóng góp của bạn. Không có quảng cáo, không kiếm tiền và không có vốn đầu tư mạo hiểm và chúng tôi dự định sẽ giữ nguyên như vậy.
Mastodon là một tổ chức phi lợi nhuận đã đăng ký và được hỗ trợ trực tiếp bởi các khoản đóng góp của bạn. Không có quảng cáo, không kiếm tiền và không có vốn đầu tư mạo hiểm và chúng tôi dự định sẽ giữ nguyên như vậy.

View File

@@ -1 +1 @@
Mạng xã hội liên hợp
Mạng xã hội phi tập trung

View File

@@ -1,6 +1,6 @@
Mastodon 是互联网上最大的去中心化社交网络。 它不是一个网站,而是由独立社区节点及其数以百万计的用户组成的网络,所有这些用户都能够无缝地相互交流。 无论你进入哪一个节点,你都可以与所有在 Mastodon 的人之间进行交流。 它不是一个网站,而是由独立社区节点及其数以百万计的用户组成的网络,所有这些用户都能够无缝地相互交流。 无论你进入哪一个节点,你都可以与所有在 Mastodon 的人之间进行交流。
加入一个社区节点并创建你的账户。 寻找并关注感兴趣的同好,无广告地浏览他们的时间线。 用自定义表情、图像、GIF、视频和音频在 500 个字符的帖子里写下你的想法。 回复及转发其他人的帖子来共同分享美好的事物。 寻找新的账户以及热门的话题来拓展你的网络。
加入一个社区节点并创建你的账户。 Find and follow fascinating folks and read their posts in an ad-free, chronological timeline. 用自定义表情、图像、GIF、视频和音频在 500 个字符的帖子里写下你的想法。 回复及转发其他人的帖子来共同分享美好的事物。 寻找新的账户以及热门的话题来拓展你的网络。
Mastodon 以隐私和安全为首要目标。 自由选择你的帖子是分享给关注者,或是你提到的人,亦或是整个世界。 内容警告允许让你隐藏可能剧透的内容,让其他人在交互之前做好充分准备。 每个社区都有自己的规则和管理员,让其用户保持安全。通过强有力的屏蔽和举报工具防止滥用。
@@ -13,4 +13,4 @@ Mastodon 以隐私和安全为首要目标。 自由选择你的帖子是分享
• 分享:从其他应用中的分享菜单中直接发布到 Mastodon
• 吉祥物:你会不时地看到我们可爱的长毛象
Mastodon 是一个注册的非营利开发项目,直接由您的捐赠支持。 没有广告,没有商业化,也没有风险资本,我们计划保持这种方式。 没有广告,没有商业化,也没有风险资本,我们计划保持这种方式。
Mastodon 是一个注册的非营利开发项目,直接由您的捐赠支持。 没有广告,没有商业化,也没有风险资本,我们计划保持这种方式。 没有广告,没有商业化,也没有风险资本,我们计划保持这种方式。

View File

@@ -1,4 +1,4 @@
Mastodon 是網際網路上最大的去中心化社網路。 它是一個由能無縫互動的獨立社群中,數百萬使用者組成的網路,而非單一網站。 無論您對什麼事情感興趣,您都能在 Mastodon 上遇到充滿熱情的人們討論該話題。 它是一個由能無縫互動的獨立社群中,數百萬使用者組成的網路,而非單一網站。 Mastodon 以隱私與安全為要。 決定您的嘟文要與您的跟隨者分享、只與您提及的人們分享,又或是與全世界分享。 內容警告可讓您隱藏包含敏感或可能觸發強烈情緒反應的嘟文,直到您準備好與它們進行互動。 每個社群都有它們自己的指導方針與管理原來確保其成員安全,強大的封鎖與回報工具有助於防止濫用。
Mastodon 是網際網路上最大的去中心化社網路。 它是一個由能無縫互動的獨立社群中,數百萬使用者組成的網路,而非單一網站。 無論您對什麼事情感興趣,您都能在 Mastodon 上遇到充滿熱情的人們討論該話題。
加入社群並建立您的個人檔案。 尋找並跟隨迷人的朋友們,並在無廣告、按時間順序排列的時間軸上閱讀他們的嘟文。 在 500 個字元的嘟文中使用自訂表情符號、GIF、視訊與音訊來表達您自己。 回覆任何人的話題與轉發貼文以分享精彩內容。 尋找要跟隨的新帳號與熱門主題標籤來拓展您的網路。
@@ -13,4 +13,4 @@ Mastodon 以隱私與安全為要。 決定您的嘟文要與您的跟隨者分
• 分享:從任何應用程式中的分享表中直接發表嘟文到 Mastodon 中
• 可愛:我們的吉祥物是一隻可愛的大象,您會不時看到牠出現
Mastodon 是一家註冊的非營利組織,您的捐款會直接支援開發工作。 沒有廣告、沒有貨幣化、沒有風險投資,我們計畫維持這種狀態。 沒有廣告、沒有貨幣化、沒有風險投資,我們計畫維持這種狀態。
Mastodon 是一家註冊的非營利組織,您的捐款會直接支援開發工作。 沒有廣告、沒有貨幣化、沒有風險投資,我們計畫維持這種狀態。 沒有廣告、沒有貨幣化、沒有風險投資,我們計畫維持這種狀態。

View File

@@ -16,4 +16,4 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
android.enableJetifier=false

View File

@@ -9,10 +9,10 @@ android {
applicationId "org.joinmastodon.android"
minSdk 23
targetSdk 33
versionCode 47
versionName "1.1.5"
versionCode 54
versionName "1.2.3"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resConfigs "ar-rSA", "be-rBY", "bn-rBD", "bs-rBA", "ca-rES", "cs-rCZ", "de-rDE", "el-rGR", "es-rES", "eu-rES", "fi-rFI", "fil-rPH", "fr-rFR", "ga-rIE", "gd-rGB", "gl-rES", "hi-rIN", "hr-rHR", "hu-rHU", "hy-rAM", "in-rID", "is-rIS", "it-rIT", "iw-rIL", "ja-rJP", "kab", "ko-rKR", "nl-rNL", "oc-rFR", "pl-rPL", "pt-rBR", "pt-rPT", "ro-rRO", "ru-rRU", "si-rLK", "sl-rSI", "sv-rSE", "th-rTH", "tr-rTR", "uk-rUA", "vi-rVN", "zh-rCN", "zh-rTW"
resConfigs "ar-rSA", "be-rBY", "bn-rBD", "bs-rBA", "ca-rES", "cs-rCZ", "da-rDK", "de-rDE", "el-rGR", "es-rES", "eu-rES", "fa-rIR", "fi-rFI", "fil-rPH", "fr-rFR", "ga-rIE", "gd-rGB", "gl-rES", "hi-rIN", "hr-rHR", "hu-rHU", "hy-rAM", "ig-rNG", "in-rID", "is-rIS", "it-rIT", "iw-rIL", "ja-rJP", "kab", "ko-rKR", "my-rMM", "nl-rNL", "no-rNO", "oc-rFR", "pl-rPL", "pt-rBR", "pt-rPT", "ro-rRO", "ru-rRU", "si-rLK", "sl-rSI", "sv-rSE", "th-rTH", "tr-rTR", "uk-rUA", "ur-rIN", "vi-rVN", "zh-rCN", "zh-rTW"
}
buildTypes {

View File

@@ -11,6 +11,16 @@
<permission android:name="${applicationId}.permission.C2D_MESSAGE" android:protectionLevel="signature"/>
<queries>
<intent>
<action android:name="android.intent.action.PROCESS_TEXT" />
<data android:mimeType="text/plain" />
</intent>
<intent>
<action android:name="android.intent.action.TRANSLATE" />
</intent>
</queries>
<application
android:name=".MastodonApp"
android:allowBackup="true"

View File

@@ -29,20 +29,20 @@ import org.joinmastodon.android.model.Poll;
import org.joinmastodon.android.model.Relationship;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.BetterItemAnimator;
import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.TileGridLayoutManager;
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ImageStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.MediaGridStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.PollFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.PollOptionStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
import org.joinmastodon.android.ui.photoviewer.PhotoViewer;
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
import org.joinmastodon.android.ui.utils.MediaAttachmentViewController;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout;
import org.joinmastodon.android.ui.views.MediaGridLayout;
import org.joinmastodon.android.utils.TypedObjectPool;
import java.util.ArrayList;
import java.util.Collections;
@@ -53,7 +53,6 @@ import java.util.stream.Collectors;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
@@ -73,6 +72,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
protected HashMap<String, Account> knownAccounts=new HashMap<>();
protected HashMap<String, Relationship> relationships=new HashMap<>();
protected Rect tmpRect=new Rect();
protected TypedObjectPool<MediaGridStatusDisplayItem.GridItemType, MediaAttachmentViewController> attachmentViewsPool=new TypedObjectPool<>(this::makeNewMediaAttachmentView);
public BaseStatusListFragment(){
super(20);
@@ -171,21 +171,21 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
@Override
public void openPhotoViewer(String parentID, Status _status, int attachmentIndex){
final Status status=_status.reblog!=null ? _status.reblog : _status;
public void openPhotoViewer(String parentID, Status _status, int attachmentIndex, MediaGridStatusDisplayItem.Holder gridHolder){
final Status status=_status.getContentStatus();
currentPhotoViewer=new PhotoViewer(getActivity(), status.mediaAttachments, attachmentIndex, new PhotoViewer.Listener(){
private ImageStatusDisplayItem.Holder<?> transitioningHolder;
private MediaAttachmentViewController transitioningHolder;
@Override
public void setPhotoViewVisibility(int index, boolean visible){
ImageStatusDisplayItem.Holder<?> holder=findPhotoViewHolder(index);
MediaAttachmentViewController holder=findPhotoViewHolder(index);
if(holder!=null)
holder.photo.setAlpha(visible ? 1f : 0f);
}
@Override
public boolean startPhotoViewTransition(int index, @NonNull Rect outRect, @NonNull int[] outCornerRadius){
ImageStatusDisplayItem.Holder<?> holder=findPhotoViewHolder(index);
MediaAttachmentViewController holder=findPhotoViewHolder(index);
if(holder!=null){
transitioningHolder=holder;
View view=transitioningHolder.photo;
@@ -193,7 +193,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
view.getLocationOnScreen(pos);
outRect.set(pos[0], pos[1], pos[0]+view.getWidth(), pos[1]+view.getHeight());
list.setClipChildren(false);
transitioningHolder.itemView.setElevation(1f);
gridHolder.setClipChildren(false);
transitioningHolder.view.setElevation(1f);
return true;
}
return false;
@@ -220,15 +221,16 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
view.setTranslationY(0f);
view.setScaleX(1f);
view.setScaleY(1f);
transitioningHolder.itemView.setElevation(0f);
transitioningHolder.view.setElevation(0f);
if(list!=null)
list.setClipChildren(true);
gridHolder.setClipChildren(true);
transitioningHolder=null;
}
@Override
public Drawable getPhotoViewCurrentDrawable(int index){
ImageStatusDisplayItem.Holder<?> holder=findPhotoViewHolder(index);
MediaAttachmentViewController holder=findPhotoViewHolder(index);
if(holder!=null)
return holder.photo.getDrawable();
return null;
@@ -244,23 +246,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
requestPermissions(permissions, PhotoViewer.PERMISSION_REQUEST);
}
private ImageStatusDisplayItem.Holder<?> findPhotoViewHolder(int index){
if(list==null)
return null;
int offset=0;
for(StatusDisplayItem item:displayItems){
if(item.parentID.equals(parentID)){
if(item instanceof ImageStatusDisplayItem){
RecyclerView.ViewHolder holder=list.findViewHolderForAdapterPosition(getMainAdapterOffset()+offset+index);
if(holder instanceof ImageStatusDisplayItem.Holder<?> imgHolder){
return imgHolder;
}
return null;
}
}
offset++;
}
return null;
private MediaAttachmentViewController findPhotoViewHolder(int index){
return gridHolder.getViewController(index);
}
});
}
@@ -310,31 +297,6 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
updateToolbar();
}
@Override
protected RecyclerView.LayoutManager onCreateLayoutManager(){
GridLayoutManager lm=new TileGridLayoutManager(getActivity(), 1000);
lm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup(){
@Override
public int getSpanSize(int position){
position-=getMainAdapterOffset();
if(position>=0 && position<displayItems.size()){
StatusDisplayItem item=displayItems.get(position);
if(item instanceof ImageStatusDisplayItem imgItem){
PhotoLayoutHelper.TiledLayoutResult layout=imgItem.tiledLayout;
PhotoLayoutHelper.TiledLayoutResult.Tile tile=imgItem.thisTile;
int spans=0;
for(int i=0;i<tile.colSpan;i++){
spans+=layout.columnSizes[tile.startCol+i];
}
return spans;
}
}
return 1000;
}
});
return lm;
}
@Override
public void onConfigurationChanged(Configuration newConfig){
super.onConfigurationChanged(newConfig);
@@ -448,7 +410,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
revealSpoiler(status, holder.getItemID());
}
public void onRevealSpoilerClick(ImageStatusDisplayItem.Holder<?> holder){
public void onRevealSpoilerClick(MediaGridStatusDisplayItem.Holder holder){
Status status=holder.getItem().status;
revealSpoiler(status, holder.getItemID());
}
@@ -479,13 +441,14 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
protected void updateImagesSpoilerState(Status status, String itemID){
ArrayList<Integer> updatedPositions=new ArrayList<>();
for(ImageStatusDisplayItem.Holder photo:(List<ImageStatusDisplayItem.Holder>)findAllHoldersOfType(itemID, ImageStatusDisplayItem.Holder.class)){
photo.setRevealed(status.spoilerRevealed);
updatedPositions.add(photo.getAbsoluteAdapterPosition()-getMainAdapterOffset());
MediaGridStatusDisplayItem.Holder mediaGrid=findHolderOfType(itemID, MediaGridStatusDisplayItem.Holder.class);
if(mediaGrid!=null){
mediaGrid.setRevealed(status.spoilerRevealed);
updatedPositions.add(mediaGrid.getAbsoluteAdapterPosition()-getMainAdapterOffset());
}
int i=0;
for(StatusDisplayItem item:displayItems){
if(itemID.equals(item.parentID) && item instanceof ImageStatusDisplayItem && !updatedPositions.contains(i)){
if(itemID.equals(item.parentID) && item instanceof MediaGridStatusDisplayItem && !updatedPositions.contains(i)){
adapter.notifyItemChanged(i);
}
i++;
@@ -609,6 +572,14 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
currentPhotoViewer.onPause();
}
private MediaAttachmentViewController makeNewMediaAttachmentView(MediaGridStatusDisplayItem.GridItemType type){
return new MediaAttachmentViewController(getActivity(), type);
}
public TypedObjectPool<MediaGridStatusDisplayItem.GridItemType, MediaAttachmentViewController> getAttachmentViewsPool(){
return attachmentViewsPool;
}
protected class DisplayItemsAdapter extends UsableRecyclerView.Adapter<BindableViewHolder<StatusDisplayItem>> implements ImageLoaderRecyclerAdapter{
public DisplayItemsAdapter(){
@@ -646,16 +617,6 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
public ImageLoaderRequest getImageRequest(int position, int image){
return displayItems.get(position).getImageRequest(image);
}
// @Override
// public void onViewDetachedFromWindow(@NonNull BindableViewHolder<StatusDisplayItem> holder){
// if(holder instanceof ImageLoaderViewHolder){
// int count=holder.getItem().getImageCount();
// for(int i=0;i<count;i++){
// ((ImageLoaderViewHolder) holder).clearImage(i);
// }
// }
// }
}
private class StatusListItemDecoration extends RecyclerView.ItemDecoration{
@@ -689,25 +650,21 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
for(int i=0;i<parent.getChildCount();i++){
View child=parent.getChildAt(i);
RecyclerView.ViewHolder holder=parent.getChildViewHolder(child);
if(holder instanceof ImageStatusDisplayItem.Holder<?> imgHolder){
if(holder instanceof MediaGridStatusDisplayItem.Holder imgHolder){
if(!imgHolder.getItem().status.spoilerRevealed && TextUtils.isEmpty(imgHolder.getItem().status.spoilerText)){
hiddenMediaPaint.setColor(0x80000000);
PhotoLayoutHelper.TiledLayoutResult.Tile tile=imgHolder.getItem().thisTile;
float hGap=tile.startCol>0 ? V.dp(1) : 0;
float vGap=tile.startRow>0 ? V.dp(1) : 0;
c.drawRect(child.getX()-hGap, child.getY()-vGap, child.getX()+child.getWidth(), child.getY()+child.getHeight(), hiddenMediaPaint);
c.drawRect(child.getX(), child.getY(), child.getX()+child.getWidth(), child.getY()+child.getHeight(), hiddenMediaPaint);
}
}
}
for(int i=0;i<parent.getChildCount();i++){
View child=parent.getChildAt(i);
RecyclerView.ViewHolder holder=parent.getChildViewHolder(child);
if(holder instanceof ImageStatusDisplayItem.Holder<?> imgHolder){
if(holder instanceof MediaGridStatusDisplayItem.Holder imgHolder){
if(!imgHolder.getItem().status.spoilerRevealed){
PhotoLayoutHelper.TiledLayoutResult.Tile tile=imgHolder.getItem().thisTile;
if(tile.startCol==0 && tile.startRow==0 && TextUtils.isEmpty(imgHolder.getItem().status.spoilerText)){
if(TextUtils.isEmpty(imgHolder.getItem().status.spoilerText)){
int listWidth=getListWidthForMediaLayout();
int width=Math.min(listWidth, V.dp(ImageAttachmentFrameLayout.MAX_WIDTH));
int width=Math.min(listWidth, V.dp(MediaGridLayout.MAX_WIDTH));
if(currentMediaHiddenLayoutsWidth!=width)
rebuildMediaHiddenLayouts(width-V.dp(32));
c.save();
@@ -732,47 +689,6 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
}
}
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state){
RecyclerView.ViewHolder holder=parent.getChildViewHolder(view);
if(holder instanceof ImageStatusDisplayItem.Holder){
int listWidth=getListWidthForMediaLayout();
int width=Math.min(listWidth, V.dp(ImageAttachmentFrameLayout.MAX_WIDTH));
PhotoLayoutHelper.TiledLayoutResult layout=((ImageStatusDisplayItem.Holder<?>) holder).getItem().tiledLayout;
PhotoLayoutHelper.TiledLayoutResult.Tile tile=((ImageStatusDisplayItem.Holder<?>) holder).getItem().thisTile;
if(tile.startCol+tile.colSpan<layout.columnSizes.length){
outRect.right=V.dp(1);
}
if(tile.startRow+tile.rowSpan<layout.rowSizes.length){
outRect.bottom=V.dp(1);
}
// For a view that spans rows, compensate its additional height so the row it's in stays the right height
if(tile.rowSpan>1){
outRect.bottom=-(Math.round(tile.height/1000f*width)-Math.round(layout.rowSizes[tile.startRow]/1000f*width));
}
// ...and for its siblings, offset those on rows below first to the right where they belong
if(tile.startCol>0 && layout.tiles[0].rowSpan>1 && tile.startRow>layout.tiles[0].startRow){
int xOffset=Math.round(layout.tiles[0].width/1000f*listWidth);
outRect.left=xOffset;
outRect.right=-xOffset;
}
// If the width of the media block is smaller than that of the RecyclerView, offset the views horizontally to center them
if(listWidth>width){
outRect.left+=(listWidth-V.dp(ImageAttachmentFrameLayout.MAX_WIDTH))/2;
if(tile.startCol>0){
int spanOffset=0;
for(int i=0;i<tile.startCol;i++){
spanOffset+=layout.columnSizes[i];
}
outRect.left-=Math.round(spanOffset/1000f*listWidth);
outRect.left+=Math.round(spanOffset/1000f*width);
}
}
}
}
private void rebuildMediaHiddenLayouts(int width){
currentMediaHiddenLayoutsWidth=width;
String title=getString(R.string.sensitive_content);

View File

@@ -1,7 +1,5 @@
package org.joinmastodon.android.fragments;
import static android.os.ext.SdkExtensions.getExtensionVersion;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -90,7 +88,7 @@ import org.joinmastodon.android.ui.text.ComposeAutocompleteSpan;
import org.joinmastodon.android.ui.text.ComposeHashtagOrMentionSpan;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
import org.joinmastodon.android.ui.utils.TransferSpeedTracker;
import org.joinmastodon.android.utils.TransferSpeedTracker;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ComposeEditText;
import org.joinmastodon.android.ui.views.ComposeMediaLayout;
@@ -333,6 +331,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
spoilerBg.setDrawableByLayerId(R.id.right_drawable, new SpoilerStripesDrawable());
spoilerEdit.setBackground(spoilerBg);
if((savedInstanceState!=null && savedInstanceState.getBoolean("hasSpoiler", false)) || hasSpoiler){
hasSpoiler=true;
spoilerEdit.setVisibility(View.VISIBLE);
spoilerBtn.setSelected(true);
}else if(editingStatus!=null && !TextUtils.isEmpty(editingStatus.spoilerText)){
@@ -641,9 +640,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
private void onCustomEmojiClick(Emoji emoji){
int start=mainEditText.getSelectionStart();
String prefix=start>0 && !Character.isWhitespace(mainEditText.getText().charAt(start-1)) ? " :" : ":";
mainEditText.getText().replace(start, mainEditText.getSelectionEnd(), prefix+emoji.shortcode+':');
if(getActivity().getCurrentFocus() instanceof EditText edit){
int start=edit.getSelectionStart();
String prefix=start>0 && !Character.isWhitespace(edit.getText().charAt(start-1)) ? " :" : ":";
edit.getText().replace(start, edit.getSelectionEnd(), prefix+emoji.shortcode+':');
}
}
@Override
@@ -794,18 +795,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
.show();
}
/**
* Check to see if Android platform photopicker is available on the device\
* @return whether the device supports photopicker intents.
*/
private boolean isPhotoPickerAvailable() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
return true;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return getExtensionVersion(Build.VERSION_CODES.R) >= 2;
} else
return false;
}
/**
* Builds the correct intent for the device version to select media.
@@ -817,24 +806,24 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
*/
private void openFilePicker(){
Intent intent;
boolean usePhotoPicker = isPhotoPickerAvailable();
if (usePhotoPicker) {
intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MediaStore.getPickImagesMaxLimit());
} else {
intent = new Intent(Intent.ACTION_GET_CONTENT);
boolean usePhotoPicker=UiUtils.isPhotoPickerAvailable();
if(usePhotoPicker){
intent=new Intent(MediaStore.ACTION_PICK_IMAGES);
intent.putExtra(MediaStore.EXTRA_PICK_IMAGES_MAX, MAX_ATTACHMENTS-getMediaAttachmentsCount());
}else{
intent=new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
}
if (!usePhotoPicker && instance.configuration != null &&
instance.configuration.mediaAttachments != null &&
instance.configuration.mediaAttachments.supportedMimeTypes != null &&
!instance.configuration.mediaAttachments.supportedMimeTypes.isEmpty()) {
if(!usePhotoPicker && instance.configuration!=null &&
instance.configuration.mediaAttachments!=null &&
instance.configuration.mediaAttachments.supportedMimeTypes!=null &&
!instance.configuration.mediaAttachments.supportedMimeTypes.isEmpty()){
intent.putExtra(Intent.EXTRA_MIME_TYPES,
instance.configuration.mediaAttachments.supportedMimeTypes.toArray(
new String[0]));
} else {
if (!usePhotoPicker) {
}else{
if(!usePhotoPicker){
// If photo picker is being used these are the default mimetypes.
intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[]{"image/*", "video/*"});
}
@@ -1070,7 +1059,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
if(att.isUploadingOrProcessing())
att.cancelUpload();
attachments.remove(att);
uploadNextQueuedAttachment();
if(!areThereAnyUploadingAttachments())
uploadNextQueuedAttachment();
attachmentsView.removeView(att.view);
if(getMediaAttachmentsCount()==0)
attachmentsView.setVisibility(View.GONE);

View File

@@ -20,6 +20,7 @@ import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.discover.DiscoverFragment;
import org.joinmastodon.android.fragments.onboarding.OnboardingFollowSuggestionsFragment;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.ui.AccountSwitcherSheet;
import org.joinmastodon.android.ui.utils.UiUtils;
@@ -31,6 +32,7 @@ import java.util.ArrayList;
import androidx.annotation.IdRes;
import androidx.annotation.Nullable;
import me.grishka.appkit.FragmentStackActivity;
import me.grishka.appkit.Nav;
import me.grishka.appkit.fragments.AppKitFragment;
import me.grishka.appkit.fragments.LoaderFragment;
import me.grishka.appkit.fragments.OnBackPressedListener;
@@ -235,6 +237,11 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
new AccountSwitcherSheet(getActivity()).show();
return true;
}
if(tab==R.id.tab_home){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), OnboardingFollowSuggestionsFragment.class, args);
}
return false;
}

View File

@@ -148,7 +148,7 @@ public class HomeTimelineFragment extends StatusListFragment{
protected void onHidden(){
super.onHidden();
if(!data.isEmpty()){
String topPostID=displayItems.get(list.getChildAdapterPosition(list.getChildAt(0))-getMainAdapterOffset()).parentID;
String topPostID=displayItems.get(Math.max(0, list.getChildAdapterPosition(list.getChildAt(0))-getMainAdapterOffset())).parentID;
if(!topPostID.equals(lastSavedMarkerID)){
lastSavedMarkerID=topPostID;
new SaveMarkers(topPostID, null)

View File

@@ -72,6 +72,18 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
tabLayout.setTabTextSize(V.dp(16));
tabLayout.setTabTextColors(UiUtils.getThemeColor(getActivity(), R.attr.colorTabInactive), UiUtils.getThemeColor(getActivity(), android.R.attr.textColorPrimary));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {}
@Override
public void onTabUnselected(TabLayout.Tab tab) {}
@Override
public void onTabReselected(TabLayout.Tab tab) {
scrollToTop();
}
});
pager.setOffscreenPageLimit(4);
pager.setAdapter(new DiscoverPagerAdapter());
@@ -137,6 +149,7 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
protected void updateToolbar(){
super.updateToolbar();
getToolbar().setOutlineProvider(null);
getToolbar().setOnClickListener(v->scrollToTop());
}
private NotificationsListFragment getFragmentForPage(int page){

View File

@@ -17,7 +17,6 @@ import org.joinmastodon.android.model.PaginatedResponse;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.displayitems.AccountCardStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ImageStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
import org.joinmastodon.android.ui.utils.InsetStatusItemDecoration;
import org.parceler.Parcels;
@@ -70,13 +69,6 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
HeaderStatusDisplayItem titleItem=extraText!=null ? new HeaderStatusDisplayItem(n.id, n.account, n.createdAt, this, accountID, null, extraText) : null;
if(n.status!=null){
ArrayList<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, n.status, accountID, n, knownAccounts, titleItem!=null, titleItem==null);
if(titleItem!=null){
for(StatusDisplayItem item:items){
if(item instanceof ImageStatusDisplayItem imgItem){
imgItem.horizontalInset=V.dp(32);
}
}
}
if(titleItem!=null)
items.add(0, titleItem);
return items;

View File

@@ -37,9 +37,11 @@ import org.joinmastodon.android.R;
import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.PushSubscriptionManager;
import org.joinmastodon.android.api.requests.oauth.RevokeOauthToken;
import org.joinmastodon.android.api.session.AccountActivationInfo;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
import org.joinmastodon.android.fragments.onboarding.AccountActivationFragment;
import org.joinmastodon.android.model.PushNotification;
import org.joinmastodon.android.model.PushSubscription;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
@@ -55,6 +57,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.imageloader.ImageCache;
@@ -122,6 +125,19 @@ public class SettingsFragment extends MastodonToolbarFragment{
items.add(new TextItem(R.string.settings_clear_cache, this::clearImageCache));
items.add(new TextItem(R.string.log_out, this::confirmLogOut));
if(BuildConfig.DEBUG){
items.add(new RedHeaderItem("Debug options"));
items.add(new TextItem("Test e-mail confirmation flow", ()->{
AccountSession sess=AccountSessionManager.getInstance().getAccount(accountID);
sess.activated=false;
sess.activationInfo=new AccountActivationInfo("test@email", System.currentTimeMillis());
Bundle args=new Bundle();
args.putString("account", accountID);
args.putBoolean("debug", true);
Nav.goClearingStack(getActivity(), AccountActivationFragment.class, args);
}));
}
items.add(new FooterItem(getString(R.string.settings_app_version, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE)));
}
@@ -346,6 +362,10 @@ public class SettingsFragment extends MastodonToolbarFragment{
this.text=getString(text);
}
public HeaderItem(String text){
this.text=text;
}
@Override
public int getViewType(){
return 0;
@@ -405,6 +425,11 @@ public class SettingsFragment extends MastodonToolbarFragment{
this.onClick=onClick;
}
public TextItem(String text, Runnable onClick){
this.text=text;
this.onClick=onClick;
}
@Override
public int getViewType(){
return 4;
@@ -417,6 +442,10 @@ public class SettingsFragment extends MastodonToolbarFragment{
super(text);
}
public RedHeaderItem(String text){
super(text);
}
@Override
public int getViewType(){
return 5;

View File

@@ -1,43 +1,47 @@
package org.joinmastodon.android.fragments;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.SpannableString;
import android.text.style.ReplacementSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Button;
import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.instance.GetInstance;
import org.joinmastodon.android.fragments.onboarding.InstanceCatalogSignupFragment;
import org.joinmastodon.android.fragments.onboarding.InstanceChooserLoginFragment;
import org.joinmastodon.android.fragments.onboarding.InstanceRulesFragment;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.ui.InterpolatingMotionEffect;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.SizeListenerFrameLayout;
import org.parceler.Parcels;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.AppKitFragment;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.BottomSheet;
public class SplashFragment extends AppKitFragment{
private static final String DEFAULT_SERVER="mastodon.social";
private SizeListenerFrameLayout contentView;
private View artContainer, blueFill, greenFill;
private ViewPager2 pager;
private ViewGroup pagerDots;
private InterpolatingMotionEffect motionEffect;
private View artClouds, artPlaneElephant, artRightHill, artLeftHill, artCenterHill;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
motionEffect=new InterpolatingMotionEffect(MastodonApp.context);
}
@Nullable
@@ -46,44 +50,26 @@ public class SplashFragment extends AppKitFragment{
contentView=(SizeListenerFrameLayout) inflater.inflate(R.layout.fragment_splash, container, false);
contentView.findViewById(R.id.btn_get_started).setOnClickListener(this::onButtonClick);
contentView.findViewById(R.id.btn_log_in).setOnClickListener(this::onButtonClick);
Button joinDefault=contentView.findViewById(R.id.btn_join_default_server);
joinDefault.setText(getString(R.string.join_default_server, DEFAULT_SERVER));
joinDefault.setOnClickListener(this::onJoinDefaultServerClick);
contentView.findViewById(R.id.btn_learn_more).setOnClickListener(this::onLearnMoreClick);
artClouds=contentView.findViewById(R.id.art_clouds);
artPlaneElephant=contentView.findViewById(R.id.art_plane_elephant);
artRightHill=contentView.findViewById(R.id.art_right_hill);
artLeftHill=contentView.findViewById(R.id.art_left_hill);
artCenterHill=contentView.findViewById(R.id.art_center_hill);
pager=contentView.findViewById(R.id.pager);
pagerDots=contentView.findViewById(R.id.pager_dots);
pager.setAdapter(new PagerAdapter());
pager.setOffscreenPageLimit(3);
pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback(){
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels){
for(int i=0;i<pagerDots.getChildCount();i++){
float alpha;
if(i==position){
alpha=0.3f+0.7f*(1f-positionOffset);
}else if(i==position+1){
alpha=0.3f+0.7f*positionOffset;
}else{
alpha=0.3f;
}
pagerDots.getChildAt(i).setAlpha(alpha);
}
float parallaxProgress=(position+positionOffset)/2f;
artClouds.setTranslationX(V.dp(-27)*(position>=1 ? 1f : positionOffset));
artPlaneElephant.setTranslationX(V.dp(101.55f)*parallaxProgress);
artLeftHill.setTranslationX(V.dp(-88)*parallaxProgress);
artLeftHill.setTranslationY(V.dp(24)*parallaxProgress);
artRightHill.setTranslationX(V.dp(-88)*parallaxProgress);
artRightHill.setTranslationY(V.dp(-24)*parallaxProgress);
artCenterHill.setTranslationX(V.dp(-40)*parallaxProgress);
}
});
artContainer=contentView.findViewById(R.id.art_container);
blueFill=contentView.findViewById(R.id.blue_fill);
greenFill=contentView.findViewById(R.id.green_fill);
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(artClouds, V.dp(-5), V.dp(5), V.dp(-5), V.dp(5)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(artRightHill, V.dp(-15), V.dp(25), V.dp(-10), V.dp(10)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(artLeftHill, V.dp(-25), V.dp(15), V.dp(-15), V.dp(15)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(artCenterHill, V.dp(-14), V.dp(14), V.dp(-5), V.dp(25)));
motionEffect.addViewEffect(new InterpolatingMotionEffect.ViewEffect(artPlaneElephant, V.dp(-20), V.dp(12), V.dp(-20), V.dp(12)));
artContainer.setOnTouchListener(motionEffect);
contentView.setSizeListener(new SizeListenerFrameLayout.OnSizeChangedListener(){
@Override
@@ -109,6 +95,38 @@ public class SplashFragment extends AppKitFragment{
Nav.go(getActivity(), isSignup ? InstanceCatalogSignupFragment.class : InstanceChooserLoginFragment.class, extras);
}
private void onJoinDefaultServerClick(View v){
new GetInstance()
.setCallback(new Callback<>(){
@Override
public void onSuccess(Instance result){
if(getActivity()==null)
return;
Bundle args=new Bundle();
args.putParcelable("instance", Parcels.wrap(result));
Nav.go(getActivity(), InstanceRulesFragment.class, args);
}
@Override
public void onError(ErrorResponse error){
if(getActivity()==null)
return;
error.showToast(getActivity());
}
})
.wrapProgress(getActivity(), R.string.loading_instance, true)
.execNoAuth(DEFAULT_SERVER);
}
private void onLearnMoreClick(View v){
View sheetView=getActivity().getLayoutInflater().inflate(R.layout.intro_bottom_sheet, null);
BottomSheet sheet=new BottomSheet(getActivity());
sheet.setContentView(sheetView);
sheet.setNavigationBarBackground(new ColorDrawable(UiUtils.alphaBlendColors(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Surface),
UiUtils.getThemeColor(getActivity(), R.attr.colorM3Primary), 0.05f)), !UiUtils.isDarkTheme());
sheet.show();
}
private void updateArtSize(int w, int h){
float scale=w/(float)V.dp(360);
artContainer.setScaleX(scale);
@@ -139,91 +157,15 @@ public class SplashFragment extends AppKitFragment{
return true;
}
private class PagerAdapter extends RecyclerView.Adapter<PagerViewHolder>{
@NonNull
@Override
public PagerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
return new PagerViewHolder(viewType);
}
@Override
public void onBindViewHolder(@NonNull PagerViewHolder holder, int position){}
@Override
public int getItemCount(){
return 3;
}
@Override
public int getItemViewType(int position){
return position;
}
@Override
protected void onShown(){
super.onShown();
motionEffect.activate();
}
private class PagerViewHolder extends RecyclerView.ViewHolder{
public PagerViewHolder(int page){
super(new LinearLayout(getActivity()));
LinearLayout ll=(LinearLayout) itemView;
ll.setOrientation(LinearLayout.VERTICAL);
int pad=V.dp(16);
ll.setPadding(pad, pad, pad, pad);
ll.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
TextView title=new TextView(getActivity());
title.setTextAppearance(R.style.m3_headline_medium);
title.setText(switch(page){
case 0 -> {
String src=getString(R.string.welcome_page1_title);
SpannableString ss=new SpannableString(src);
int start=src.indexOf("{logo}");
if(start!=-1){
LogoSpan span=new LogoSpan(getResources().getDrawable(R.drawable.splash_logo, getActivity().getTheme()));
ss.setSpan(span, start, start+6, 0);
}
yield ss;
}
case 1 -> getString(R.string.welcome_page2_title);
case 2 -> getString(R.string.welcome_page3_title);
default -> throw new IllegalStateException("Unexpected value: "+page);
});
title.setTextColor(0xFF17063B);
LinearLayout.LayoutParams lp=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(page==0 ? 46 : 36));
lp.bottomMargin=V.dp(page==0 ? 4 : 14);
ll.addView(title, lp);
TextView text=new TextView(getActivity());
text.setTextAppearance(R.style.m3_body_medium);
text.setText(switch(page){
case 0 -> R.string.welcome_page1_text;
case 1 -> R.string.welcome_page2_text;
case 2 -> R.string.welcome_page3_text;
default -> throw new IllegalStateException("Unexpected value: "+page);
});
text.setTextColor(0xFF17063B);
ll.addView(text, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
}
private class LogoSpan extends ReplacementSpan{
private final Drawable drawable;
private LogoSpan(Drawable drawable){
this.drawable=drawable;
}
@Override
public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm){
return drawable.getIntrinsicWidth();
}
@Override
public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint){
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
canvas.save();
canvas.translate(x, y-V.dp(20));
drawable.draw(canvas);
canvas.restore();
}
@Override
protected void onHidden(){
super.onHidden();
motionEffect.deactivate();
}
}

View File

@@ -143,7 +143,7 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>{
protected void onRemoveAccountPostsEvent(RemoveAccountPostsEvent ev){
List<Status> toRemove=Stream.concat(data.stream(), preloadedData.stream())
.filter(s->s.account.id.equals(ev.postsByAccountID) || (s.reblog!=null && s.reblog.account.id.equals(ev.postsByAccountID)))
.filter(s->s.account.id.equals(ev.postsByAccountID) || (!ev.isUnfollow && s.reblog!=null && s.reblog.account.id.equals(ev.postsByAccountID)))
.collect(Collectors.toList());
for(Status s:toRemove){
removeStatus(s);

View File

@@ -236,7 +236,7 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
}
public void setQuery(String q){
if(Objects.equals(q, currentQuery))
if(Objects.equals(q, currentQuery) || q.isBlank())
return;
if(currentRequest!=null){
currentRequest.cancel();

View File

@@ -193,30 +193,24 @@ public class AccountActivationFragment extends ToolbarFragment{
mgr.removeAccount(accountID);
mgr.addAccount(mgr.getInstanceInfo(session.domain), session.token, result, session.app, null);
String newID=mgr.getLastActiveAccountID();
Bundle args=new Bundle();
args.putString("account", newID);
if(session.self.avatar!=null || session.self.displayName!=null){
File avaFile=session.self.avatar!=null ? new File(session.self.avatar) : null;
new UpdateAccountCredentials(session.self.displayName, "", avaFile, null, Collections.emptyList())
accountID=newID;
if((session.self.avatar!=null || session.self.displayName!=null) && !getArguments().getBoolean("debug")){
new UpdateAccountCredentials(session.self.displayName, "", (File)null, null, Collections.emptyList())
.setCallback(new Callback<>(){
@Override
public void onSuccess(Account result){
if(avaFile!=null)
avaFile.delete();
mgr.updateAccountInfo(newID, result);
Nav.goClearingStack(getActivity(), HomeFragment.class, args);
proceed();
}
@Override
public void onError(ErrorResponse error){
if(avaFile!=null)
avaFile.delete();
Nav.goClearingStack(getActivity(), HomeFragment.class, args);
proceed();
}
})
.exec(newID);
}else{
Nav.goClearingStack(getActivity(), HomeFragment.class, args);
proceed();
}
}
@@ -249,4 +243,11 @@ public class AccountActivationFragment extends ToolbarFragment{
super.onDestroyView();
resendBtn.removeCallbacks(resendTimer);
}
private void proceed(){
Bundle args=new Bundle();
args.putString("account", accountID);
// Nav.goClearingStack(getActivity(), HomeFragment.class, args);
Nav.goClearingStack(getActivity(), OnboardingFollowSuggestionsFragment.class, args);
}
}

View File

@@ -5,6 +5,7 @@ import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -19,6 +20,7 @@ import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.ui.DividerItemDecoration;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.utils.ElevationOnScrollListener;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.parceler.Parcels;
@@ -42,6 +44,7 @@ import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.MergeRecyclerAdapter;
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
import me.grishka.appkit.views.UsableRecyclerView;
import okhttp3.Call;
import okhttp3.Callback;
@@ -58,6 +61,9 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
private ArrayList<Item> items=new ArrayList<>();
private Call currentRequest;
private ItemsAdapter itemsAdapter;
private ElevationOnScrollListener onScrollListener;
private static final int SIGNUP_REQUEST=722;
@Override
public void onCreate(Bundle savedInstanceState){
@@ -72,7 +78,7 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
setNavigationBarColor(UiUtils.getThemeColor(activity, R.attr.colorWindowBackground));
instance=Parcels.unwrap(getArguments().getParcelable("instance"));
items.add(new Item("Mastodon for Android Privacy Policy", "joinmastodon.org", "https://joinmastodon.org/android/privacy", "https://joinmastodon.org/favicon-32x32.png"));
items.add(new Item("Mastodon for Android Privacy Policy", getString(R.string.privacy_policy_explanation), "joinmastodon.org", "https://joinmastodon.org/android/privacy", "https://joinmastodon.org/favicon-32x32.png"));
loadServerPrivacyPolicy();
}
@@ -93,18 +99,24 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
list.setLayoutManager(new LinearLayoutManager(getActivity()));
View headerView=inflater.inflate(R.layout.item_list_header_simple, list, false);
TextView text=headerView.findViewById(R.id.text);
text.setText(R.string.privacy_policy_subtitle);
text.setText(getString(R.string.privacy_policy_subtitle, instance.uri));
adapter=new MergeRecyclerAdapter();
adapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
adapter.addAdapter(itemsAdapter=new ItemsAdapter());
list.setAdapter(adapter);
list.addItemDecoration(new DividerItemDecoration(getActivity(), R.attr.colorM3SurfaceVariant, 1, 56, 0, DividerItemDecoration.NOT_FIRST));
btn=view.findViewById(R.id.btn_next);
btn.setOnClickListener(v->onButtonClick());
buttonBar=view.findViewById(R.id.button_bar);
Button backBtn=view.findViewById(R.id.btn_back);
backBtn.setText(getString(R.string.server_policy_disagree, instance.uri));
backBtn.setOnClickListener(v->{
setResult(false, null);
Nav.finish(this);
});
return view;
}
@@ -113,19 +125,32 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
super.onViewCreated(view, savedInstanceState);
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
list.addOnScrollListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
}
@Override
protected void onUpdateToolbar(){
super.onUpdateToolbar();
getToolbar().setBackground(null);
getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
getToolbar().setElevation(0);
if(onScrollListener!=null){
onScrollListener.setViews(buttonBar, getToolbar());
}
}
protected void onButtonClick(){
Bundle args=new Bundle();
args.putParcelable("instance", Parcels.wrap(instance));
Nav.go(getActivity(), SignupFragment.class, args);
Nav.goForResult(getActivity(), SignupFragment.class, args, SIGNUP_REQUEST, this);
}
@Override
public void onFragmentResult(int reqCode, boolean success, Bundle result){
super.onFragmentResult(reqCode, success, result);
if(reqCode==SIGNUP_REQUEST && !success){
setResult(false, null);
Nav.finish(this);
}
}
@Override
@@ -158,7 +183,7 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
if(!response.isSuccessful())
return;
Document doc=Jsoup.parse(Objects.requireNonNull(body).byteStream(), Objects.requireNonNull(body.contentType()).charset(StandardCharsets.UTF_8).name(), req.url().toString());
final Item item=new Item(doc.title(), instance.uri, req.url().toString(), "https://"+instance.uri+"/favicon.ico");
final Item item=new Item(doc.title(), null, instance.uri, req.url().toString(), "https://"+instance.uri+"/favicon.ico");
Activity activity=getActivity();
if(activity!=null){
activity.runOnUiThread(()->{
@@ -192,16 +217,23 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
private class ItemViewHolder extends BindableViewHolder<Item> implements UsableRecyclerView.Clickable{
private final TextView title;
private final TextView subtitle;
public ItemViewHolder(){
super(getActivity(), R.layout.item_privacy_policy_link, list);
title=findViewById(R.id.title);
title.setPaintFlags(title.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
subtitle=findViewById(R.id.subtitle);
}
@Override
public void onBind(Item item){
title.setText(item.title);
if(TextUtils.isEmpty(item.subtitle)){
subtitle.setVisibility(View.GONE);
}else{
subtitle.setVisibility(View.VISIBLE);
subtitle.setText(item.subtitle);
}
}
@Override
@@ -211,10 +243,11 @@ public class GoogleMadeMeAddThisFragment extends ToolbarFragment{
}
private static class Item{
public String title, domain, url, faviconUrl;
public String title, subtitle, domain, url, faviconUrl;
public Item(String title, String domain, String url, String faviconUrl){
public Item(String title, String subtitle, String domain, String url, String faviconUrl){
this.title=title;
this.subtitle=subtitle;
this.domain=domain;
this.url=url;
this.faviconUrl=faviconUrl;

View File

@@ -5,15 +5,12 @@ import android.app.ProgressDialog;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.LocaleList;
import android.text.TextUtils;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;
import android.widget.TextView;
import org.joinmastodon.android.R;
@@ -23,7 +20,6 @@ import org.joinmastodon.android.api.requests.instance.GetInstance;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.catalog.CatalogInstance;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
@@ -31,6 +27,8 @@ import org.xml.sax.InputSource;
import java.io.IOException;
import java.net.IDN;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -50,7 +48,6 @@ import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.MergeRecyclerAdapter;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.UsableRecyclerView;
import okhttp3.Call;
import okhttp3.Request;
import okhttp3.Response;
@@ -92,7 +89,7 @@ abstract class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInsta
protected boolean onSearchEnterPressed(TextView v, int actionId, KeyEvent event){
if(event!=null && event.getAction()!=KeyEvent.ACTION_DOWN)
return true;
currentSearchQuery=searchEdit.getText().toString().toLowerCase();
currentSearchQuery=searchEdit.getText().toString().toLowerCase().trim();
updateFilteredList();
searchEdit.removeCallbacks(searchDebouncer);
Instance instance=instancesCache.get(normalizeInstanceDomain(currentSearchQuery));
@@ -106,52 +103,16 @@ abstract class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInsta
}
protected void onSearchChangedDebounced(){
currentSearchQuery=searchEdit.getText().toString().toLowerCase();
currentSearchQuery=searchEdit.getText().toString().toLowerCase().trim();
updateFilteredList();
loadInstanceInfo(currentSearchQuery, false);
}
protected List<CatalogInstance> sortInstances(List<CatalogInstance> result){
Map<String, List<CatalogInstance>> byLang=result.stream().collect(Collectors.groupingBy(ci->ci.language));
for(List<CatalogInstance> group:byLang.values()){
Collections.sort(group, (a, b)->{
double aa=Math.abs(DUNBAR-Math.log(a.lastWeekUsers));
double bb=Math.abs(DUNBAR-Math.log(b.lastWeekUsers));
return Double.compare(aa, bb);
});
}
// get the list of user-configured system languages
List<String> userLangs;
if(Build.VERSION.SDK_INT<24){
userLangs=Collections.singletonList(getResources().getConfiguration().locale.getLanguage());
}else{
LocaleList ll=getResources().getConfiguration().getLocales();
userLangs=new ArrayList<>(ll.size());
for(int i=0;i<ll.size();i++){
userLangs.add(ll.get(i).getLanguage());
}
}
// add instances in preferred languages to the top of the list, in the order of preference
Map<Boolean, List<CatalogInstance>> byLang=result.stream().sorted(Comparator.comparingInt((CatalogInstance ci)->ci.lastWeekUsers).reversed()).collect(Collectors.groupingBy(ci->ci.approvalRequired));
ArrayList<CatalogInstance> sortedList=new ArrayList<>();
for(String lang:userLangs){
List<CatalogInstance> langInstances=byLang.remove(lang);
if(langInstances!=null){
sortedList.addAll(langInstances);
}
}
// sort the remaining language groups by aggregate lastWeekUsers
class InstanceGroup{
public int activeUsers;
public List<CatalogInstance> instances;
}
byLang.values().stream().map(il->{
InstanceGroup group=new InstanceGroup();
group.instances=il;
for(CatalogInstance instance:il){
group.activeUsers+=instance.lastWeekUsers;
}
return group;
}).sorted(Comparator.comparingInt((InstanceGroup g)->g.activeUsers).reversed()).forEachOrdered(ig->sortedList.addAll(ig.instances));
sortedList.addAll(byLang.getOrDefault(false, Collections.emptyList()));
sortedList.addAll(byLang.getOrDefault(true, Collections.emptyList()));
return sortedList;
}
@@ -208,6 +169,20 @@ abstract class InstanceCatalogFragment extends BaseRecyclerFragment<CatalogInsta
cancelLoadingInstanceInfo();
}
}
try{
new URI("https://"+domain+"/api/v1/instance"); // Validate the host by trying to parse the URI
}catch(URISyntaxException x){
showInstanceInfoLoadError(domain, x);
if(fakeInstance!=null){
fakeInstance.description=getString(R.string.error);
if(filteredData.size()>0 && filteredData.get(0)==fakeInstance){
if(list.findViewHolderForAdapterPosition(1) instanceof BindableViewHolder<?> ivh){
ivh.rebind();
}
}
}
return;
}
loadingInstanceDomain=domain;
loadingInstanceRequest=new GetInstance();
loadingInstanceRequest.setCallback(new Callback<>(){

View File

@@ -1,14 +1,8 @@
package org.joinmastodon.android.fragments.onboarding;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
@@ -20,7 +14,6 @@ import android.view.WindowInsets;
import android.view.inputmethod.InputMethodManager;
import android.widget.HorizontalScrollView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.RadioButton;
@@ -38,6 +31,7 @@ import org.joinmastodon.android.ui.BetterItemAnimator;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.FilterChipView;
import org.joinmastodon.android.utils.ElevationOnScrollListener;
import org.parceler.Parcels;
import java.util.ArrayList;
@@ -56,11 +50,7 @@ import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.OnBackPressedListener;
import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.CubicBezierInterpolator;
import me.grishka.appkit.utils.MergeRecyclerAdapter;
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
import me.grishka.appkit.utils.V;
@@ -74,7 +64,7 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
private List<String> languages=Collections.emptyList();
private PopupMenu langFilterMenu, speedFilterMenu;
private SignupSpeedFilter currentSignupSpeedFilter=SignupSpeedFilter.INSTANT;
private SignupSpeedFilter currentSignupSpeedFilter=SignupSpeedFilter.ANY;
private String currentLanguage=null;
private boolean searchQueryMode;
private LinearLayout filtersWrap;
@@ -85,7 +75,7 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
private FilterChipView categoryGeneral, categorySpecialInterests;
private List<FilterChipView> regionalFilters;
private CatalogInstance.Region chosenRegion;
private CategoryChoice categoryChoice;
private CategoryChoice categoryChoice=CategoryChoice.GENERAL;
public InstanceCatalogSignupFragment(){
super(R.layout.fragment_onboarding_common, 10);
@@ -215,47 +205,7 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
setStatusBarColor(0);
topBar=view.findViewById(R.id.top_bar);
LayerDrawable topBg=(LayerDrawable) topBar.getBackground().mutate();
topBar.setBackground(topBg);
Drawable topOverlay=topBg.findDrawableByLayerId(R.id.color_overlay);
topOverlay.setAlpha(0);
LayerDrawable btmBg=(LayerDrawable) buttonBar.getBackground().mutate();
buttonBar.setBackground(btmBg);
Drawable btmOverlay=btmBg.findDrawableByLayerId(R.id.color_overlay);
btmOverlay.setAlpha(0);
list.addOnScrollListener(new RecyclerView.OnScrollListener(){
private boolean isAtTop=true;
private Animator currentPanelsAnim;
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){
boolean newAtTop=recyclerView.getChildCount()==0 || (recyclerView.getChildAdapterPosition(recyclerView.getChildAt(0))==0 && recyclerView.getChildAt(0).getTop()==recyclerView.getPaddingTop());
if(newAtTop!=isAtTop){
isAtTop=newAtTop;
if(currentPanelsAnim!=null)
currentPanelsAnim.cancel();
AnimatorSet set=new AnimatorSet();
set.playTogether(
ObjectAnimator.ofInt(topOverlay, "alpha", isAtTop ? 0 : 20),
ObjectAnimator.ofInt(btmOverlay, "alpha", isAtTop ? 0 : 20),
ObjectAnimator.ofFloat(topBar, View.TRANSLATION_Z, isAtTop ? 0 : V.dp(3)),
ObjectAnimator.ofFloat(buttonBar, View.TRANSLATION_Z, isAtTop ? 0 : V.dp(3))
);
set.setDuration(150);
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
set.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
currentPanelsAnim=null;
}
});
set.start();
currentPanelsAnim=set;
}
}
});
list.addOnScrollListener(new ElevationOnScrollListener(null, topBar, buttonBar));
searchEdit=view.findViewById(R.id.search_edit);
searchEdit.setOnEditorActionListener(this::onSearchEnterPressed);
@@ -366,6 +316,9 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
}).collect(Collectors.toList());
focusThing=view.findViewById(R.id.focus_thing);
focusThing.requestFocus();
view.findViewById(R.id.btn_random_instance).setOnClickListener(this::onPickRandomInstanceClick);
nextButton.setEnabled(chosenInstance!=null);
}
private void onRegionFilterClick(View v){
@@ -396,22 +349,6 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
updateFilteredList();
}
@Override
protected void onNextClick(View v){
if(chosenInstance==null){
String lang=Locale.getDefault().getLanguage();
List<CatalogInstance> instances=data.stream().filter(ci->!ci.approvalRequired && ("general".equals(ci.category) || (ci.categories!=null && ci.categories.contains("general"))) && (lang.equals(ci.language) || (ci.languages!=null && ci.languages.contains(lang)))).collect(Collectors.toList());
if(instances.isEmpty()){
instances=data.stream().filter(ci->!ci.approvalRequired && ("general".equals(ci.category) || (ci.categories!=null && ci.categories.contains("general")))).collect(Collectors.toList());
}
if(instances.isEmpty()){
return;
}
chosenInstance=instances.get(new Random().nextInt(instances.size()));
}
super.onNextClick(v);
}
@Override
protected void proceedWithAuthOrSignup(Instance instance){
getActivity().getSystemService(InputMethodManager.class).hideSoftInputFromWindow(contentView.getWindowToken(), 0);
@@ -428,6 +365,22 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
Nav.go(getActivity(), InstanceRulesFragment.class, args);
}
private void onPickRandomInstanceClick(View v){
String lang=Locale.getDefault().getLanguage();
List<CatalogInstance> instances=data.stream().filter(ci->!ci.approvalRequired && ("general".equals(ci.category) || (ci.categories!=null && ci.categories.contains("general"))) && (lang.equals(ci.language) || (ci.languages!=null && ci.languages.contains(lang)))).collect(Collectors.toList());
if(instances.isEmpty()){
instances=data.stream().filter(ci->!ci.approvalRequired && ("general".equals(ci.category) || (ci.categories!=null && ci.categories.contains("general")))).collect(Collectors.toList());
}
if(instances.isEmpty()){
instances=data.stream().filter(ci->("general".equals(ci.category) || (ci.categories!=null && ci.categories.contains("general")))).collect(Collectors.toList());
}
if(instances.isEmpty()){
return;
}
chosenInstance=instances.get(new Random().nextInt(instances.size()));
onNextClick(v);
}
// private String getEmojiForCategory(String category){
// return switch(category){
// case "all" -> "💬";
@@ -577,7 +530,16 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
updateFilteredList();
}
private class InstancesAdapter extends UsableRecyclerView.Adapter<InstanceCatalogSignupFragment.InstanceViewHolder> implements ImageLoaderRecyclerAdapter{
@Override
protected void onShown(){
super.onShown();
if(!searchQueryMode){
// Prevent search view automatically getting focused when the user returns to this fragment
focusThing.requestFocus();
}
}
private class InstancesAdapter extends UsableRecyclerView.Adapter<InstanceCatalogSignupFragment.InstanceViewHolder>{
public InstancesAdapter(){
super(imgLoader);
}
@@ -603,22 +565,11 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
public int getItemViewType(int position){
return -1;
}
@Override
public int getImageCountForItem(int position){
return filteredData.get(position).thumbnailRequest!=null ? 1 : 0;
}
@Override
public ImageLoaderRequest getImageRequest(int position, int image){
return filteredData.get(position).thumbnailRequest;
}
}
private class InstanceViewHolder extends BindableViewHolder<CatalogInstance> implements UsableRecyclerView.DisableableClickable, ImageLoaderViewHolder{
private class InstanceViewHolder extends BindableViewHolder<CatalogInstance> implements UsableRecyclerView.DisableableClickable{
private final TextView title, description;
private final RadioButton radioButton;
private final ImageView thumbnail;
private boolean enabled;
public InstanceViewHolder(){
@@ -626,15 +577,12 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
title=findViewById(R.id.title);
description=findViewById(R.id.description);
radioButton=findViewById(R.id.radiobtn);
thumbnail=findViewById(R.id.image);
}
@Override
public void onBind(CatalogInstance item){
title.setText(item.normalizedDomain);
radioButton.setChecked(chosenInstance==item);
if(item.thumbnailRequest==null)
thumbnail.setImageDrawable(null);
Instance realInstance=instancesCache.get(item.normalizedDomain);
float alpha;
if(realInstance!=null && !realInstance.registrations){
@@ -649,7 +597,6 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
title.setAlpha(alpha);
description.setAlpha(alpha);
radioButton.setAlpha(alpha);
thumbnail.setAlpha(alpha);
}
@Override
@@ -672,6 +619,9 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
adapter.notifyItemChanged(idx);
}
}
if(!nextButton.isEnabled()){
nextButton.setEnabled(true);
}
radioButton.setChecked(true);
if(chosenInstance==null)
nextButton.setEnabled(true);
@@ -679,16 +629,6 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
loadInstanceInfo(chosenInstance.domain, false);
}
@Override
public void setImage(int index, Drawable image){
thumbnail.setImageDrawable(image);
}
@Override
public void clearImage(int index){
setImage(index, null);
}
@Override
public boolean isEnabled(){
return enabled;
@@ -710,4 +650,5 @@ public class InstanceCatalogSignupFragment extends InstanceCatalogFragment imple
return (this==GENERAL)==isGeneral;
}
}
}

View File

@@ -2,8 +2,14 @@ package org.joinmastodon.android.fragments.onboarding;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.StyleSpan;
import android.text.style.TypefaceSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -17,6 +23,7 @@ import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.ui.DividerItemDecoration;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.utils.ElevationOnScrollListener;
import org.parceler.Parcels;
import androidx.annotation.NonNull;
@@ -28,6 +35,7 @@ import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.MergeRecyclerAdapter;
import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
import me.grishka.appkit.views.UsableRecyclerView;
public class InstanceRulesFragment extends ToolbarFragment{
@@ -36,6 +44,9 @@ public class InstanceRulesFragment extends ToolbarFragment{
private Button btn;
private View buttonBar;
private Instance instance;
private ElevationOnScrollListener onScrollListener;
private static final int RULES_REQUEST=376;
@Override
public void onCreate(Bundle savedInstanceState){
@@ -59,7 +70,7 @@ public class InstanceRulesFragment extends ToolbarFragment{
list.setLayoutManager(new LinearLayoutManager(getActivity()));
View headerView=inflater.inflate(R.layout.item_list_header_simple, list, false);
TextView text=headerView.findViewById(R.id.text);
text.setText(getString(R.string.instance_rules_subtitle, instance.uri));
text.setText(Html.fromHtml(getString(R.string.instance_rules_subtitle, "<b>"+Html.escapeHtml(instance.uri)+"</b>")));
adapter=new MergeRecyclerAdapter();
adapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
@@ -71,6 +82,8 @@ public class InstanceRulesFragment extends ToolbarFragment{
btn.setOnClickListener(v->onButtonClick());
buttonBar=view.findViewById(R.id.button_bar);
view.findViewById(R.id.btn_back).setOnClickListener(v->Nav.finish(this));
return view;
}
@@ -79,19 +92,31 @@ public class InstanceRulesFragment extends ToolbarFragment{
super.onViewCreated(view, savedInstanceState);
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
list.addOnScrollListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
}
@Override
protected void onUpdateToolbar(){
super.onUpdateToolbar();
getToolbar().setBackground(null);
getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
getToolbar().setElevation(0);
if(onScrollListener!=null){
onScrollListener.setViews(buttonBar, getToolbar());
}
}
protected void onButtonClick(){
Bundle args=new Bundle();
args.putParcelable("instance", Parcels.wrap(instance));
Nav.go(getActivity(), GoogleMadeMeAddThisFragment.class, args);
Nav.goForResult(getActivity(), GoogleMadeMeAddThisFragment.class, args, RULES_REQUEST, this);
}
@Override
public void onFragmentResult(int reqCode, boolean success, Bundle result){
super.onFragmentResult(reqCode, success, result);
if(reqCode==RULES_REQUEST && !success){
Nav.finish(this);
}
}
@Override

View File

@@ -0,0 +1,344 @@
package org.joinmastodon.android.fragments.onboarding;
import android.app.ProgressDialog;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
import org.joinmastodon.android.api.requests.accounts.GetFollowSuggestions;
import org.joinmastodon.android.api.requests.accounts.SetAccountFollowed;
import org.joinmastodon.android.fragments.HomeFragment;
import org.joinmastodon.android.fragments.ProfileFragment;
import org.joinmastodon.android.model.FollowSuggestion;
import org.joinmastodon.android.model.ParsedAccount;
import org.joinmastodon.android.model.Relationship;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ProgressBarButton;
import org.joinmastodon.android.utils.ElevationOnScrollListener;
import org.parceler.Parcels;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.imageloader.ImageLoaderRecyclerAdapter;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
import me.grishka.appkit.views.UsableRecyclerView;
public class OnboardingFollowSuggestionsFragment extends BaseRecyclerFragment<ParsedAccount>{
private String accountID;
private Map<String, Relationship> relationships=Collections.emptyMap();
private GetAccountRelationships relationshipsRequest;
private View buttonBar;
private ElevationOnScrollListener onScrollListener;
private int numRunningFollowRequests=0;
public OnboardingFollowSuggestionsFragment(){
super(R.layout.fragment_onboarding_follow_suggestions, 40);
}
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setRetainInstance(true);
setTitle(R.string.popular_on_mastodon);
accountID=getArguments().getString("account");
loadData();
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
buttonBar=view.findViewById(R.id.button_bar);
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
list.addOnScrollListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
view.findViewById(R.id.btn_next).setOnClickListener(UiUtils.rateLimitedClickListener(this::onFollowAllClick));
view.findViewById(R.id.btn_skip).setOnClickListener(UiUtils.rateLimitedClickListener(v->proceed()));
}
@Override
protected void onUpdateToolbar(){
super.onUpdateToolbar();
getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
getToolbar().setElevation(0);
if(onScrollListener!=null){
onScrollListener.setViews(buttonBar, getToolbar());
}
}
@Override
protected void doLoadData(int offset, int count){
new GetFollowSuggestions(40)
.setCallback(new SimpleCallback<>(this){
@Override
public void onSuccess(List<FollowSuggestion> result){
onDataLoaded(result.stream().map(fs->new ParsedAccount(fs.account, accountID)).collect(Collectors.toList()), false);
loadRelationships();
}
})
.exec(accountID);
}
private void loadRelationships(){
relationships=Collections.emptyMap();
relationshipsRequest=new GetAccountRelationships(data.stream().map(fs->fs.account.id).collect(Collectors.toList()));
relationshipsRequest.setCallback(new Callback<>(){
@Override
public void onSuccess(List<Relationship> result){
relationshipsRequest=null;
relationships=result.stream().collect(Collectors.toMap(rel->rel.id, Function.identity()));
if(list==null)
return;
for(int i=0;i<list.getChildCount();i++){
RecyclerView.ViewHolder holder=list.getChildViewHolder(list.getChildAt(i));
if(holder instanceof SuggestionViewHolder svh)
svh.rebind();
}
}
@Override
public void onError(ErrorResponse error){
relationshipsRequest=null;
}
}).exec(accountID);
}
@Override
public void onApplyWindowInsets(WindowInsets insets){
if(Build.VERSION.SDK_INT>=27){
int inset=insets.getSystemWindowInsetBottom();
buttonBar.setPadding(0, 0, 0, inset>0 ? Math.max(inset, V.dp(36)) : 0);
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), 0));
}else{
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()));
}
}
@Override
protected RecyclerView.Adapter getAdapter(){
return new SuggestionsAdapter();
}
private void onFollowAllClick(View v){
if(!loaded || relationships.isEmpty())
return;
if(data.isEmpty()){
proceed();
return;
}
ArrayList<String> accountIdsToFollow=new ArrayList<>();
for(ParsedAccount acc:data){
Relationship rel=relationships.get(acc.account.id);
if(rel==null)
continue;
if(rel.canFollow())
accountIdsToFollow.add(acc.account.id);
}
final ProgressDialog progress=new ProgressDialog(getActivity());
progress.setIndeterminate(false);
progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progress.setMax(accountIdsToFollow.size());
progress.setCancelable(false);
progress.setMessage(getString(R.string.sending_follows));
progress.show();
for(int i=0;i<Math.min(accountIdsToFollow.size(), 5);i++){ // Send up to 5 requests in parallel
followNextAccount(accountIdsToFollow, progress);
}
}
private void followNextAccount(ArrayList<String> accountIdsToFollow, ProgressDialog progress){
if(accountIdsToFollow.isEmpty()){
if(numRunningFollowRequests==0){
progress.dismiss();
proceed();
}
return;
}
numRunningFollowRequests++;
String id=accountIdsToFollow.remove(0);
new SetAccountFollowed(id, true, true)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Relationship result){
relationships.put(id, result);
for(int i=0;i<list.getChildCount();i++){
if(list.getChildViewHolder(list.getChildAt(i)) instanceof SuggestionViewHolder svh && svh.getItem().account.id.equals(id)){
svh.rebind();
break;
}
}
numRunningFollowRequests--;
progress.setProgress(progress.getMax()-accountIdsToFollow.size()-numRunningFollowRequests);
followNextAccount(accountIdsToFollow, progress);
}
@Override
public void onError(ErrorResponse error){
numRunningFollowRequests--;
progress.setProgress(progress.getMax()-accountIdsToFollow.size()-numRunningFollowRequests);
followNextAccount(accountIdsToFollow, progress);
}
})
.exec(accountID);
}
private void proceed(){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), OnboardingProfileSetupFragment.class, args);
}
private class SuggestionsAdapter extends UsableRecyclerView.Adapter<SuggestionViewHolder> implements ImageLoaderRecyclerAdapter{
public SuggestionsAdapter(){
super(imgLoader);
}
@NonNull
@Override
public SuggestionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
return new SuggestionViewHolder();
}
@Override
public int getItemCount(){
return data.size();
}
@Override
public void onBindViewHolder(SuggestionViewHolder holder, int position){
holder.bind(data.get(position));
super.onBindViewHolder(holder, position);
}
@Override
public int getImageCountForItem(int position){
return data.get(position).emojiHelper.getImageCount()+1;
}
@Override
public ImageLoaderRequest getImageRequest(int position, int image){
ParsedAccount account=data.get(position);
if(image==0)
return account.avatarRequest;
return account.emojiHelper.getImageRequest(image-1);
}
}
private class SuggestionViewHolder extends BindableViewHolder<ParsedAccount> implements ImageLoaderViewHolder, UsableRecyclerView.Clickable{
private final TextView name, username, bio;
private final ImageView avatar;
private final ProgressBarButton actionButton;
private final ProgressBar actionProgress;
private final View actionWrap;
private Relationship relationship;
public SuggestionViewHolder(){
super(getActivity(), R.layout.item_user_row_m3, list);
name=findViewById(R.id.name);
username=findViewById(R.id.username);
bio=findViewById(R.id.bio);
avatar=findViewById(R.id.avatar);
actionButton=findViewById(R.id.action_btn);
actionProgress=findViewById(R.id.action_progress);
actionWrap=findViewById(R.id.action_btn_wrap);
avatar.setOutlineProvider(OutlineProviders.roundedRect(10));
avatar.setClipToOutline(true);
actionButton.setOnClickListener(UiUtils.rateLimitedClickListener(this::onActionButtonClick));
}
@Override
public void onBind(ParsedAccount item){
name.setText(item.parsedName);
username.setText(item.account.getDisplayUsername());
if(TextUtils.isEmpty(item.parsedBio)){
bio.setVisibility(View.GONE);
}else{
bio.setVisibility(View.VISIBLE);
bio.setText(item.parsedBio);
}
relationship=relationships.get(item.account.id);
if(relationship==null){
actionWrap.setVisibility(View.GONE);
}else{
actionWrap.setVisibility(View.VISIBLE);
UiUtils.setRelationshipToActionButtonM3(relationship, actionButton);
}
}
@Override
public void setImage(int index, Drawable image){
if(index==0){
avatar.setImageDrawable(image);
}else{
item.emojiHelper.setImageDrawable(index-1, image);
name.invalidate();
bio.invalidate();
}
if(image instanceof Animatable a && !a.isRunning())
a.start();
}
@Override
public void clearImage(int index){
setImage(index, null);
}
@Override
public void onClick(){
Bundle args=new Bundle();
args.putString("account", accountID);
args.putParcelable("profileAccount", Parcels.wrap(item.account));
Nav.go(getActivity(), ProfileFragment.class, args);
}
private void onActionButtonClick(View v){
itemView.setHasTransientState(true);
UiUtils.performAccountAction(getActivity(), item.account, accountID, relationship, actionButton, this::setActionProgressVisible, rel->{
itemView.setHasTransientState(false);
relationships.put(item.account.id, rel);
rebind();
});
}
private void setActionProgressVisible(boolean visible){
actionButton.setTextVisible(!visible);
actionProgress.setVisibility(visible ? View.VISIBLE : View.GONE);
actionButton.setClickable(!visible);
}
}
}

View File

@@ -0,0 +1,229 @@
package org.joinmastodon.android.fragments.onboarding;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ScrollView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.UpdateAccountCredentials;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.HomeFragment;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.AccountField;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ReorderableLinearLayout;
import org.joinmastodon.android.utils.ElevationOnScrollListener;
import java.util.ArrayList;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.ToolbarFragment;
import me.grishka.appkit.imageloader.ViewImageLoader;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
public class OnboardingProfileSetupFragment extends ToolbarFragment implements ReorderableLinearLayout.OnDragListener{
private Button btn;
private View buttonBar;
private String accountID;
private ElevationOnScrollListener onScrollListener;
private ScrollView scroller;
private EditText nameEdit, bioEdit;
private ImageView avaImage, coverImage;
private Button addRow;
private ReorderableLinearLayout profileFieldsLayout;
private Uri avatarUri, coverUri;
private static final int AVATAR_RESULT=348;
private static final int COVER_RESULT=183;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public void onAttach(Activity activity){
super.onAttach(activity);
setNavigationBarColor(UiUtils.getThemeColor(activity, R.attr.colorWindowBackground));
accountID=getArguments().getString("account");
setTitle(R.string.profile_setup);
}
@Override
public View onCreateContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
View view=inflater.inflate(R.layout.fragment_onboarding_profile_setup, container, false);
scroller=view.findViewById(R.id.scroller);
nameEdit=view.findViewById(R.id.display_name);
bioEdit=view.findViewById(R.id.bio);
avaImage=view.findViewById(R.id.avatar);
coverImage=view.findViewById(R.id.header);
addRow=view.findViewById(R.id.add_row);
profileFieldsLayout=view.findViewById(R.id.profile_fields);
btn=view.findViewById(R.id.btn_next);
btn.setOnClickListener(v->onButtonClick());
buttonBar=view.findViewById(R.id.button_bar);
avaImage.setOutlineProvider(OutlineProviders.roundedRect(24));
avaImage.setClipToOutline(true);
Account account=AccountSessionManager.getInstance().getAccount(accountID).self;
if(savedInstanceState==null){
nameEdit.setText(account.displayName);
makeFieldsRow();
}else{
ArrayList<String> fieldTitles=savedInstanceState.getStringArrayList("fieldTitles");
ArrayList<String> fieldValues=savedInstanceState.getStringArrayList("fieldValues");
for(int i=0;i<fieldTitles.size();i++){
View row=makeFieldsRow();
EditText title=row.findViewById(R.id.title);
EditText content=row.findViewById(R.id.content);
title.setText(fieldTitles.get(i));
content.setText(fieldValues.get(i));
}
if(fieldTitles.size()==4)
addRow.setVisibility(View.GONE);
}
addRow.setOnClickListener(v->{
makeFieldsRow();
if(profileFieldsLayout.getChildCount()==4){
addRow.setVisibility(View.GONE);
}
});
profileFieldsLayout.setDragListener(this);
avaImage.setOnClickListener(v->startActivityForResult(UiUtils.getMediaPickerIntent(new String[]{"image/*"}, 1), AVATAR_RESULT));
coverImage.setOnClickListener(v->startActivityForResult(UiUtils.getMediaPickerIntent(new String[]{"image/*"}, 1), COVER_RESULT));
return view;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
scroller.setOnScrollChangeListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
}
@Override
protected void onUpdateToolbar(){
super.onUpdateToolbar();
getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
getToolbar().setElevation(0);
if(onScrollListener!=null){
onScrollListener.setViews(buttonBar, getToolbar());
}
}
protected void onButtonClick(){
ArrayList<AccountField> fields=new ArrayList<>();
for(int i=0;i<profileFieldsLayout.getChildCount();i++){
View row=profileFieldsLayout.getChildAt(i);
EditText title=row.findViewById(R.id.title);
EditText content=row.findViewById(R.id.content);
AccountField fld=new AccountField();
fld.name=title.getText().toString();
fld.value=content.getText().toString();
fields.add(fld);
}
new UpdateAccountCredentials(nameEdit.getText().toString(), bioEdit.getText().toString(), avatarUri, coverUri, fields)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Account result){
AccountSessionManager.getInstance().updateAccountInfo(accountID, result);
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.goClearingStack(getActivity(), HomeFragment.class, args);
}
@Override
public void onError(ErrorResponse error){
error.showToast(getActivity());
}
})
.wrapProgress(getActivity(), R.string.saving, true)
.exec(accountID);
}
@Override
public void onApplyWindowInsets(WindowInsets insets){
if(Build.VERSION.SDK_INT>=27){
int inset=insets.getSystemWindowInsetBottom();
buttonBar.setPadding(0, 0, 0, inset>0 ? Math.max(inset, V.dp(36)) : 0);
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), 0));
}else{
super.onApplyWindowInsets(insets.replaceSystemWindowInsets(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(), insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom()));
}
}
private View makeFieldsRow(){
View view=LayoutInflater.from(getActivity()).inflate(R.layout.onboarding_profile_field, profileFieldsLayout, false);
profileFieldsLayout.addView(view);
view.findViewById(R.id.dragger_thingy).setOnLongClickListener(v->{
profileFieldsLayout.startDragging(view);
return true;
});
view.findViewById(R.id.delete).setOnClickListener(v->{
profileFieldsLayout.removeView(view);
if(addRow.getVisibility()==View.GONE)
addRow.setVisibility(View.VISIBLE);
});
return view;
}
@Override
public void onSwapItems(int oldIndex, int newIndex){}
@Override
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
ArrayList<String> fieldTitles=new ArrayList<>(), fieldValues=new ArrayList<>();
for(int i=0;i<profileFieldsLayout.getChildCount();i++){
View row=profileFieldsLayout.getChildAt(i);
EditText title=row.findViewById(R.id.title);
EditText content=row.findViewById(R.id.content);
fieldTitles.add(title.getText().toString());
fieldValues.add(content.getText().toString());
}
outState.putStringArrayList("fieldTitles", fieldTitles);
outState.putStringArrayList("fieldValues", fieldValues);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
if(resultCode!=Activity.RESULT_OK)
return;
ImageView img;
Uri uri=data.getData();
int size;
if(requestCode==AVATAR_RESULT){
img=avaImage;
avatarUri=uri;
size=V.dp(100);
}else{
img=coverImage;
coverUri=uri;
size=V.dp(1000);
}
img.setForeground(null);
ViewImageLoader.load(img, null, new UrlImageLoaderRequest(uri, size, size));
}
}

View File

@@ -1,14 +1,18 @@
package org.joinmastodon.android.fragments.onboarding;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.Html;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -16,11 +20,9 @@ import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.api.MastodonDetailedErrorResponse;
import org.joinmastodon.android.api.requests.accounts.RegisterAccount;
import org.joinmastodon.android.api.requests.oauth.CreateOAuthApp;
@@ -31,18 +33,22 @@ import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Application;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Token;
import org.joinmastodon.android.ui.text.LinkSpan;
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.FloatingHintEditTextLayout;
import org.joinmastodon.android.utils.ElevationOnScrollListener;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.NodeVisitor;
import org.parceler.Parcels;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import androidx.annotation.Nullable;
@@ -51,12 +57,10 @@ import me.grishka.appkit.api.APIRequest;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.fragments.ToolbarFragment;
import me.grishka.appkit.imageloader.ViewImageLoader;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.FragmentRootLinearLayout;
public class SignupFragment extends ToolbarFragment{
private static final int AVATAR_RESULT=198;
private static final String TAG="SignupFragment";
private Instance instance;
@@ -73,6 +77,7 @@ public class SignupFragment extends ToolbarFragment{
private boolean submitAfterGettingToken;
private ProgressDialog progressDialog;
private HashSet<EditText> errorFields=new HashSet<>();
private ElevationOnScrollListener onScrollListener;
@Override
public void onCreate(Bundle savedInstanceState){
@@ -145,19 +150,22 @@ public class SignupFragment extends ToolbarFragment{
super.onViewCreated(view, savedInstanceState);
setStatusBarColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
view.setBackgroundColor(UiUtils.getThemeColor(getActivity(), R.attr.colorM3Background));
view.findViewById(R.id.scroller).setOnScrollChangeListener(onScrollListener=new ElevationOnScrollListener((FragmentRootLinearLayout) view, buttonBar, getToolbar()));
}
@Override
protected void onUpdateToolbar(){
super.onUpdateToolbar();
getToolbar().setBackground(null);
getToolbar().setBackgroundResource(R.drawable.bg_onboarding_panel);
getToolbar().setElevation(0);
if(onScrollListener!=null){
onScrollListener.setViews(buttonBar, getToolbar());
}
}
private void onButtonClick(){
if(!password.getText().toString().equals(passwordConfirm.getText().toString())){
passwordConfirm.setError(getString(R.string.signup_passwords_dont_match));
passwordConfirmWrap.setErrorState();
passwordConfirmWrap.setErrorState(getString(R.string.signup_passwords_dont_match));
return;
}
showProgressDialog();
@@ -212,8 +220,22 @@ public class SignupFragment extends ToolbarFragment{
anyFieldsSkipped=true;
continue;
}
field.setError(fieldErrors.get(fieldName).stream().map(err->err.description).collect(Collectors.joining("\n")));
getFieldWrapByName(fieldName).setErrorState();
List<MastodonDetailedErrorResponse.FieldError> errors=Objects.requireNonNull(fieldErrors.get(fieldName));
if(errors.size()==1){
getFieldWrapByName(fieldName).setErrorState(getErrorDescription(errors.get(0), fieldName));
}else{
SpannableStringBuilder ssb=new SpannableStringBuilder();
boolean firstErr=true;
for(MastodonDetailedErrorResponse.FieldError err:errors){
if(firstErr){
firstErr=false;
}else{
ssb.append('\n');
}
ssb.append(getErrorDescription(err, fieldName));
}
getFieldWrapByName(fieldName).setErrorState(getErrorDescription(errors.get(0), fieldName));
}
errorFields.add(field);
if(first){
first=false;
@@ -231,6 +253,40 @@ public class SignupFragment extends ToolbarFragment{
.exec(instance.uri, apiToken);
}
private CharSequence getErrorDescription(MastodonDetailedErrorResponse.FieldError error, String fieldName){
return switch(fieldName){
case "email" -> switch(error.error){
case "ERR_BLOCKED" -> {
String emailAddr=email.getText().toString();
String s=getResources().getString(R.string.signup_email_domain_blocked, TextUtils.htmlEncode(instance.uri), TextUtils.htmlEncode(emailAddr.substring(emailAddr.lastIndexOf('@')+1)));
SpannableStringBuilder ssb=new SpannableStringBuilder();
Jsoup.parseBodyFragment(s).body().traverse(new NodeVisitor(){
private int spanStart;
@Override
public void head(Node node, int depth){
if(node instanceof TextNode tn){
ssb.append(tn.text());
}else if(node instanceof Element){
spanStart=ssb.length();
}
}
@Override
public void tail(Node node, int depth){
if(node instanceof Element){
ssb.setSpan(new LinkSpan("", SignupFragment.this::onGoBackLinkClick, LinkSpan.Type.CUSTOM, null), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new TypefaceSpan("sans-serif-medium"), spanStart, ssb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
});
yield ssb;
}
default -> error.description;
};
default -> error.description;
};
}
private EditText getFieldByName(String name){
return switch(name){
case "email" -> email;
@@ -323,6 +379,11 @@ public class SignupFragment extends ToolbarFragment{
}
}
private void onGoBackLinkClick(LinkSpan span){
setResult(false, null);
Nav.finish(this);
}
private class ErrorClearingListener implements TextWatcher{
public final EditText editText;

View File

@@ -25,7 +25,6 @@ import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.displayitems.AudioStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ImageStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.LinkCardStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ReblogOrReplyLineStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
@@ -131,22 +130,7 @@ public class ReportAddPostsChoiceFragment extends StatusListFragment{
if(holder.getAbsoluteAdapterPosition()==0)
return;
outRect.left=V.dp(40);
if(holder instanceof ImageStatusDisplayItem.Holder<?> imgHolder){
PhotoLayoutHelper.TiledLayoutResult layout=imgHolder.getItem().tiledLayout;
PhotoLayoutHelper.TiledLayoutResult.Tile tile=imgHolder.getItem().thisTile;
String siblingID;
if(holder.getAbsoluteAdapterPosition()<parent.getAdapter().getItemCount()-1){
siblingID=displayItems.get(holder.getAbsoluteAdapterPosition()-getMainAdapterOffset()+1).parentID;
}else{
siblingID=null;
}
if(tile.startCol>0)
outRect.left=0;
outRect.left+=V.dp(16);
outRect.right=V.dp(16);
if(!imgHolder.getItemID().equals(siblingID) || tile.startRow+tile.rowSpan==layout.rowSizes.length)
outRect.bottom=V.dp(16);
}else if(holder instanceof AudioStatusDisplayItem.Holder){
if(holder instanceof AudioStatusDisplayItem.Holder){
outRect.bottom=V.dp(16);
}else if(holder instanceof LinkCardStatusDisplayItem.Holder){
outRect.bottom=V.dp(16);
@@ -165,10 +149,6 @@ public class ReportAddPostsChoiceFragment extends StatusListFragment{
parent.getDecoratedBoundsWithMargins(child, tmpRect);
String id=sdiHolder.getItemID();
int height=tmpRect.height();
if(holder instanceof ImageStatusDisplayItem.Holder<?> imgHolder){
if(imgHolder.getItem().thisTile.startCol+imgHolder.getItem().thisTile.colSpan<imgHolder.getItem().tiledLayout.columnSizes.length)
height=0;
}
if(!(holder instanceof HeaderStatusDisplayItem.Holder) && !(holder instanceof ReblogOrReplyLineStatusDisplayItem.Holder))
postsWithKnownNonHeaderHeights.add(id);
knownDisplayItemHeights.put(holder.getAbsoluteAdapterPosition(), height);
@@ -235,17 +215,6 @@ public class ReportAddPostsChoiceFragment extends StatusListFragment{
return adapter;
}
@Override
protected List<StatusDisplayItem> buildDisplayItems(Status s){
List<StatusDisplayItem> items=StatusDisplayItem.buildItems(this, s, accountID, s, knownAccounts, true, false);
for(StatusDisplayItem item:items){
if(item instanceof ImageStatusDisplayItem isdi){
isdi.horizontalInset=V.dp(40+32);
}
}
return items;
}
protected void drawDivider(View child, View bottomSibling, RecyclerView.ViewHolder holder, RecyclerView.ViewHolder siblingHolder, RecyclerView parent, Canvas c, Paint paint){
parent.getDecoratedBoundsWithMargins(child, tmpRect);
tmpRect.offset(0, Math.round(child.getTranslationY()));

View File

@@ -45,26 +45,26 @@ public class Attachment extends BaseModel{
public int getWidth(){
if(meta==null)
return 0;
return 1920;
if(meta.width>0)
return meta.width;
if(meta.original!=null && meta.original.width>0)
return meta.original.width;
if(meta.small!=null && meta.small.width>0)
return meta.small.width;
return 0;
return 1920;
}
public int getHeight(){
if(meta==null)
return 0;
return 1080;
if(meta.height>0)
return meta.height;
if(meta.original!=null && meta.original.height>0)
return meta.original.height;
if(meta.small!=null && meta.small.height>0)
return meta.small.height;
return 0;
return 1080;
}
public double getDuration(){

View File

@@ -45,7 +45,7 @@ public class Instance extends BaseModel{
@RequiredField
public String version;
/**
* Primary langauges of the website and its staff.
* Primary languages of the website and its staff.
*/
// @RequiredField
public List<String> languages;

View File

@@ -0,0 +1,33 @@
package org.joinmastodon.android.model;
import android.text.SpannableStringBuilder;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
import java.util.Collections;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.V;
public class ParsedAccount{
public Account account;
public CharSequence parsedName, parsedBio;
public CustomEmojiHelper emojiHelper;
public ImageLoaderRequest avatarRequest;
public ParsedAccount(Account account, String accountID){
this.account=account;
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
emojiHelper=new CustomEmojiHelper();
SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName);
ssb.append(parsedBio);
emojiHelper.setText(ssb);
avatarRequest=new UrlImageLoaderRequest(GlobalUserPreferences.playGifs ? account.avatar : account.avatarStatic, V.dp(40), V.dp(40));
}
}

View File

@@ -16,6 +16,7 @@ public class Poll extends BaseModel{
private boolean expired;
public boolean multiple;
public int votersCount;
public int votesCount;
public boolean voted;
@RequiredField
public List<Integer> ownVotes;
@@ -41,10 +42,12 @@ public class Poll extends BaseModel{
", expired="+expired+
", multiple="+multiple+
", votersCount="+votersCount+
", votesCount="+votesCount+
", voted="+voted+
", ownVotes="+ownVotes+
", options="+options+
", emojis="+emojis+
", selectedOptions="+selectedOptions+
'}';
}

View File

@@ -18,6 +18,10 @@ public class Relationship extends BaseModel{
public boolean blockedBy;
public String note;
public boolean canFollow(){
return !(following || blocking || blockedBy || domainBlocking);
}
@Override
public String toString(){
return "Relationship{"+

View File

@@ -1,17 +1,25 @@
package org.joinmastodon.android.ui;
import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.PathInterpolator;
import java.util.ArrayList;
public class InterpolatingMotionEffect implements SensorEventListener{
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.FloatValueHolder;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
public class InterpolatingMotionEffect implements SensorEventListener, View.OnTouchListener{
private SensorManager sm;
private WindowManager wm;
@@ -20,6 +28,34 @@ public class InterpolatingMotionEffect implements SensorEventListener{
private Sensor accelerometer;
private boolean accelerometerEnabled;
private ArrayList<ViewEffect> views=new ArrayList<>();
private float pitch, roll;
private float touchDownX, touchDownY, touchAddX, touchAddY, touchAddLastAnimX, touchAddLastAnimY;
private PathInterpolator touchInterpolator=new PathInterpolator(0.5f, 1f, 0.89f, 1f);
private SpringAnimation touchSpringX, touchSpringY;
private FloatValueHolder touchSpringXHolder=new FloatValueHolder(){
@Override
public float getValue(){
return touchAddX;
}
@Override
public void setValue(float value){
touchAddX=value;
updateEffects();
}
};
private FloatValueHolder touchSpringYHolder=new FloatValueHolder(){
@Override
public float getValue(){
return touchAddY;
}
@Override
public void setValue(float value){
touchAddY=value;
updateEffects();
}
};
public InterpolatingMotionEffect(Context context){
sm=context.getSystemService(SensorManager.class);
@@ -50,8 +86,8 @@ public class InterpolatingMotionEffect implements SensorEventListener{
float z=event.values[2]/SensorManager.GRAVITY_EARTH;
float pitch=(float) (Math.atan2(x, Math.sqrt(y*y+z*z))/Math.PI*2.0);
float roll=(float) (Math.atan2(y, Math.sqrt(x*x+z*z))/Math.PI*2.0);
pitch=(float) (Math.atan2(x, Math.sqrt(y*y+z*z))/Math.PI*2.0);
roll=(float) (Math.atan2(y, Math.sqrt(x*x+z*z))/Math.PI*2.0);
switch(rotation){
case Surface.ROTATION_0:
@@ -88,9 +124,7 @@ public class InterpolatingMotionEffect implements SensorEventListener{
}else if(roll<-1f){
roll=-2f-roll;
}
for(ViewEffect view:views){
view.update(pitch, roll);
}
updateEffects();
}
@Override
@@ -110,6 +144,62 @@ public class InterpolatingMotionEffect implements SensorEventListener{
views.clear();
}
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouch(View v, MotionEvent ev){
switch(ev.getAction()){
case MotionEvent.ACTION_DOWN -> {
if(touchSpringX!=null){
touchAddLastAnimX=touchAddX;
touchSpringX.cancel();
touchSpringX=null;
}else{
touchAddLastAnimX=0;
}
if(touchSpringY!=null){
touchAddLastAnimY=touchAddY;
touchSpringY.cancel();
touchSpringY=null;
}else{
touchAddLastAnimY=0;
}
touchDownX=ev.getX();
touchDownY=ev.getY();
}
case MotionEvent.ACTION_MOVE -> {
touchAddX=touchInterpolator.getInterpolation(Math.min(1f, Math.abs((ev.getX()-touchDownX)/(v.getWidth()/2f))));
touchAddY=touchInterpolator.getInterpolation(Math.min(1f, Math.abs((ev.getY()-touchDownY)/(v.getHeight()/2f))));
if(ev.getX()>touchDownX)
touchAddX=-touchAddX;
if(ev.getY()<touchDownY)
touchAddY=-touchAddY;
touchAddX+=touchAddLastAnimX;
touchAddY+=touchAddLastAnimY;
updateEffects();
}
case MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
touchSpringX=new SpringAnimation(touchSpringXHolder, 0f);
touchSpringX.setMinimumVisibleChange(0.01f);
touchSpringX.getSpring().setStiffness(SpringForce.STIFFNESS_LOW).setDampingRatio(0.85f);
touchSpringX.addEndListener((animation, canceled, value, velocity)->touchSpringX=null);
touchSpringX.start();
touchSpringY=new SpringAnimation(touchSpringYHolder, 0f);
touchSpringY.setMinimumVisibleChange(0.01f);
touchSpringY.getSpring().setStiffness(SpringForce.STIFFNESS_LOW).setDampingRatio(0.85f);
touchSpringY.addEndListener((animation, canceled, value, velocity)->touchSpringY=null);
touchSpringY.start();
updateEffects();
}
}
return true;
}
private void updateEffects(){
for(ViewEffect view:views){
view.update(Math.min(1f, Math.max(-1f, pitch+touchAddX)), Math.min(1f, Math.max(-1f, roll+touchAddY)));
}
}
public static class ViewEffect{
private View view;
private float minX, maxX, minY, maxY;

View File

@@ -11,8 +11,14 @@ import java.util.List;
import androidx.annotation.NonNull;
public class PhotoLayoutHelper{
public static final int MAX_WIDTH=1000;
public static final int MAX_HEIGHT=1910;
@NonNull
public static TiledLayoutResult processThumbs(int _maxW, int _maxH, List<Attachment> thumbs){
public static TiledLayoutResult processThumbs(List<Attachment> thumbs){
int _maxW=MAX_WIDTH;
int _maxH=MAX_HEIGHT;
TiledLayoutResult result=new TiledLayoutResult();
if(thumbs.size()==1){
Attachment att=thumbs.get(0);
@@ -45,13 +51,8 @@ public class PhotoLayoutHelper{
float avgRatio=!ratios.isEmpty() ? sum(ratios)/ratios.size() : 1.0f;
float maxW, maxH, marginW=0, marginH=0;
if(_maxW>0){
maxW=_maxW;
maxH=_maxH;
}else{
maxW=510;
maxH=510;
}
maxW=_maxW;
maxH=_maxH;
float maxRatio=maxW/maxH;

View File

@@ -1,42 +0,0 @@
package org.joinmastodon.android.ui.displayitems;
import android.app.Activity;
import android.graphics.Outline;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.PhotoLayoutHelper;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
public class GifVStatusDisplayItem extends ImageStatusDisplayItem{
public GifVStatusDisplayItem(String parentID, Status status, Attachment attachment, BaseStatusListFragment parentFragment, int index, int totalPhotos, PhotoLayoutHelper.TiledLayoutResult tiledLayout, PhotoLayoutHelper.TiledLayoutResult.Tile thisTile){
super(parentID, parentFragment, attachment, status, index, totalPhotos, tiledLayout, thisTile);
request=new UrlImageLoaderRequest(attachment.previewUrl, 1000, 1000);
}
@Override
public Type getType(){
return Type.GIFV;
}
public static class Holder extends ImageStatusDisplayItem.Holder<GifVStatusDisplayItem>{
public Holder(Activity activity, ViewGroup parent){
super(activity, R.layout.display_item_gifv, parent);
View play=findViewById(R.id.play_button);
play.setOutlineProvider(new ViewOutlineProvider(){
@Override
public void getOutline(View view, Outline outline){
outline.setOval(0, 0, view.getWidth(), view.getHeight());
outline.setAlpha(.99f); // fixes shadow rendering
}
});
}
}
}

View File

@@ -189,7 +189,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
progress.dismiss();
}, rel->{
relationship=rel;
Toast.makeText(activity, activity.getString(rel.following ? R.string.followed_user : R.string.unfollowed_user, account.getDisplayUsername()), Toast.LENGTH_SHORT).show();
Toast.makeText(activity, activity.getString(rel.following ? R.string.followed_user : rel.requested ? R.string.following_user_requested : R.string.unfollowed_user, account.getDisplayUsername()), Toast.LENGTH_SHORT).show();
});
}else if(id==R.id.block_domain){
UiUtils.confirmToggleBlockDomain(activity, item.parentFragment.getAccountID(), account.getDomain(), relationship!=null && relationship.domainBlocking, ()->{});

View File

@@ -1,105 +0,0 @@
package org.joinmastodon.android.ui.displayitems;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.drawables.BlurhashCrossfadeDrawable;
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
import org.joinmastodon.android.ui.views.ImageAttachmentFrameLayout;
import androidx.annotation.LayoutRes;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
public abstract class ImageStatusDisplayItem extends StatusDisplayItem{
public final int index;
public final int totalPhotos;
protected Attachment attachment;
protected ImageLoaderRequest request;
public final Status status;
public final PhotoLayoutHelper.TiledLayoutResult tiledLayout;
public final PhotoLayoutHelper.TiledLayoutResult.Tile thisTile;
public int horizontalInset;
public ImageStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Attachment photo, Status status, int index, int totalPhotos, PhotoLayoutHelper.TiledLayoutResult tiledLayout, PhotoLayoutHelper.TiledLayoutResult.Tile thisTile){
super(parentID, parentFragment);
this.attachment=photo;
this.status=status;
this.index=index;
this.totalPhotos=totalPhotos;
this.tiledLayout=tiledLayout;
this.thisTile=thisTile;
}
@Override
public int getImageCount(){
return 1;
}
@Override
public ImageLoaderRequest getImageRequest(int index){
return request;
}
public static abstract class Holder<T extends ImageStatusDisplayItem> extends StatusDisplayItem.Holder<T> implements ImageLoaderViewHolder{
public final ImageView photo;
private ImageAttachmentFrameLayout layout;
private BlurhashCrossfadeDrawable crossfadeDrawable=new BlurhashCrossfadeDrawable();
private boolean didClear;
public Holder(Activity activity, @LayoutRes int layout, ViewGroup parent){
super(activity, layout, parent);
photo=findViewById(R.id.photo);
photo.setOnClickListener(this::onViewClick);
this.layout=(ImageAttachmentFrameLayout)itemView;
}
@Override
public void onBind(ImageStatusDisplayItem item){
layout.setLayout(item.tiledLayout, item.thisTile, item.horizontalInset);
crossfadeDrawable.setSize(item.attachment.getWidth(), item.attachment.getHeight());
crossfadeDrawable.setBlurhashDrawable(item.attachment.blurhashPlaceholder);
crossfadeDrawable.setCrossfadeAlpha(item.status.spoilerRevealed ? 0f : 1f);
photo.setImageDrawable(null);
photo.setImageDrawable(crossfadeDrawable);
photo.setContentDescription(TextUtils.isEmpty(item.attachment.description) ? item.parentFragment.getString(R.string.media_no_description) : item.attachment.description);
didClear=false;
}
@Override
public void setImage(int index, Drawable drawable){
crossfadeDrawable.setImageDrawable(drawable);
if(didClear && item.status.spoilerRevealed)
crossfadeDrawable.animateAlpha(0f);
}
@Override
public void clearImage(int index){
crossfadeDrawable.setCrossfadeAlpha(1f);
crossfadeDrawable.setImageDrawable(null);
didClear=true;
}
private void onViewClick(View v){
if(!item.status.spoilerRevealed){
item.parentFragment.onRevealSpoilerClick(this);
}else if(item.parentFragment instanceof PhotoViewerHost){
Status contentStatus=item.status.reblog!=null ? item.status.reblog : item.status;
((PhotoViewerHost) item.parentFragment).openPhotoViewer(item.parentID, item.status, contentStatus.mediaAttachments.indexOf(item.attachment));
}
}
public void setRevealed(boolean revealed){
crossfadeDrawable.animateAlpha(revealed ? 0f : 1f);
}
}
}

View File

@@ -0,0 +1,295 @@
package org.joinmastodon.android.ui.displayitems;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.photoviewer.PhotoViewerHost;
import org.joinmastodon.android.ui.utils.MediaAttachmentViewController;
import org.joinmastodon.android.ui.views.FrameLayoutThatOnlyMeasuresFirstChild;
import org.joinmastodon.android.ui.views.MediaGridLayout;
import org.joinmastodon.android.utils.TypedObjectPool;
import java.util.ArrayList;
import java.util.List;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
import me.grishka.appkit.utils.CubicBezierInterpolator;
public class MediaGridStatusDisplayItem extends StatusDisplayItem{
private static final String TAG="MediaGridDisplayItem";
private final PhotoLayoutHelper.TiledLayoutResult tiledLayout;
private final TypedObjectPool<GridItemType, MediaAttachmentViewController> viewPool;
private final List<Attachment> attachments;
private final ArrayList<ImageLoaderRequest> requests=new ArrayList<>();
public final Status status;
public MediaGridStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, PhotoLayoutHelper.TiledLayoutResult tiledLayout, List<Attachment> attachments, Status status){
super(parentID, parentFragment);
this.tiledLayout=tiledLayout;
this.viewPool=parentFragment.getAttachmentViewsPool();
this.attachments=attachments;
this.status=status;
for(Attachment att:attachments){
requests.add(new UrlImageLoaderRequest(switch(att.type){
case IMAGE -> att.url;
case VIDEO, GIFV -> att.previewUrl;
default -> throw new IllegalStateException("Unexpected value: "+att.type);
}, 1000, 1000));
}
}
@Override
public Type getType(){
return Type.MEDIA_GRID;
}
@Override
public int getImageCount(){
return requests.size();
}
@Override
public ImageLoaderRequest getImageRequest(int index){
return requests.get(index);
}
public enum GridItemType{
PHOTO,
VIDEO,
GIFV
}
public static class Holder extends StatusDisplayItem.Holder<MediaGridStatusDisplayItem> implements ImageLoaderViewHolder{
private final FrameLayout wrapper;
private final MediaGridLayout layout;
private final View.OnClickListener clickListener=this::onViewClick, altTextClickListener=this::onAltTextClick;
private final ArrayList<MediaAttachmentViewController> controllers=new ArrayList<>();
private final FrameLayout altTextWrapper;
private final TextView altTextButton;
private final View altTextScroller;
private final ImageButton altTextClose;
private final TextView altText;
private int altTextIndex=-1;
private Animator altTextAnimator;
public Holder(Activity activity, ViewGroup parent){
super(new FrameLayoutThatOnlyMeasuresFirstChild(activity));
wrapper=(FrameLayout)itemView;
layout=new MediaGridLayout(activity);
wrapper.addView(layout);
activity.getLayoutInflater().inflate(R.layout.overlay_image_alt_text, wrapper);
altTextWrapper=findViewById(R.id.alt_text_wrapper);
altTextButton=findViewById(R.id.alt_button);
altTextScroller=findViewById(R.id.alt_text_scroller);
altTextClose=findViewById(R.id.alt_text_close);
altText=findViewById(R.id.alt_text);
altTextClose.setOnClickListener(this::onAltTextCloseClick);
}
@Override
public void onBind(MediaGridStatusDisplayItem item){
if(altTextAnimator!=null)
altTextAnimator.cancel();
layout.setTiledLayout(item.tiledLayout);
for(MediaAttachmentViewController c:controllers){
item.viewPool.reuse(c.type, c);
}
layout.removeAllViews();
controllers.clear();
int i=0;
for(Attachment att:item.attachments){
MediaAttachmentViewController c=item.viewPool.obtain(switch(att.type){
case IMAGE -> GridItemType.PHOTO;
case VIDEO -> GridItemType.VIDEO;
case GIFV -> GridItemType.GIFV;
default -> throw new IllegalStateException("Unexpected value: "+att.type);
});
if(c.view.getLayoutParams()==null)
c.view.setLayoutParams(new MediaGridLayout.LayoutParams(item.tiledLayout.tiles[i]));
else
((MediaGridLayout.LayoutParams) c.view.getLayoutParams()).tile=item.tiledLayout.tiles[i];
layout.addView(c.view);
c.view.setOnClickListener(clickListener);
c.view.setTag(i);
if(c.altButton!=null){
c.altButton.setOnClickListener(altTextClickListener);
c.altButton.setTag(i);
c.altButton.setAlpha(1f);
}
controllers.add(c);
c.bind(att, item.status);
i++;
}
altTextWrapper.setVisibility(View.GONE);
altTextIndex=-1;
}
@Override
public void setImage(int index, Drawable drawable){
controllers.get(index).setImage(drawable);
}
@Override
public void clearImage(int index){
controllers.get(index).clearImage();
}
private void onViewClick(View v){
int index=(Integer)v.getTag();
if(!item.status.spoilerRevealed){
item.parentFragment.onRevealSpoilerClick(this);
}else if(item.parentFragment instanceof PhotoViewerHost){
((PhotoViewerHost) item.parentFragment).openPhotoViewer(item.parentID, item.status, index, this);
}
}
private void onAltTextClick(View v){
if(altTextAnimator!=null)
altTextAnimator.cancel();
v.setVisibility(View.INVISIBLE);
int index=(Integer)v.getTag();
altTextIndex=index;
Attachment att=item.attachments.get(index);
altText.setText(att.description);
altTextWrapper.setVisibility(View.VISIBLE);
altTextWrapper.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
@Override
public boolean onPreDraw(){
altTextWrapper.getViewTreeObserver().removeOnPreDrawListener(this);
int[] loc={0, 0};
v.getLocationInWindow(loc);
int btnL=loc[0], btnT=loc[1];
wrapper.getLocationInWindow(loc);
btnL-=loc[0];
btnT-=loc[1];
ArrayList<Animator> anims=new ArrayList<>();
anims.add(ObjectAnimator.ofFloat(altTextButton, View.ALPHA, 1, 0));
anims.add(ObjectAnimator.ofFloat(altTextScroller, View.ALPHA, 0, 1));
anims.add(ObjectAnimator.ofFloat(altTextClose, View.ALPHA, 0, 1));
anims.add(ObjectAnimator.ofInt(altTextWrapper, "left", btnL, altTextWrapper.getLeft()));
anims.add(ObjectAnimator.ofInt(altTextWrapper, "top", btnT, altTextWrapper.getTop()));
anims.add(ObjectAnimator.ofInt(altTextWrapper, "right", btnL+v.getWidth(), altTextWrapper.getRight()));
anims.add(ObjectAnimator.ofInt(altTextWrapper, "bottom", btnT+v.getHeight(), altTextWrapper.getBottom()));
for(Animator a:anims)
a.setDuration(300);
for(MediaAttachmentViewController c:controllers){
if(c.altButton!=null && c.altButton!=v){
anims.add(ObjectAnimator.ofFloat(c.altButton, View.ALPHA, 1, 0).setDuration(150));
}
}
AnimatorSet set=new AnimatorSet();
set.playTogether(anims);
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
set.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
altTextAnimator=null;
for(MediaAttachmentViewController c:controllers){
if(c.altButton!=null){
c.altButton.setVisibility(View.INVISIBLE);
}
}
}
});
altTextAnimator=set;
set.start();
return true;
}
});
}
private void onAltTextCloseClick(View v){
if(altTextAnimator!=null)
altTextAnimator.cancel();
View btn=controllers.get(altTextIndex).altButton;
int i=0;
for(MediaAttachmentViewController c:controllers){
if(c.altButton!=null && c.altButton!=btn && !TextUtils.isEmpty(item.attachments.get(i).description))
c.altButton.setVisibility(View.VISIBLE);
i++;
}
int[] loc={0, 0};
btn.getLocationInWindow(loc);
int btnL=loc[0], btnT=loc[1];
wrapper.getLocationInWindow(loc);
btnL-=loc[0];
btnT-=loc[1];
ArrayList<Animator> anims=new ArrayList<>();
anims.add(ObjectAnimator.ofFloat(altTextButton, View.ALPHA, 1));
anims.add(ObjectAnimator.ofFloat(altTextScroller, View.ALPHA, 0));
anims.add(ObjectAnimator.ofFloat(altTextClose, View.ALPHA, 0));
anims.add(ObjectAnimator.ofInt(altTextWrapper, "left", btnL));
anims.add(ObjectAnimator.ofInt(altTextWrapper, "top", btnT));
anims.add(ObjectAnimator.ofInt(altTextWrapper, "right", btnL+btn.getWidth()));
anims.add(ObjectAnimator.ofInt(altTextWrapper, "bottom", btnT+btn.getHeight()));
for(Animator a:anims)
a.setDuration(300);
for(MediaAttachmentViewController c:controllers){
if(c.altButton!=null && c.altButton!=btn){
anims.add(ObjectAnimator.ofFloat(c.altButton, View.ALPHA, 1).setDuration(150));
}
}
AnimatorSet set=new AnimatorSet();
set.playTogether(anims);
set.setInterpolator(CubicBezierInterpolator.DEFAULT);
set.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
altTextAnimator=null;
altTextWrapper.setVisibility(View.GONE);
btn.setVisibility(View.VISIBLE);
}
});
altTextAnimator=set;
set.start();
}
public void setRevealed(boolean revealed){
for(MediaAttachmentViewController c:controllers){
c.setRevealed(revealed);
}
}
public MediaAttachmentViewController getViewController(int index){
return controllers.get(index);
}
public void setClipChildren(boolean clip){
layout.setClipChildren(clip);
wrapper.setClipChildren(clip);
}
}
}

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