Compare commits

..

136 Commits

Author SHA1 Message Date
sk
9a985aad29 fix deleting boosted posts in profile 2023-10-14 01:47:13 +02:00
sk
42fac30e63 wrap into full-width view 2023-10-13 23:50:49 +02:00
sk
18e7f14c16 remove duplicate selectable background 2023-10-13 23:49:54 +02:00
sk
7b263800a6 reduce button margins, realign buttons
closes sk22#
2023-10-13 23:27:49 +02:00
sk
17387a32b2 don't scale buttons with text
re: sk22#787
2023-10-13 23:04:45 +02:00
sk
3fe642c2f2 remove unwanted margin 2023-10-13 22:36:15 +02:00
sk
9225447409 use action bar icons color for toolbar
closes sk22#860
2023-10-13 22:27:53 +02:00
sk
db661b56cb fix inconsistent styles, fix non-sp font
closes sk22#862
2023-10-13 22:17:45 +02:00
sk
638e1bf8e9 do show labels per default
This reverts commit a1c81e89e8.
2023-10-13 21:16:52 +02:00
sk
83786171a7 ellipsize tab bar labels 2023-10-13 13:49:54 +02:00
sk
f638a538c1 Merge remote-tracking branch 'upstream/l10n_master' 2023-10-13 13:45:36 +02:00
sk22
11e2316cbc Translated using Weblate (German)
Currently translated at 100.0% (393 of 393 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-10-13 11:45:15 +00:00
ihor_ck
1b372c7dca Translated using Weblate (Ukrainian)
Currently translated at 100.0% (390 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-13 11:43:24 +00:00
ihor_ck
cf4e37fade Translated using Weblate (Ukrainian)
Currently translated at 100.0% (390 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-13 11:43:24 +00:00
SomeTr
f3fc60ac00 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (390 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-13 11:43:24 +00:00
butterflyoffire
1026d99025 Translated using Weblate (Arabic)
Currently translated at 81.2% (317 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ar/
2023-10-13 11:43:24 +00:00
ihor_ck
3fb947fbfe Translated using Weblate (Ukrainian)
Currently translated at 100.0% (390 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-13 11:43:24 +00:00
David Lapshin
f097506d49 Translated using Weblate (Russian)
Currently translated at 99.7% (389 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2023-10-13 11:43:24 +00:00
alextecplayz
3df7d74fbf Translated using Weblate (Romanian)
Currently translated at 100.0% (390 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ro/
2023-10-13 11:43:24 +00:00
Oliebol
3fc17eb9c9 Translated using Weblate (Dutch)
Currently translated at 81.0% (316 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/nl/
2023-10-13 11:43:24 +00:00
Linerly
67ee74c1a0 Translated using Weblate (Indonesian)
Currently translated at 100.0% (390 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-10-13 11:43:24 +00:00
Espasant3
bcebba8896 Translated using Weblate (Galician)
Currently translated at 97.9% (382 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/gl/
2023-10-13 11:43:24 +00:00
Choukajohn
451b0c1ac5 Translated using Weblate (French)
Currently translated at 100.0% (390 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-10-13 11:43:24 +00:00
butterflyoffire
5d08b4923b Translated using Weblate (French)
Currently translated at 100.0% (390 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-10-13 11:43:24 +00:00
kallekn
9ba948c721 Translated using Weblate (Finnish)
Currently translated at 100.0% (390 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fi/
2023-10-13 11:43:24 +00:00
gallegonovato
23e7513133 Translated using Weblate (Spanish)
Currently translated at 100.0% (390 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-10-13 11:43:24 +00:00
poesty
aaed8e53c8 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.7% (389 of 390 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-10-13 11:43:24 +00:00
sk
f2754cc5c9 bump version 2023-10-13 13:43:08 +02:00
sk
6a65edd089 fix draft/schedule view for large display sizes
cc @LucasGGamerM
see 77e19b4d6f
2023-10-13 13:39:51 +02:00
LucasGGamerM
4d49b10585 fix(compose): make 'This post will be saved as a draft' view work better on smaller screens
cc: @sk22
2023-10-13 13:27:13 +02:00
sk
86bfab81bd lucas is right
closes sk22#857
2023-10-13 02:27:34 +02:00
sk
50e313cff0 fix gap max_id when post before gap is filtered
hopefully fixes sk22#856
2023-10-13 02:22:03 +02:00
sk
5d07cde6dd fix gap not filtering posts 2023-10-13 01:48:45 +02:00
sk
f84a923102 implement global default color
closes sk22#853
2023-10-13 01:28:59 +02:00
sk
c9eac34ae6 fix gap item alpha not being reset
closes sk22#851
2023-10-13 00:27:35 +02:00
sk
181a0577c8 fix missing gap item when status removed 2023-10-13 00:24:32 +02:00
sk
0426084194 fix changes breaking off-screen bound holders
i hope i didn't break everything lol
2023-10-13 00:14:29 +02:00
Eugen Rochko
197d0caf44 New translations strings.xml (Japanese) 2023-10-11 18:34:49 +02:00
Eugen Rochko
a4a082f76a New translations strings.xml (Japanese) 2023-10-11 17:14:57 +02:00
Eugen Rochko
2528d48010 New translations strings.xml (Icelandic) 2023-10-10 18:10:41 +02:00
Eugen Rochko
5456d71979 New translations strings.xml (Chinese Traditional) 2023-10-10 10:25:33 +02:00
Eugen Rochko
e36aae3cf3 New translations strings.xml (Thai) 2023-10-09 20:31:09 +02:00
Grishka
d6040c0895 Hide the FAB while editing profile 2023-10-09 19:42:54 +02:00
Eugen Rochko
6d12e2dd72 New translations strings.xml (Thai) 2023-10-09 19:20:32 +02:00
sk
ff47e6edba remove unused method 2023-10-09 18:46:52 +02:00
sk
327ceb04d4 fix deleting notifications
closes sk22#677
closes sk22#633
2023-10-09 18:35:27 +02:00
sk
40a34b07de add option to disable underlined links
closes sk22#847
2023-10-09 18:07:19 +02:00
Eugen Rochko
f117249bb5 New translations strings.xml (Thai) 2023-10-09 18:02:31 +02:00
sk
1c90164ece fix broken hashtag links
closes sk22#848
2023-10-09 17:59:22 +02:00
sk
0d5fb250bc migrate theme colors
closes sk22#849
2023-10-09 17:54:54 +02:00
sk
e9bd5a373a remove unused icons and replace some wrong ones 2023-10-09 17:39:18 +02:00
sk
c494d283ba remove duplicate section, replace icons
closes sk22#850
2023-10-09 17:38:55 +02:00
Eugen Rochko
cf1d537367 New translations strings.xml (Vietnamese) 2023-10-09 06:03:28 +02:00
Eugen Rochko
517d13b400 New translations strings.xml (Vietnamese) 2023-10-09 05:07:06 +02:00
Eugen Rochko
fae870c93a New translations strings.xml (Urdu (India)) 2023-10-08 21:13:23 +02:00
Eugen Rochko
f8e00dcc80 New translations strings.xml (Kabyle) 2023-10-08 21:13:22 +02:00
Eugen Rochko
5fdbb597bb New translations strings.xml (Igbo) 2023-10-08 21:13:21 +02:00
Eugen Rochko
d74b286a9d New translations strings.xml (Occitan) 2023-10-08 21:13:20 +02:00
Eugen Rochko
ecb3c521ff New translations strings.xml (Scottish Gaelic) 2023-10-08 21:13:19 +02:00
Eugen Rochko
1d093ce928 New translations strings.xml (Sinhala) 2023-10-08 21:13:18 +02:00
Eugen Rochko
46b711af2e New translations strings.xml (Bosnian) 2023-10-08 21:13:17 +02:00
Eugen Rochko
772e6ddb5d New translations strings.xml (Filipino) 2023-10-08 21:13:16 +02:00
Eugen Rochko
f84e8443d2 New translations strings.xml (Burmese) 2023-10-08 21:13:15 +02:00
Eugen Rochko
250c18ebf1 New translations strings.xml (Hindi) 2023-10-08 21:13:14 +02:00
Eugen Rochko
e3d0f38b79 New translations strings.xml (Croatian) 2023-10-08 21:13:14 +02:00
Eugen Rochko
c512f97783 New translations strings.xml (Bengali) 2023-10-08 21:13:13 +02:00
Eugen Rochko
0594680775 New translations strings.xml (Persian) 2023-10-08 21:13:12 +02:00
Eugen Rochko
f999881f59 New translations strings.xml (Indonesian) 2023-10-08 21:13:11 +02:00
Eugen Rochko
4fe9192ac6 New translations strings.xml (Portuguese, Brazilian) 2023-10-08 21:13:10 +02:00
Eugen Rochko
d936702fa9 New translations strings.xml (Galician) 2023-10-08 21:13:08 +02:00
Eugen Rochko
74e284b0de New translations strings.xml (Vietnamese) 2023-10-08 21:13:07 +02:00
Eugen Rochko
4c42b72ed8 New translations strings.xml (Chinese Simplified) 2023-10-08 21:13:06 +02:00
Eugen Rochko
0e0046df65 New translations strings.xml (Turkish) 2023-10-08 21:13:05 +02:00
Eugen Rochko
c80d1d10c2 New translations strings.xml (Slovenian) 2023-10-08 21:13:05 +02:00
Eugen Rochko
da97971011 New translations strings.xml (Portuguese) 2023-10-08 21:13:04 +02:00
Eugen Rochko
700447dbe7 New translations strings.xml (Polish) 2023-10-08 21:13:03 +02:00
Eugen Rochko
37e7b5ee93 New translations strings.xml (Norwegian) 2023-10-08 21:13:02 +02:00
Eugen Rochko
1265afa93f New translations strings.xml (Dutch) 2023-10-08 21:13:01 +02:00
Eugen Rochko
1e09481b02 New translations strings.xml (Korean) 2023-10-08 21:13:00 +02:00
Eugen Rochko
9996a5a05e New translations strings.xml (Armenian) 2023-10-08 21:12:59 +02:00
Eugen Rochko
f20aac7c81 New translations strings.xml (Hungarian) 2023-10-08 21:12:58 +02:00
Eugen Rochko
98f7b0bacd New translations strings.xml (Hebrew) 2023-10-08 21:12:57 +02:00
Eugen Rochko
3f6d3fb3a2 New translations strings.xml (Irish) 2023-10-08 21:12:56 +02:00
Eugen Rochko
663b49c76b New translations strings.xml (Basque) 2023-10-08 21:12:55 +02:00
Eugen Rochko
16e38f2541 New translations strings.xml (Greek) 2023-10-08 21:12:54 +02:00
Eugen Rochko
842cc55e47 New translations strings.xml (German) 2023-10-08 21:12:53 +02:00
Eugen Rochko
72db099e6f New translations strings.xml (Danish) 2023-10-08 21:12:52 +02:00
Eugen Rochko
be130bc3a7 New translations strings.xml (Czech) 2023-10-08 21:12:51 +02:00
Eugen Rochko
42253336e1 New translations strings.xml (Catalan) 2023-10-08 21:12:50 +02:00
Eugen Rochko
572631e1d7 New translations strings.xml (Belarusian) 2023-10-08 21:12:49 +02:00
Eugen Rochko
723777a800 New translations strings.xml (Arabic) 2023-10-08 21:12:48 +02:00
Eugen Rochko
b825d534c1 New translations strings.xml (Spanish) 2023-10-08 21:12:47 +02:00
Eugen Rochko
b9749620a8 New translations strings.xml (French) 2023-10-08 21:12:46 +02:00
Eugen Rochko
70ea9989aa New translations strings.xml (Romanian) 2023-10-08 21:12:45 +02:00
Eugen Rochko
b3ec9c981c New translations strings.xml (Chinese Traditional) 2023-10-08 21:12:44 +02:00
Eugen Rochko
bf72085abb New translations strings.xml (Finnish) 2023-10-08 21:12:43 +02:00
Eugen Rochko
64dd416b59 New translations strings.xml (Russian) 2023-10-08 21:12:42 +02:00
Eugen Rochko
ab2a920455 New translations strings.xml (Swedish) 2023-10-08 21:12:41 +02:00
Eugen Rochko
7580446d60 New translations strings.xml (Italian) 2023-10-08 21:12:40 +02:00
Eugen Rochko
ade18ac6fc New translations strings.xml (Ukrainian) 2023-10-08 21:12:39 +02:00
Eugen Rochko
005c851d72 New translations strings.xml (Japanese) 2023-10-08 21:12:38 +02:00
Eugen Rochko
0f1d46c765 New translations strings.xml (Icelandic) 2023-10-08 21:12:36 +02:00
Eugen Rochko
21fbb07b1d New translations strings.xml (Thai) 2023-10-08 21:12:36 +02:00
sk
58e0ce3970 add tooltips 2023-10-08 16:36:56 +02:00
sk
139a7d7c98 change settings order 2023-10-08 16:36:48 +02:00
sk
a1c81e89e8 don't show labels per default 2023-10-08 16:36:41 +02:00
sk
a5c197b496 hearts everywhere
closes sk22#846
2023-10-08 13:04:26 +02:00
sk
df49ef9d58 redder red 2023-10-08 12:54:59 +02:00
sk
f747d4c979 toggle label font weight according to m3 2023-10-08 12:49:29 +02:00
sk
98677cd307 on page change listener may also load first page 2023-10-08 11:48:59 +02:00
sk
cd3de97d55 Merge remote-tracking branch 'upstream/l10n_master' 2023-10-07 23:47:36 +02:00
sk
4853a25710 bump version 2023-10-07 23:47:01 +02:00
SomeTr
eba9a1da7b Translated using Weblate (Ukrainian)
Currently translated at 100.0% (18 of 18 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/uk/
2023-10-07 21:46:18 +00:00
SomeTr
068c62b060 Translated using Weblate (Ukrainian)
Currently translated at 98.9% (385 of 389 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-07 21:46:18 +00:00
David Lapshin
5d7f06eba0 Translated using Weblate (Russian)
Currently translated at 97.6% (380 of 389 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2023-10-07 21:46:18 +00:00
Linerly
fed9dec33a Translated using Weblate (Indonesian)
Currently translated at 100.0% (389 of 389 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-10-07 21:46:18 +00:00
Choukajohn
7973914a5f Translated using Weblate (French)
Currently translated at 100.0% (389 of 389 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-10-07 21:46:18 +00:00
kallekn
35efb3f047 Translated using Weblate (Finnish)
Currently translated at 100.0% (389 of 389 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fi/
2023-10-07 21:46:18 +00:00
sk
0a4ed50904 i think i fixed the offset issue 2023-10-07 23:45:33 +02:00
sk
002c66174a fix type filter, wrong max id, refactor max id 2023-10-07 23:32:10 +02:00
Eugen Rochko
22aac3d943 New translations strings.xml (Finnish) 2023-10-07 22:49:20 +02:00
sk
872f47305a Revert "temporary fix for pre-release users"
This reverts commit 2314871246.
2023-10-07 22:38:42 +02:00
sk
75d5332411 don't add existing posts to timeline 2023-10-07 22:38:30 +02:00
sk
035da8a517 update blocks and languages 2023-10-07 22:17:36 +02:00
sk
4c2c877d41 bump version 2023-10-07 22:11:35 +02:00
Eugen Rochko
53afc120f3 New translations strings.xml (Chinese Traditional) 2023-10-07 03:46:12 +02:00
Eugen Rochko
a75ce70615 New translations strings.xml (Finnish) 2023-10-06 16:38:40 +02:00
Eugen Rochko
4a3b948760 New translations strings.xml (Finnish) 2023-10-05 22:23:12 +02:00
Eugen Rochko
f81283c892 New translations strings.xml (Italian) 2023-10-05 21:19:39 +02:00
Eugen Rochko
7eae879037 New translations strings.xml (Russian) 2023-10-05 16:06:00 +02:00
Eugen Rochko
1b0ce5d893 New translations strings.xml (Swedish) 2023-10-05 12:02:19 +02:00
Eugen Rochko
c17745368d New translations strings.xml (Italian) 2023-10-04 22:24:20 +02:00
Eugen Rochko
e78b518654 New translations strings.xml (Ukrainian) 2023-10-04 18:44:26 +02:00
Eugen Rochko
55a8634be2 New translations strings.xml (Japanese) 2023-10-04 16:52:54 +02:00
Eugen Rochko
ac891eea53 New translations strings.xml (Icelandic) 2023-10-04 15:28:52 +02:00
Eugen Rochko
74fa2a3081 New translations strings.xml (Thai) 2023-10-03 21:27:27 +02:00
272 changed files with 1406 additions and 1666 deletions

View File

@@ -15,8 +15,8 @@ android {
applicationId "org.joinmastodon.android.sk" applicationId "org.joinmastodon.android.sk"
minSdk 23 minSdk 23
targetSdk 33 targetSdk 33
versionCode 100 versionCode 104
versionName "2.1.6+fork.100" versionName "2.1.6+fork.104"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resourceConfigurations += ['ar-rSA', 'ar-rDZ', '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'] resourceConfigurations += ['ar-rSA', 'ar-rDZ', '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']
} }

View File

@@ -1,56 +1,43 @@
13bells.com 13bells.com
1611.social 1611.social
4aem.com 4aem.com
5dollah.click
adachi.party adachi.party
anime.website adtension.com
annihilation.social annihilation.social
anon-kenkai.com anon-kenkai.com
asbestos.cafe asbestos.cafe
bae.st bae.st
bajax.us
banepo.st banepo.st
baraag.net
bassam.social bassam.social
battlepenguin.video
beefyboys.win beefyboys.win
beepboop.ga
berserker.town
bikeshed.party
boks.moe
boymoder.biz boymoder.biz
brainsoap.net brainsoap.net
breastmilk.club breastmilk.club
brighteon.social brighteon.social
bungle.online cachapa.xyz
canary.fedinuke.example.com
catgirl.life
cawfee.club cawfee.club
childlove.space
clew.lol clew.lol
clubcyberia.co clubcyberia.co
collapsitarian.io
comfyboy.club
contrapointsfan.club contrapointsfan.club
crucible.world
cum.camp cum.camp
cum.salon cum.salon
darknight-coffee.org
decayable.ink decayable.ink
dembased.xyz dembased.xyz
desupost.soy
detroitriotcity.com detroitriotcity.com
eatthebugs.social djsumdog.com
eientei.org eientei.org
elementality.org
eveningzoo.club eveningzoo.club
firedragonstudios.com
firefaithfellowship.com
fluf.club fluf.club
foxfam.club
freak.university freak.university
freeatlantis.com freeatlantis.com
freedomstrike.org
freesoftwareextremist.com
freespeech.group
freespeechextremist.com freespeechextremist.com
freetalklive.com
froth.zone froth.zone
fulltermprivacy.com
gameliberty.club gameliberty.club
gearlandia.haus gearlandia.haus
genderheretics.xyz genderheretics.xyz
@@ -59,42 +46,34 @@ gleasonator.com
glee.li glee.li
glindr.org glindr.org
goyim.app goyim.app
goyslop.cafe h5q.net
haeder.net haeder.net
handholding.io handholding.io
hitchhiker.social hitchhiker.social
hunk.city
iddqd.social iddqd.social
intkos.link
justicewarrior.social
kawa-kun.com
kitsunemimi.club kitsunemimi.club
kiwifarms.cc kiwifarms.cc
kompost.cz
kurosawa.moe kurosawa.moe
kyaruc.moe
leafposter.club leafposter.club
leftychan.net
lewdieheaven.com lewdieheaven.com
liberdon.com liberdon.com
ligma.pro ligma.pro
lolicon.rocks lolicon.rocks
lolison.network
lolison.top lolison.top
lovingexpressions.net lovingexpressions.net
mahodou.moe
makemysarcophagus.com makemysarcophagus.com
maladaptive.art
marsey.moe marsey.moe
masochi.st
mastinator.com mastinator.com
merovingian.club merovingian.club
midwaytrades.com midwaytrades.com
mirr0r.city mirr0r.city
moa.st morale.ch
mouse.services mouse.services
mugicha.club mugicha.club
narrativerry.xyz narrativerry.xyz
natehiggers.online natehiggers.online
neckbeard.xyz
needs.vodka needs.vodka
neenster.org neenster.org
nicecrew.digital nicecrew.digital
@@ -103,18 +82,18 @@ noagendasocial.com
noagendasocial.nl noagendasocial.nl
noagendatube.com noagendatube.com
nobodyhasthe.biz nobodyhasthe.biz
nukem.biz norwoodzero.net
obo.sh nyanide.com
onionfarms.org onionfarms.org
pawlicker.com pawlicker.com
pawoo.net pawoo.net
pedo.school pedo.school
peervideo.club
piazza.today piazza.today
pibvt.net pibvt.net
pieville.net pieville.net
pisskey.io pisskey.io
plagu.ee plagu.ee
pmth.us
poa.st poa.st
poast.org poast.org
poast.tv poast.tv
@@ -123,17 +102,18 @@ prospeech.space
quodverum.com quodverum.com
r18.social r18.social
rakket.app rakket.app
rapemeat.express
rapemeat.solutions rapemeat.solutions
rdrama.cc rayci.st
rebelbase.site rebelbase.site
retardedniggers.forsale
rojogato.com
ryona.agency ryona.agency
sad.cab
schwartzwelt.xyz schwartzwelt.xyz
seal.cafe seal.cafe
shaw.app
shigusegubu.club shigusegubu.club
shitpost.cloud shitpost.cloud
shota.house shortstacksran.ch
silliness.observer silliness.observer
skinheads.eu skinheads.eu
skinheads.io skinheads.io
@@ -148,23 +128,20 @@ sneed.social
sonichu.com sonichu.com
spinster.xyz spinster.xyz
springbo.cc springbo.cc
starnix.network
strelizia.net strelizia.net
syspxl.xyz
tastingtraffic.net tastingtraffic.net
teci.world teci.world
theapex.social theapex.social
thechimp.zone
thenobody.club
thepostearthdestination.com thepostearthdestination.com
tkammer.de tkammer.de
trumpislovetrumpis.life trumpislovetrumpis.life
truthsocial.co.in truthsocial.co.in
urchan.org usualsuspects.lol
varishangout.net varishangout.net
whinge.house vtuberfan.social
whinge.town
wideboys.org
wolfgirl.bar wolfgirl.bar
xn--p1abe3d.xn--80asehdb xn--p1abe3d.xn--80asehdb
yggdrasil.social yggdrasil.social
youjo.love youjo.love
zztails.gay

View File

@@ -281,7 +281,7 @@ public class AudioPlayerService extends Service{
if(playerReady){ if(playerReady){
boolean isPlaying=player.isPlaying(); boolean isPlaying=player.isPlaying();
bldr.addAction(new Notification.Action.Builder(Icon.createWithResource(this, isPlaying ? R.drawable.ic_pause_24 : R.drawable.ic_play_24), bldr.addAction(new Notification.Action.Builder(Icon.createWithResource(this, isPlaying ? R.drawable.ic_fluent_pause_24_filled : R.drawable.ic_fluent_play_24_filled),
getString(isPlaying ? R.string.pause : R.string.play), getString(isPlaying ? R.string.pause : R.string.play),
PendingIntent.getBroadcast(this, 2, new Intent(ACTION_PLAY_PAUSE), PendingIntent.FLAG_IMMUTABLE)) PendingIntent.getBroadcast(this, 2, new Intent(ACTION_PLAY_PAUSE), PendingIntent.FLAG_IMMUTABLE))
.build()); .build());

View File

@@ -1,17 +1,17 @@
package org.joinmastodon.android; package org.joinmastodon.android;
import static org.joinmastodon.android.api.MastodonAPIController.gson; import static org.joinmastodon.android.api.MastodonAPIController.gson;
import static org.joinmastodon.android.api.session.AccountLocalPreferences.ColorPreference.MATERIAL3;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.util.Log; import android.util.Log;
import androidx.annotation.StringRes;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.session.AccountLocalPreferences; import org.joinmastodon.android.api.session.AccountLocalPreferences;
import org.joinmastodon.android.api.session.AccountLocalPreferences.ColorPreference;
import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.ContentType; import org.joinmastodon.android.model.ContentType;
@@ -25,8 +25,6 @@ import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import androidx.annotation.StringRes;
public class GlobalUserPreferences{ public class GlobalUserPreferences{
private static final String TAG="GlobalUserPreferences"; private static final String TAG="GlobalUserPreferences";
@@ -62,6 +60,9 @@ public class GlobalUserPreferences{
public static boolean displayPronounsInTimelines, displayPronounsInThreads, displayPronounsInUserListings; public static boolean displayPronounsInTimelines, displayPronounsInThreads, displayPronounsInUserListings;
public static boolean overlayMedia; public static boolean overlayMedia;
public static boolean showSuicideHelp; public static boolean showSuicideHelp;
public static boolean underlinedLinks;
public static ColorPreference color;
public static boolean likeIcon;
private static SharedPreferences getPrefs(){ private static SharedPreferences getPrefs(){
return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE); return MastodonApp.context.getSharedPreferences("global", Context.MODE_PRIVATE);
@@ -122,6 +123,9 @@ public class GlobalUserPreferences{
displayPronounsInUserListings=prefs.getBoolean("displayPronounsInUserListings", true); displayPronounsInUserListings=prefs.getBoolean("displayPronounsInUserListings", true);
overlayMedia=prefs.getBoolean("overlayMedia", false); overlayMedia=prefs.getBoolean("overlayMedia", false);
showSuicideHelp=prefs.getBoolean("showSuicideHelp", true); showSuicideHelp=prefs.getBoolean("showSuicideHelp", true);
underlinedLinks=prefs.getBoolean("underlinedLinks", true);
color=ColorPreference.valueOf(prefs.getString("color", MATERIAL3.name()));
likeIcon=prefs.getBoolean("likeIcon", false);
if (prefs.contains("prefixRepliesWithRe")) { if (prefs.contains("prefixRepliesWithRe")) {
prefixReplies = prefs.getBoolean("prefixRepliesWithRe", false) prefixReplies = prefs.getBoolean("prefixRepliesWithRe", false)
@@ -132,8 +136,11 @@ public class GlobalUserPreferences{
.apply(); .apply();
} }
if(prefs.getInt("migrationLevel", 0) < 61) migrateToUpstreamVersion61(); int migrationLevel=prefs.getInt("migrationLevel", BuildConfig.VERSION_CODE);
if(prefs.getInt("migrationLevel", 0) < 101) migrateToVersion101(); if(migrationLevel < 61)
migrateToUpstreamVersion61();
if(migrationLevel < BuildConfig.VERSION_CODE)
prefs.edit().putInt("migrationLevel", BuildConfig.VERSION_CODE).apply();
} }
public static void save(){ public static void save(){
@@ -174,19 +181,33 @@ public class GlobalUserPreferences{
.putBoolean("displayPronounsInUserListings", displayPronounsInUserListings) .putBoolean("displayPronounsInUserListings", displayPronounsInUserListings)
.putBoolean("overlayMedia", overlayMedia) .putBoolean("overlayMedia", overlayMedia)
.putBoolean("showSuicideHelp", showSuicideHelp) .putBoolean("showSuicideHelp", showSuicideHelp)
.putBoolean("underlinedLinks", underlinedLinks)
.putString("color", color.name())
.putBoolean("likeIcon", likeIcon)
.apply(); .apply();
} }
private static void migrateToVersion101(){ public enum ThemePreference{
Log.d(TAG, "Migrating preferences to version 101!! (copy current theme to local preferences)"); AUTO,
LIGHT,
AccountSessionManager asm=AccountSessionManager.getInstance(); DARK
for(AccountSession session : asm.getLoggedInAccounts()){
String accountID=session.getID();
AccountLocalPreferences localPrefs=session.getLocalPreferences();
}
} }
public enum AutoRevealMode {
NEVER,
THREADS,
DISCUSSIONS
}
public enum PrefixRepliesMode {
NEVER,
ALWAYS,
TO_OTHERS
}
//region preferences migrations
private static void migrateToUpstreamVersion61(){ private static void migrateToUpstreamVersion61(){
Log.d(TAG, "Migrating preferences to upstream version 61!!"); Log.d(TAG, "Migrating preferences to upstream version 61!!");
@@ -233,25 +254,8 @@ public class GlobalUserPreferences{
localPrefs.save(); localPrefs.save();
} }
prefs.edit().putInt("migrationLevel", 61).apply();
} }
public enum ThemePreference{ //endregion
AUTO,
LIGHT,
DARK
}
public enum AutoRevealMode {
NEVER,
THREADS,
DISCUSSIONS
}
public enum PrefixRepliesMode {
NEVER,
ALWAYS,
TO_OTHERS
}
} }

View File

@@ -14,7 +14,6 @@ import android.content.Intent;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@@ -33,7 +32,6 @@ import org.joinmastodon.android.model.Preferences;
import org.joinmastodon.android.model.PushNotification; import org.joinmastodon.android.model.PushNotification;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.StatusPrivacy; import org.joinmastodon.android.model.StatusPrivacy;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import org.parceler.Parcels; import org.parceler.Parcels;
@@ -212,7 +210,7 @@ public class PushNotificationReceiver extends BroadcastReceiver{
if (!GlobalUserPreferences.uniformNotificationIcon) { if (!GlobalUserPreferences.uniformNotificationIcon) {
builder.setSmallIcon(switch (pn.notificationType) { builder.setSmallIcon(switch (pn.notificationType) {
case FAVORITE -> R.drawable.ic_fluent_star_24_filled; case FAVORITE -> GlobalUserPreferences.likeIcon ? R.drawable.ic_fluent_heart_24_filled : R.drawable.ic_fluent_star_24_filled;
case REBLOG -> R.drawable.ic_fluent_arrow_repeat_all_24_filled; case REBLOG -> R.drawable.ic_fluent_arrow_repeat_all_24_filled;
case FOLLOW -> R.drawable.ic_fluent_person_add_24_filled; case FOLLOW -> R.drawable.ic_fluent_person_add_24_filled;
case MENTION -> R.drawable.ic_fluent_mention_24_filled; case MENTION -> R.drawable.ic_fluent_mention_24_filled;

View File

@@ -26,6 +26,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.function.Consumer; import java.util.function.Consumer;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
@@ -69,7 +70,7 @@ public class CacheController{
Status status=MastodonAPIController.gson.fromJson(cursor.getString(0), Status.class); Status status=MastodonAPIController.gson.fromJson(cursor.getString(0), Status.class);
status.postprocess(); status.postprocess();
int flags=cursor.getInt(1); int flags=cursor.getInt(1);
status.hasGapAfter=((flags & POST_FLAG_GAP_AFTER)!=0); status.hasGapAfter=((flags & POST_FLAG_GAP_AFTER)!=0) ? status.id : null;
newMaxID=status.id; newMaxID=status.id;
result.add(status); result.add(status);
}while(cursor.moveToNext()); }while(cursor.moveToNext());
@@ -113,7 +114,7 @@ public class CacheController{
values.put("id", s.id); values.put("id", s.id);
values.put("json", MastodonAPIController.gson.toJson(s)); values.put("json", MastodonAPIController.gson.toJson(s));
int flags=0; int flags=0;
if(s.hasGapAfter) if(Objects.equals(s.hasGapAfter, s.id))
flags|=POST_FLAG_GAP_AFTER; flags|=POST_FLAG_GAP_AFTER;
values.put("flags", flags); values.put("flags", flags);
values.put("time", s.createdAt.getEpochSecond()); values.put("time", s.createdAt.getEpochSecond());

View File

@@ -97,7 +97,7 @@ public class PushSubscriptionManager{
deviceToken=getPrefs().getString("deviceToken", null); deviceToken=getPrefs().getString("deviceToken", null);
int tokenVersion=getPrefs().getInt("version", 0); int tokenVersion=getPrefs().getInt("version", 0);
if(!TextUtils.isEmpty(deviceToken) && tokenVersion==BuildConfig.VERSION_CODE){ if(!TextUtils.isEmpty(deviceToken) && tokenVersion==BuildConfig.VERSION_CODE){
registerAllAccountsForPush(true); // TODO: revert this before release registerAllAccountsForPush(false);
return; return;
} }
Log.i(TAG, "tryRegisterFCM: no token found or app was updated. Trying to get push token..."); Log.i(TAG, "tryRegisterFCM: no token found or app was updated. Trying to get push token...");

View File

@@ -13,7 +13,7 @@ import okhttp3.MultipartBody;
import okhttp3.RequestBody; import okhttp3.RequestBody;
public class PleromaMarkNotificationsRead extends MastodonAPIRequest<List<Notification>> { public class PleromaMarkNotificationsRead extends MastodonAPIRequest<List<Notification>> {
private String maxID; private final String maxID;
public PleromaMarkNotificationsRead(String maxID) { public PleromaMarkNotificationsRead(String maxID) {
super(HttpMethod.POST, "/pleroma/notifications/read", new TypeToken<>(){}); super(HttpMethod.POST, "/pleroma/notifications/read", new TypeToken<>(){});
this.maxID = maxID; this.maxID = maxID;

View File

@@ -10,6 +10,7 @@ import androidx.annotation.StringRes;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.model.ContentType; import org.joinmastodon.android.model.ContentType;
import org.joinmastodon.android.model.Emoji; import org.joinmastodon.android.model.Emoji;
@@ -43,7 +44,6 @@ public class AccountLocalPreferences{
public boolean emojiReactionsEnabled; public boolean emojiReactionsEnabled;
public ShowEmojiReactions showEmojiReactions; public ShowEmojiReactions showEmojiReactions;
public ColorPreference color; public ColorPreference color;
public boolean likeIcon;
public ArrayList<Emoji> recentCustomEmoji; public ArrayList<Emoji> recentCustomEmoji;
private final static Type recentLanguagesType=new TypeToken<ArrayList<String>>() {}.getType(); private final static Type recentLanguagesType=new TypeToken<ArrayList<String>>() {}.getType();
@@ -73,8 +73,7 @@ public class AccountLocalPreferences{
keepOnlyLatestNotification=prefs.getBoolean("keepOnlyLatestNotification", false); keepOnlyLatestNotification=prefs.getBoolean("keepOnlyLatestNotification", false);
emojiReactionsEnabled=prefs.getBoolean("emojiReactionsEnabled", session.getInstance().isPresent() && session.getInstance().get().isAkkoma()); emojiReactionsEnabled=prefs.getBoolean("emojiReactionsEnabled", session.getInstance().isPresent() && session.getInstance().get().isAkkoma());
showEmojiReactions=ShowEmojiReactions.valueOf(prefs.getString("showEmojiReactions", ShowEmojiReactions.HIDE_EMPTY.name())); showEmojiReactions=ShowEmojiReactions.valueOf(prefs.getString("showEmojiReactions", ShowEmojiReactions.HIDE_EMPTY.name()));
color=ColorPreference.valueOf(prefs.getString("color", ColorPreference.MATERIAL3.name())); color=prefs.contains("color") ? ColorPreference.valueOf(prefs.getString("color", null)) : null;
likeIcon=prefs.getBoolean("likeIcon", false);
recentCustomEmoji=fromJson(prefs.getString("recentCustomEmoji", null), recentCustomEmojiType, new ArrayList<>()); recentCustomEmoji=fromJson(prefs.getString("recentCustomEmoji", null), recentCustomEmojiType, new ArrayList<>());
} }
@@ -86,6 +85,10 @@ public class AccountLocalPreferences{
prefs.edit().putLong("notificationsPauseTime", time).apply(); prefs.edit().putLong("notificationsPauseTime", time).apply();
} }
public ColorPreference getCurrentColor(){
return color!=null ? color : GlobalUserPreferences.color!=null ? GlobalUserPreferences.color : ColorPreference.MATERIAL3;
}
public void save(){ public void save(){
prefs.edit() prefs.edit()
.putBoolean("interactionCounts", showInteractionCounts) .putBoolean("interactionCounts", showInteractionCounts)
@@ -109,8 +112,7 @@ public class AccountLocalPreferences{
.putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification) .putBoolean("keepOnlyLatestNotification", keepOnlyLatestNotification)
.putBoolean("emojiReactionsEnabled", emojiReactionsEnabled) .putBoolean("emojiReactionsEnabled", emojiReactionsEnabled)
.putString("showEmojiReactions", showEmojiReactions.name()) .putString("showEmojiReactions", showEmojiReactions.name())
.putString("color", color.name()) .putString("color", color!=null ? color.name() : null)
.putBoolean("likeIcon", likeIcon)
.putString("recentCustomEmoji", gson.toJson(recentCustomEmoji)) .putString("recentCustomEmoji", gson.toJson(recentCustomEmoji))
.apply(); .apply();
} }

View File

@@ -270,6 +270,7 @@ public class AccountSession{
if(s!=null && s.filtered!=null){ if(s!=null && s.filtered!=null){
localPreferences.serverSideFiltersSupported=true; localPreferences.serverSideFiltersSupported=true;
localPreferences.save(); localPreferences.save();
break;
} }
} }
@@ -279,9 +280,17 @@ public class AccountSession{
if(filterStatusContainingObject(o, extractor, context, profile)){ if(filterStatusContainingObject(o, extractor, context, profile)){
Status s=extractor.apply(o); Status s=extractor.apply(o);
removeUs.add(o); removeUs.add(o);
if(s!=null && s.hasGapAfter && i > 0){ if(s!=null && s.hasGapAfter!=null && i>0){
Status prev=extractor.apply(objects.get(i - 1)); // oops, we're about to remove an item that has a gap after...
if(prev!=null) prev.hasGapAfter=true; // gotta find the previous status that's not also about to be removed
for(int j=i-1; j>=0; j--){
T p=objects.get(j);
Status prev=extractor.apply(objects.get(j));
if(prev!=null && !removeUs.contains(p)){
prev.hasGapAfter=s.hasGapAfter;
break;
}
}
} }
} }
} }
@@ -295,7 +304,7 @@ public class AccountSession{
// don't hide own posts in own profile // don't hide own posts in own profile
if(statusIsOnOwnProfile(s, profile)) if(statusIsOnOwnProfile(s, profile))
return false; return false;
if(isFilteredType(s)) if(isFilteredType(s) && (context == FilterContext.HOME || context == FilterContext.PUBLIC))
return true; return true;
// Even with server-side filters, clients are expected to remove statuses that match a filter that hides them // Even with server-side filters, clients are expected to remove statuses that match a filter that hides them
if(localPreferences.serverSideFiltersSupported){ if(localPreferences.serverSideFiltersSupported){

View File

@@ -1,7 +1,5 @@
package org.joinmastodon.android.events; package org.joinmastodon.android.events;
import org.joinmastodon.android.model.ScheduledStatus;
public class ScheduledStatusDeletedEvent{ public class ScheduledStatusDeletedEvent{
public final String id; public final String id;
public final String accountID; public final String accountID;

View File

@@ -52,14 +52,14 @@ public class AccountTimelineFragment extends StatusListFragment{
@Override @Override
protected void doLoadData(int offset, int count){ protected void doLoadData(int offset, int count){
currentRequest=new GetAccountStatuses(user.id, offset>0 ? getMaxID() : null, null, count, filter) currentRequest=new GetAccountStatuses(user.id, getMaxID(), null, count, filter)
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
if(getActivity()==null) return; if(getActivity()==null) return;
boolean empty=result.isEmpty(); boolean more=applyMaxID(result);
AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext(), user); AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext(), user);
onDataLoaded(result, !empty); onDataLoaded(result, more);
} }
}) })
.exec(accountID); .exec(accountID);

View File

@@ -97,7 +97,7 @@ public class AnnouncementsFragment extends BaseStatusListFragment<Announcement>
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(List<Announcement> result){ public void onSuccess(List<Announcement> result){
if (getActivity() == null) return; if(getActivity()==null) return;
// get unread items first // get unread items first
List<Announcement> data = result.stream().filter(a -> !a.read).collect(toList()); List<Announcement> data = result.stream().filter(a -> !a.read).collect(toList());

View File

@@ -33,7 +33,6 @@ import org.joinmastodon.android.model.Translation;
import org.joinmastodon.android.ui.BetterItemAnimator; import org.joinmastodon.android.ui.BetterItemAnimator;
import org.joinmastodon.android.ui.M3AlertDialogBuilder; import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.AccountStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.EmojiReactionsStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem; import org.joinmastodon.android.ui.displayitems.GapStatusDisplayItem;
@@ -89,6 +88,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
protected Rect tmpRect=new Rect(); protected Rect tmpRect=new Rect();
protected TypedObjectPool<MediaGridStatusDisplayItem.GridItemType, MediaAttachmentViewController> attachmentViewsPool=new TypedObjectPool<>(this::makeNewMediaAttachmentView); protected TypedObjectPool<MediaGridStatusDisplayItem.GridItemType, MediaAttachmentViewController> attachmentViewsPool=new TypedObjectPool<>(this::makeNewMediaAttachmentView);
protected boolean currentlyScrolling; protected boolean currentlyScrolling;
protected String maxID;
public BaseStatusListFragment(){ public BaseStatusListFragment(){
super(20); super(20);
@@ -155,6 +155,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
} }
protected String getMaxID(){ protected String getMaxID(){
if(refreshing) return null;
if(maxID!=null) return maxID;
if(!preloadedData.isEmpty()) if(!preloadedData.isEmpty())
return preloadedData.get(preloadedData.size()-1).getID(); return preloadedData.get(preloadedData.size()-1).getID();
else if(!data.isEmpty()) else if(!data.isEmpty())
@@ -163,6 +165,12 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
return null; return null;
} }
protected boolean applyMaxID(List<Status> result){
boolean empty=result.isEmpty();
if(!empty) maxID=result.get(result.size()-1).id;
return !empty;
}
protected abstract List<StatusDisplayItem> buildDisplayItems(T s); protected abstract List<StatusDisplayItem> buildDisplayItems(T s);
protected abstract void addAccountToKnown(T s); protected abstract void addAccountToKnown(T s);
@@ -457,12 +465,12 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
public abstract void onItemClick(String id); public abstract void onItemClick(String id);
protected void updatePoll(String itemID, Status status, Poll poll){ protected void updatePoll(String parentID, Status statusForContent, Poll poll){
status.poll=poll; statusForContent.poll=poll;
int firstOptionIndex=-1, footerIndex=-1; int firstOptionIndex=-1, footerIndex=-1;
int i=0; int i=0;
for(StatusDisplayItem item:displayItems){ for(StatusDisplayItem item:displayItems){
if(item.parentID.equals(itemID)){ if(item.contentStatusID.equals(statusForContent.id)){
if(item instanceof PollOptionStatusDisplayItem && firstOptionIndex==-1){ if(item instanceof PollOptionStatusDisplayItem && firstOptionIndex==-1){
firstOptionIndex=i; firstOptionIndex=i;
}else if(item instanceof PollFooterStatusDisplayItem){ }else if(item instanceof PollFooterStatusDisplayItem){
@@ -477,7 +485,7 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
List<StatusDisplayItem> pollItems=displayItems.subList(firstOptionIndex, footerIndex+1); List<StatusDisplayItem> pollItems=displayItems.subList(firstOptionIndex, footerIndex+1);
int prevSize=pollItems.size(); int prevSize=pollItems.size();
pollItems.clear(); pollItems.clear();
StatusDisplayItem.buildPollItems(itemID, this, poll, pollItems); StatusDisplayItem.buildPollItems(parentID, statusForContent.id, this, poll, pollItems);
if(prevSize!=pollItems.size()){ if(prevSize!=pollItems.size()){
adapter.notifyItemRangeRemoved(firstOptionIndex, prevSize); adapter.notifyItemRangeRemoved(firstOptionIndex, prevSize);
adapter.notifyItemRangeInserted(firstOptionIndex, pollItems.size()); adapter.notifyItemRangeInserted(firstOptionIndex, pollItems.size());
@@ -549,21 +557,21 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
public void onVisibilityIconClick(HeaderStatusDisplayItem.Holder holder) { public void onVisibilityIconClick(HeaderStatusDisplayItem.Holder holder) {
Status status = holder.getItem().status; Status status = holder.getItem().status;
MediaGridStatusDisplayItem.Holder mediaGrid = findHolderOfType(holder.getItemID(), MediaGridStatusDisplayItem.Holder.class);
if (mediaGrid != null) {
if (!status.sensitiveRevealed) mediaGrid.revealSensitive();
else mediaGrid.hideSensitive();
} else {
// media grid's methods normally change the status' state - we still want to be able
// to do this if the media grid is not bound, tho - so, doing it ourselves here
status.sensitiveRevealed = !status.sensitiveRevealed;
}
if(holder.getItem().hasVisibilityToggle) holder.animateVisibilityToggle(false); if(holder.getItem().hasVisibilityToggle) holder.animateVisibilityToggle(false);
MediaGridStatusDisplayItem.Holder mediaGrid=findHolderOfType(holder.getItemID(), MediaGridStatusDisplayItem.Holder.class);
if(mediaGrid!=null){
if(!status.sensitiveRevealed) mediaGrid.revealSensitive();
else mediaGrid.hideSensitive();
}else{
status.sensitiveRevealed=false;
notifyItemChangedAfter(holder.getItem(), MediaGridStatusDisplayItem.class);
}
} }
public void onSensitiveRevealed(MediaGridStatusDisplayItem.Holder holder) { public void onSensitiveRevealed(MediaGridStatusDisplayItem.Holder holder) {
HeaderStatusDisplayItem.Holder header = findHolderOfType(holder.getItemID(), HeaderStatusDisplayItem.Holder.class); HeaderStatusDisplayItem.Holder header=findHolderOfType(holder.getItemID(), HeaderStatusDisplayItem.Holder.class);
if(header != null && header.getItem().hasVisibilityToggle) header.animateVisibilityToggle(true); if(header!=null && header.getItem().hasVisibilityToggle) header.animateVisibilityToggle(true);
else notifyItemChangedBefore(holder.getItem(), HeaderStatusDisplayItem.class);
} }
protected void toggleSpoiler(Status status, String itemID){ protected void toggleSpoiler(Status status, String itemID){
@@ -572,8 +580,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
status.sensitiveRevealed = false; status.sensitiveRevealed = false;
SpoilerStatusDisplayItem.Holder spoiler=findHolderOfType(itemID, SpoilerStatusDisplayItem.Holder.class); SpoilerStatusDisplayItem.Holder spoiler=findHolderOfType(itemID, SpoilerStatusDisplayItem.Holder.class);
if(spoiler!=null) if(spoiler!=null) spoiler.rebind();
spoiler.rebind(); else notifyItemChanged(itemID, SpoilerStatusDisplayItem.class);
SpoilerStatusDisplayItem spoilerItem=Objects.requireNonNull(findItemOfType(itemID, SpoilerStatusDisplayItem.class)); SpoilerStatusDisplayItem spoilerItem=Objects.requireNonNull(findItemOfType(itemID, SpoilerStatusDisplayItem.class));
int index=displayItems.indexOf(spoilerItem); int index=displayItems.indexOf(spoilerItem);
@@ -585,39 +593,29 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
adapter.notifyItemRangeRemoved(index+1, spoilerItem.contentItems.size()); adapter.notifyItemRangeRemoved(index+1, spoilerItem.contentItems.size());
} }
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class); notifyItemChanged(itemID, TextStatusDisplayItem.class);
if(text!=null)
adapter.notifyItemChanged(text.getAbsoluteAdapterPosition()-getMainAdapterOffset());
HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class); HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class);
if(header!=null) if(header!=null) header.rebind();
header.rebind(); else notifyItemChanged(itemID, HeaderStatusDisplayItem.class);
list.invalidateItemDecorations(); list.invalidateItemDecorations();
} }
public void onEnableExpandable(TextStatusDisplayItem.Holder holder, boolean expandable) { public void onEnableExpandable(TextStatusDisplayItem.Holder holder, boolean expandable) {
if (holder.getItem().status.textExpandable != expandable && list != null) { Status s=holder.getItem().status;
holder.getItem().status.textExpandable = expandable; if(s.textExpandable!=expandable && list!=null) {
HeaderStatusDisplayItem.Holder header = findHolderOfType(holder.getItemID(), HeaderStatusDisplayItem.Holder.class); s.textExpandable=expandable;
if (header != null) header.rebind(); HeaderStatusDisplayItem.Holder header=findHolderOfType(holder.getItemID(), HeaderStatusDisplayItem.Holder.class);
if(header!=null) header.bindCollapseButton();
} }
} }
public void onToggleExpanded(Status status, String itemID) { public void onToggleExpanded(Status status, String itemID) {
status.textExpanded = !status.textExpanded; status.textExpanded = !status.textExpanded;
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class); notifyItemChanged(itemID, TextStatusDisplayItem.class);
HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class); HeaderStatusDisplayItem.Holder header=findHolderOfType(itemID, HeaderStatusDisplayItem.Holder.class);
if (text != null) text.rebind(); if(header!=null) header.animateExpandToggle();
if (header != null) header.rebind(); else notifyItemChanged(itemID, HeaderStatusDisplayItem.class);
}
public void updateEmojiReactions(Status status, String itemID){
EmojiReactionsStatusDisplayItem.Holder reactions=findHolderOfType(itemID, EmojiReactionsStatusDisplayItem.Holder.class);
if(reactions != null){
reactions.getItem().status.reactions.clear();
reactions.getItem().status.reactions.addAll(status.reactions);
reactions.rebind();
}
} }
public void onGapClick(GapStatusDisplayItem.Holder item, boolean downwards){} public void onGapClick(GapStatusDisplayItem.Holder item, boolean downwards){}
@@ -676,9 +674,61 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
return null; return null;
} }
/**
* Use this as a fallback if findHolderOfType fails to find the ViewHolder.
* It might still be bound but off-screen and therefore not a child of the RecyclerView -
* resulting in the ViewHolder displaying an outdated state once scrolled back into view.
*/
protected <I extends StatusDisplayItem> int notifyItemChanged(String id, Class<I> type){
boolean encounteredParent=false;
for(int i=0; i<displayItems.size(); i++){
StatusDisplayItem item=displayItems.get(i);
boolean idEquals=id.equals(item.parentID);
if(!encounteredParent && idEquals) encounteredParent=true; // reached top of the parent
else if(encounteredParent && !idEquals) break; // passed by bottom of the parent. man muss ja wissen wann schluss is
if(idEquals && type.isInstance(item)){
adapter.notifyItemChanged(i);
return i;
}
}
return -1;
}
protected <I extends StatusDisplayItem> int notifyItemChangedAfter(StatusDisplayItem afterThis, Class<I> type){
int startIndex=displayItems.indexOf(afterThis);
if(startIndex == -1) throw new IllegalStateException("notifyItemChangedAfter didn't find the passed StatusDisplayItem");
String parentID=afterThis.parentID;
for(int i=startIndex; i<displayItems.size(); i++){
StatusDisplayItem item=displayItems.get(i);
if(!parentID.equals(item.parentID)) break; // didn't find anything
if(type.isInstance(item)){
// found it
adapter.notifyItemChanged(i);
return i;
}
}
return -1;
}
protected <I extends StatusDisplayItem> int notifyItemChangedBefore(StatusDisplayItem beforeThis, Class<I> type){
int startIndex=displayItems.indexOf(beforeThis);
if(startIndex == -1) throw new IllegalStateException("notifyItemChangedBefore didn't find the passed StatusDisplayItem");
String parentID=beforeThis.parentID;
for(int i=startIndex; i>=0; i--){
StatusDisplayItem item=displayItems.get(i);
if(!parentID.equals(item.parentID)) break; // didn't find anything
if(type.isInstance(item)){
// found it
adapter.notifyItemChanged(i);
return i;
}
}
return -1;
}
@Nullable @Nullable
protected <I extends StatusDisplayItem, H extends StatusDisplayItem.Holder<I>> H findHolderOfType(String id, Class<H> type){ protected <I extends StatusDisplayItem, H extends StatusDisplayItem.Holder<I>> H findHolderOfType(String id, Class<H> type){
for(int i=0;i<list.getChildCount();i++){ for(int i=0; i<list.getChildCount(); i++){
RecyclerView.ViewHolder holder=list.getChildViewHolder(list.getChildAt(i)); RecyclerView.ViewHolder holder=list.getChildViewHolder(list.getChildAt(i));
if(holder instanceof StatusDisplayItem.Holder<?> itemHolder && itemHolder.getItemID().equals(id) && type.isInstance(holder)) if(holder instanceof StatusDisplayItem.Holder<?> itemHolder && itemHolder.getItemID().equals(id) && type.isInstance(holder))
return type.cast(holder); return type.cast(holder);
@@ -800,6 +850,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
if(text!=null){ if(text!=null){
text.updateTranslation(true); text.updateTranslation(true);
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition()); imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
}else{
notifyItemChanged(itemID, TextStatusDisplayItem.class);
} }
} }
@@ -811,6 +863,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class); TextStatusDisplayItem.Holder text=findHolderOfType(itemID, TextStatusDisplayItem.Holder.class);
if(text!=null){ if(text!=null){
text.updateTranslation(true); text.updateTranslation(true);
}else{
notifyItemChanged(itemID, TextStatusDisplayItem.class);
} }
new M3AlertDialogBuilder(getActivity()) new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.error) .setTitle(R.string.error)
@@ -827,6 +881,8 @@ public abstract class BaseStatusListFragment<T extends DisplayItemsParent> exten
if(text!=null){ if(text!=null){
text.updateTranslation(true); text.updateTranslation(true);
imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition()); imgLoader.bindViewHolder((ImageLoaderRecyclerAdapter) list.getAdapter(), text, text.getAbsoluteAdapterPosition());
}else{
notifyItemChanged(itemID, TextStatusDisplayItem.class);
} }
} }

View File

@@ -28,7 +28,7 @@ public class BookmarkedStatusListFragment extends StatusListFragment{
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(HeaderPaginationList<Status> result){ public void onSuccess(HeaderPaginationList<Status> result){
if (getActivity() == null) return; if(getActivity()==null) return;
if(result.nextPageUri!=null) if(result.nextPageUri!=null)
nextMaxID=result.nextPageUri.getQueryParameter("max_id"); nextMaxID=result.nextPageUri.getQueryParameter("max_id");
else else

View File

@@ -63,7 +63,8 @@ public class ComposeImageDescriptionFragment extends MastodonToolbarFragment imp
accountID=getArguments().getString("account"); accountID=getArguments().getString("account");
attachmentID=getArguments().getString("attachment"); attachmentID=getArguments().getString("attachment");
themeWrapper=new ContextThemeWrapper(activity, R.style.Theme_Mastodon_Dark); themeWrapper=new ContextThemeWrapper(activity, R.style.Theme_Mastodon_Dark);
ColorPalette.palettes.get(AccountSessionManager.get(accountID).getLocalPreferences().color).apply(themeWrapper, GlobalUserPreferences.ThemePreference.DARK); ColorPalette.palettes.get(AccountSessionManager.get(accountID).getLocalPreferences().getCurrentColor())
.apply(themeWrapper, GlobalUserPreferences.ThemePreference.DARK);
setTitle(R.string.add_alt_text); setTitle(R.string.add_alt_text);
} }

View File

@@ -169,7 +169,7 @@ public class EditTimelinesFragment extends MastodonRecyclerFragment<TimelineDefi
} }
private void updateOptionsMenu() { private void updateOptionsMenu() {
if (getActivity() == null) return; if(getActivity()==null) return;
optionsMenu.clear(); optionsMenu.clear();
timelineByMenuItem.clear(); timelineByMenuItem.clear();

View File

@@ -27,7 +27,7 @@ public class FavoritedStatusListFragment extends StatusListFragment{
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(HeaderPaginationList<Status> result){ public void onSuccess(HeaderPaginationList<Status> result){
if (getActivity() == null) return; if(getActivity()==null) return;
if(result.nextPageUri!=null) if(result.nextPageUri!=null)
nextMaxID=result.nextPageUri.getQueryParameter("max_id"); nextMaxID=result.nextPageUri.getQueryParameter("max_id");
else else

View File

@@ -83,7 +83,7 @@ public class FollowRequestsListFragment extends MastodonRecyclerFragment<FollowR
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(HeaderPaginationList<Account> result){ public void onSuccess(HeaderPaginationList<Account> result){
if (getActivity() == null) return; if(getActivity()==null) return;
if(result.nextPageUri!=null) if(result.nextPageUri!=null)
nextMaxID=result.nextPageUri.getQueryParameter("max_id"); nextMaxID=result.nextPageUri.getQueryParameter("max_id");
else else

View File

@@ -56,7 +56,7 @@ public class FollowedHashtagsFragment extends MastodonRecyclerFragment<Hashtag>
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(HeaderPaginationList<Hashtag> result){ public void onSuccess(HeaderPaginationList<Hashtag> result){
if (getActivity() == null) return; if(getActivity()==null) return;
if(result.nextPageUri!=null) if(result.nextPageUri!=null)
nextMaxID=result.nextPageUri.getQueryParameter("max_id"); nextMaxID=result.nextPageUri.getQueryParameter("max_id");
else else

View File

@@ -91,14 +91,14 @@ public class HashtagTimelineFragment extends PinnableStatusListFragment{
@Override @Override
protected void doLoadData(int offset, int count){ protected void doLoadData(int offset, int count){
currentRequest=new GetHashtagTimeline(hashtagName, offset==0 ? null : getMaxID(), null, count, any, all, none, localOnly, getLocalPrefs().timelineReplyVisibility) currentRequest=new GetHashtagTimeline(hashtagName, getMaxID(), null, count, any, all, none, localOnly, getLocalPrefs().timelineReplyVisibility)
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
if(getActivity()==null) return; if(getActivity()==null) return;
boolean empty=result.isEmpty(); boolean more=applyMaxID(result);
AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext()); AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext());
onDataLoaded(result, !empty); onDataLoaded(result, more);
} }
}) })
.exec(accountID); .exec(accountID);

View File

@@ -287,7 +287,7 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
new GetAnnouncements(false).setCallback(new Callback<>() { new GetAnnouncements(false).setCallback(new Callback<>() {
@Override @Override
public void onSuccess(List<Announcement> result) { public void onSuccess(List<Announcement> result) {
if (getActivity() == null) return; if(getActivity()==null) return;
if (result.stream().anyMatch(a -> !a.read)) { if (result.stream().anyMatch(a -> !a.read)) {
announcementsBadged = true; announcementsBadged = true;
announcements.setVisible(false); announcements.setVisible(false);
@@ -381,7 +381,7 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
} }
private void updateOverflowMenu() { private void updateOverflowMenu() {
if (getActivity() == null) return; if(getActivity()==null) return;
Menu m = overflowPopup.getMenu(); Menu m = overflowPopup.getMenu();
m.clear(); m.clear();
overflowPopup.inflate(R.menu.home_overflow); overflowPopup.inflate(R.menu.home_overflow);

View File

@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import me.grishka.appkit.api.Callback; import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse; import me.grishka.appkit.api.ErrorResponse;
@@ -137,11 +138,13 @@ public class HomeTimelineFragment extends StatusListFragment {
Status last=result.get(result.size()-1); Status last=result.get(result.size()-1);
List<Status> toAdd; List<Status> toAdd;
if(!data.isEmpty() && last.id.equals(data.get(0).id)){ // This part intersects with the existing one if(!data.isEmpty() && last.id.equals(data.get(0).id)){ // This part intersects with the existing one
toAdd=result.subList(0, result.size()-1); // Remove the already known last post toAdd=new ArrayList<>(result.subList(0, result.size()-1)); // Remove the already known last post
}else{ }else{
result.get(result.size()-1).hasGapAfter=true; last.hasGapAfter=last.id;
toAdd=result; toAdd=result;
} }
List<String> existingIds=data.stream().map(Status::getID).collect(Collectors.toList());
toAdd.removeIf(s->existingIds.contains(s.getID()));
List<Status> toAddUnfiltered=new ArrayList<>(toAdd); List<Status> toAddUnfiltered=new ArrayList<>(toAdd);
AccountSessionManager.get(accountID).filterStatuses(toAdd, getFilterContext()); AccountSessionManager.get(accountID).filterStatuses(toAdd, getFilterContext());
if(!toAdd.isEmpty()){ if(!toAdd.isEmpty()){
@@ -173,10 +176,10 @@ public class HomeTimelineFragment extends StatusListFragment {
gap.loading=true; gap.loading=true;
dataLoading=true; dataLoading=true;
String maxID = null; String maxID=null;
String minID = null; String minID=null;
if (downwards) { if (downwards) {
maxID = item.getItemID(); maxID=item.getItem().getMaxID();
} else { } else {
int gapPos=displayItems.indexOf(gap); int gapPos=displayItems.indexOf(gap);
StatusDisplayItem nextItem=displayItems.get(gapPos + 1); StatusDisplayItem nextItem=displayItems.get(gapPos + 1);
@@ -193,12 +196,13 @@ public class HomeTimelineFragment extends StatusListFragment {
int gapPos=displayItems.indexOf(gap); int gapPos=displayItems.indexOf(gap);
if(gapPos==-1) if(gapPos==-1)
return; return;
AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext());
if(result.isEmpty()){ if(result.isEmpty()){
displayItems.remove(gapPos); displayItems.remove(gapPos);
adapter.notifyItemRemoved(getMainAdapterOffset()+gapPos); adapter.notifyItemRemoved(getMainAdapterOffset()+gapPos);
Status gapStatus=getStatusByID(gap.parentID); Status gapStatus=getStatusByID(gap.parentID);
if(gapStatus!=null){ if(gapStatus!=null){
gapStatus.hasGapAfter=false; gapStatus.hasGapAfter=null;
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(gapStatus), false); AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(gapStatus), false);
} }
}else{ }else{
@@ -211,7 +215,7 @@ public class HomeTimelineFragment extends StatusListFragment {
idsBelowGap.add(s.id); idsBelowGap.add(s.id);
}else if(s.id.equals(gap.parentID)){ }else if(s.id.equals(gap.parentID)){
belowGap=true; belowGap=true;
s.hasGapAfter=false; s.hasGapAfter=null;
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(s), false); AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(s), false);
}else{ }else{
gapPostIndex++; gapPostIndex++;
@@ -224,7 +228,8 @@ public class HomeTimelineFragment extends StatusListFragment {
break; break;
} }
if(endIndex==result.size()){ if(endIndex==result.size()){
result.get(result.size()-1).hasGapAfter=true; Status last=result.get(result.size()-1);
last.hasGapAfter=last.id;
}else{ }else{
result=result.subList(0, endIndex); result=result.subList(0, endIndex);
} }
@@ -269,7 +274,7 @@ public class HomeTimelineFragment extends StatusListFragment {
.filter(s->Objects.equals(s.id, gap.parentID)) .filter(s->Objects.equals(s.id, gap.parentID))
.findFirst(); .findFirst();
if (gapStatus.isPresent()) { if (gapStatus.isPresent()) {
gapStatus.get().hasGapAfter=false; gapStatus.get().hasGapAfter=null;
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(gapStatus.get()), false); AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(Collections.singletonList(gapStatus.get()), false);
} }
targetList.clear(); targetList.clear();

View File

@@ -62,7 +62,7 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
new GetList(listID).setCallback(new Callback<>() { new GetList(listID).setCallback(new Callback<>() {
@Override @Override
public void onSuccess(ListTimeline listTimeline) { public void onSuccess(ListTimeline listTimeline) {
if (getActivity() == null) return; if(getActivity()==null) return;
// TODO: save updated info // TODO: save updated info
if (!listTimeline.title.equals(listTitle)) setTitle(listTimeline.title); if (!listTimeline.title.equals(listTitle)) setTitle(listTimeline.title);
if (listTimeline.repliesPolicy != null && !listTimeline.repliesPolicy.equals(repliesPolicy)) { if (listTimeline.repliesPolicy != null && !listTimeline.repliesPolicy.equals(repliesPolicy)) {
@@ -100,7 +100,7 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
new UpdateList(listID, newTitle, editor.isExclusive(), editor.getRepliesPolicy()).setCallback(new Callback<>() { new UpdateList(listID, newTitle, editor.isExclusive(), editor.getRepliesPolicy()).setCallback(new Callback<>() {
@Override @Override
public void onSuccess(ListTimeline list) { public void onSuccess(ListTimeline list) {
if (getActivity() == null) return; if(getActivity()==null) return;
setTitle(list.title); setTitle(list.title);
listTitle = list.title; listTitle = list.title;
repliesPolicy = list.repliesPolicy; repliesPolicy = list.repliesPolicy;
@@ -133,14 +133,14 @@ public class ListTimelineFragment extends PinnableStatusListFragment {
@Override @Override
protected void doLoadData(int offset, int count) { protected void doLoadData(int offset, int count) {
currentRequest=new GetListTimeline(listID, offset==0 ? null : getMaxID(), null, count, null, getLocalPrefs().timelineReplyVisibility) currentRequest=new GetListTimeline(listID, getMaxID(), null, count, null, getLocalPrefs().timelineReplyVisibility)
.setCallback(new SimpleCallback<>(this) { .setCallback(new SimpleCallback<>(this) {
@Override @Override
public void onSuccess(List<Status> result) { public void onSuccess(List<Status> result) {
if(getActivity()==null) return; if(getActivity()==null) return;
boolean empty=result.isEmpty(); boolean more=applyMaxID(result);
AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext()); AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext());
onDataLoaded(result, !empty); onDataLoaded(result, more);
} }
}) })
.exec(accountID); .exec(accountID);

View File

@@ -140,7 +140,7 @@ public class ListsFragment extends MastodonRecyclerFragment<ListTimeline> implem
.setCallback(new SimpleCallback<>(this) { .setCallback(new SimpleCallback<>(this) {
@Override @Override
public void onSuccess(List<ListTimeline> lists) { public void onSuccess(List<ListTimeline> lists) {
if (getActivity() == null) return; if(getActivity()==null) return;
for (ListTimeline l : lists) userInListBefore.put(l.id, true); for (ListTimeline l : lists) userInListBefore.put(l.id, true);
userInList.putAll(userInListBefore); userInList.putAll(userInListBefore);
if (profileAccountId == null || !lists.isEmpty()) onDataLoaded(lists, false); if (profileAccountId == null || !lists.isEmpty()) onDataLoaded(lists, false);
@@ -149,7 +149,7 @@ public class ListsFragment extends MastodonRecyclerFragment<ListTimeline> implem
currentRequest=new GetLists().setCallback(new SimpleCallback<>(ListsFragment.this) { currentRequest=new GetLists().setCallback(new SimpleCallback<>(ListsFragment.this) {
@Override @Override
public void onSuccess(List<ListTimeline> allLists) { public void onSuccess(List<ListTimeline> allLists) {
if (getActivity() == null) return; if(getActivity()==null) return;
List<ListTimeline> newLists = new ArrayList<>(); List<ListTimeline> newLists = new ArrayList<>();
for (ListTimeline l : allLists) { for (ListTimeline l : allLists) {
if (lists.stream().noneMatch(e -> e.id.equals(l.id))) newLists.add(l); if (lists.stream().noneMatch(e -> e.id.equals(l.id))) newLists.add(l);

View File

@@ -254,7 +254,7 @@ public class NotificationsFragment extends MastodonToolbarFragment implements Sc
new GetFollowRequests(null, 1).setCallback(new Callback<>() { new GetFollowRequests(null, 1).setCallback(new Callback<>() {
@Override @Override
public void onSuccess(HeaderPaginationList<Account> accounts) { public void onSuccess(HeaderPaginationList<Account> accounts) {
if (getActivity() == null) return; if(getActivity()==null) return;
getToolbar().getMenu().findItem(R.id.follow_requests).setVisible(!accounts.isEmpty()); getToolbar().getMenu().findItem(R.id.follow_requests).setVisible(!accounts.isEmpty());
} }

View File

@@ -238,7 +238,7 @@ public class NotificationsListFragment extends BaseStatusListFragment<Notificati
continue; continue;
Status contentStatus=ntf.status.getContentStatus(); Status contentStatus=ntf.status.getContentStatus();
if(contentStatus.poll!=null && contentStatus.poll.id.equals(ev.poll.id)){ if(contentStatus.poll!=null && contentStatus.poll.id.equals(ev.poll.id)){
updatePoll(ntf.id, ntf.status, ev.poll); updatePoll(ntf.id, contentStatus, ev.poll);
} }
} }
} }

View File

@@ -482,7 +482,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(Account result){ public void onSuccess(Account result){
if (getActivity() == null) return; if(getActivity()==null) return;
onAccountLoaded(result); onAccountLoaded(result);
} }
}) })
@@ -894,7 +894,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
} }
private void updateRelationship(){ private void updateRelationship(){
if (getActivity() == null) return; if(getActivity()==null) return;
invalidateOptionsMenu(); invalidateOptionsMenu();
actionButton.setVisibility(View.VISIBLE); actionButton.setVisibility(View.VISIBLE);
notifyButton.setVisibility(relationship.following ? View.VISIBLE : View.GONE); notifyButton.setVisibility(relationship.following ? View.VISIBLE : View.GONE);
@@ -1177,6 +1177,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
imm.hideSoftInputFromWindow(content.getWindowToken(), 0); imm.hideSoftInputFromWindow(content.getWindowToken(), 0);
V.setVisibilityAnimated(fab, View.VISIBLE); V.setVisibilityAnimated(fab, View.VISIBLE);
bindHeaderView(); bindHeaderView();
V.setVisibilityAnimated(fab, View.VISIBLE);
} }
private void saveAndExitEditMode(){ private void saveAndExitEditMode(){
@@ -1191,7 +1192,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
savingEdits=false; savingEdits=false;
account=result; account=result;
AccountSessionManager.getInstance().updateAccountInfo(accountID, account); AccountSessionManager.getInstance().updateAccountInfo(accountID, account);
if (getActivity() == null) return; if(getActivity()==null) return;
exitEditMode(); exitEditMode();
setActionProgressVisible(false); setActionProgressVisible(false);
} }

View File

@@ -129,7 +129,7 @@ public class ScheduledStatusListFragment extends BaseStatusListFragment<Schedule
nextMaxID=result.nextPageUri.getQueryParameter("max_id"); nextMaxID=result.nextPageUri.getQueryParameter("max_id");
else else
nextMaxID=null; nextMaxID=null;
if (getActivity() == null) return; if(getActivity()==null) return;
onDataLoaded(result, nextMaxID!=null); onDataLoaded(result, nextMaxID!=null);
} }
}) })

View File

@@ -145,7 +145,7 @@ public class StatusEditHistoryFragment extends StatusListFragment{
} }
String sep = getString(R.string.sk_separator); String sep = getString(R.string.sk_separator);
items.add(0, new ReblogOrReplyLineStatusDisplayItem(s.id, this, action+" "+sep+" "+date, Collections.emptyList(), 0, null, null, s)); items.add(0, new ReblogOrReplyLineStatusDisplayItem(s.id, this, action+" "+sep+" "+date, Collections.emptyList(), 0, null, null, s));
items.add(1, new DummyStatusDisplayItem(s.id, this)); items.add(1, new DummyStatusDisplayItem(s.id, s.getContentStatus().id, this));
} }
return items; return items;
} }

View File

@@ -28,7 +28,9 @@ import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
import org.parceler.Parcels; import org.parceler.Parcels;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -174,41 +176,57 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>
} }
} }
protected void removeStatus(Status status){ private void iterateRemoveStatus(List<Status> l, String id){
data.remove(status); Iterator<Status> it=l.iterator();
preloadedData.remove(status); while(it.hasNext()){
int index=-1, ancestorFirstIndex = -1, ancestorLastIndex = -1; if(Objects.equals(it.next().getContentStatus().id, id)){
for(int i=0;i<displayItems.size();i++){ it.remove();
StatusDisplayItem item = displayItems.get(i);
if(status.id.equals(item.parentID)){
index=i;
break;
}
if (item.parentID.equals(status.inReplyToId)) {
if (ancestorFirstIndex == -1) ancestorFirstIndex = i;
ancestorLastIndex = i;
} }
} }
}
private int removeStatusDisplayItems(Status status, int index, int ancestorFirstIndex, int ancestorLastIndex, int indexOffset){
// did we find an ancestor that is also the status' neighbor? // did we find an ancestor that is also the status' neighbor?
if (ancestorFirstIndex >= 0 && ancestorLastIndex == index - 1) { if(ancestorFirstIndex>=0 && ancestorLastIndex==index-1){
for (int i = ancestorFirstIndex; i <= ancestorLastIndex; i++) { for(int i=ancestorFirstIndex; i<=ancestorLastIndex; i++){
StatusDisplayItem item = displayItems.get(i); StatusDisplayItem item=displayItems.get(i);
// update ancestor to have no descendant anymore // update ancestor to have no descendant anymore
if (item.parentID.equals(status.inReplyToId)) item.hasDescendantNeighbor = false; if(item.contentStatusID.equals(status.inReplyToId)) item.hasDescendantNeighbor=false;
} }
adapter.notifyItemRangeChanged(ancestorFirstIndex, ancestorLastIndex - ancestorFirstIndex + 1); adapter.notifyItemRangeChanged(ancestorFirstIndex-indexOffset, ancestorLastIndex-ancestorFirstIndex+1);
} }
if(index==-1) if(index==-1) return 0;
return;
int lastIndex; int lastIndex;
for(lastIndex=index;lastIndex<displayItems.size();lastIndex++){ for(lastIndex=index;lastIndex<displayItems.size();lastIndex++){
if(!displayItems.get(lastIndex).parentID.equals(status.id)) if(!displayItems.get(lastIndex).contentStatusID.equals(status.id))
break; break;
} }
displayItems.subList(index, lastIndex).clear(); int count=lastIndex-index;
adapter.notifyItemRangeRemoved(index, lastIndex-index); displayItems.subList(index-indexOffset, lastIndex-indexOffset).clear();
adapter.notifyItemRangeRemoved(index-indexOffset, lastIndex-index);
return count;
}
protected void removeStatus(Status status){
Status contentStatus=status.getContentStatus();
String id=contentStatus.id;
iterateRemoveStatus(data, id);
iterateRemoveStatus(preloadedData, id);
int ancestorFirstIndex=-1, ancestorLastIndex=-1;
int offset=0;
for(int i=0;i<displayItems.size();i++){
StatusDisplayItem item = displayItems.get(i);
if(id.equals(item.contentStatusID)){
offset+=removeStatusDisplayItems(contentStatus, i, ancestorFirstIndex, ancestorLastIndex, offset);
ancestorFirstIndex=ancestorLastIndex=-1;
continue;
}
if(item.parentID.equals(status.inReplyToId)){
if(ancestorFirstIndex==-1) ancestorFirstIndex=i;
ancestorLastIndex=i;
}
}
} }
@Override @Override

View File

@@ -83,7 +83,7 @@ public abstract class BaseAccountListFragment extends MastodonRecyclerFragment<A
for(Relationship rel:result){ for(Relationship rel:result){
relationships.put(rel.id, rel); relationships.put(rel.id, rel);
} }
if (getActivity() == null) return; if(getActivity()==null) return;
if(list==null) if(list==null)
return; return;
for(int i=0;i<list.getChildCount();i++){ for(int i=0;i<list.getChildCount();i++){

View File

@@ -133,7 +133,7 @@ public abstract class PaginatedAccountListFragment<T> extends BaseAccountListFra
nextMaxID=result.nextPageUri.getQueryParameter("max_id"); nextMaxID=result.nextPageUri.getQueryParameter("max_id");
else else
nextMaxID=null; nextMaxID=null;
if (getActivity() == null) return; if(getActivity()==null) return;
List<AccountViewModel> items = result.stream() List<AccountViewModel> items = result.stream()
.filter(a -> d.size() > 1000 || d.stream() .filter(a -> d.size() > 1000 || d.stream()
.noneMatch(i -> i.account.url.equals(a.url))) .noneMatch(i -> i.account.url.equals(a.url)))

View File

@@ -19,7 +19,6 @@ import me.grishka.appkit.utils.MergeRecyclerAdapter;
public class BubbleTimelineFragment extends StatusListFragment { public class BubbleTimelineFragment extends StatusListFragment {
private DiscoverInfoBannerHelper bannerHelper; private DiscoverInfoBannerHelper bannerHelper;
private String maxID;
@Override @Override
public void onCreate(Bundle savedInstanceState){ public void onCreate(Bundle savedInstanceState){
@@ -35,15 +34,14 @@ public class BubbleTimelineFragment extends StatusListFragment {
@Override @Override
protected void doLoadData(int offset, int count){ protected void doLoadData(int offset, int count){
currentRequest=new GetBubbleTimeline(refreshing ? null : maxID, count, getLocalPrefs().timelineReplyVisibility) currentRequest=new GetBubbleTimeline(getMaxID(), count, getLocalPrefs().timelineReplyVisibility)
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
if(getActivity()==null) return; if(getActivity()==null) return;
boolean empty=result.isEmpty(); boolean more=applyMaxID(result);
if(!empty) maxID=result.get(result.size()-1).id;
AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext()); AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext());
onDataLoaded(result, !empty); onDataLoaded(result, more);
bannerHelper.onBannerBecameVisible(); bannerHelper.onBannerBecameVisible();
} }
}) })

View File

@@ -77,7 +77,7 @@ public class DiscoverAccountsFragment extends MastodonRecyclerFragment<DiscoverA
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(List<FollowSuggestion> result){ public void onSuccess(List<FollowSuggestion> result){
if (getActivity() == null) return; if(getActivity()==null) return;
onDataLoaded(result.stream().map(fs->new AccountWrapper(fs.account)).collect(Collectors.toList()), false); onDataLoaded(result.stream().map(fs->new AccountWrapper(fs.account)).collect(Collectors.toList()), false);
loadRelationships(); loadRelationships();
} }
@@ -112,7 +112,7 @@ public class DiscoverAccountsFragment extends MastodonRecyclerFragment<DiscoverA
public void onSuccess(List<Relationship> result){ public void onSuccess(List<Relationship> result){
relationshipsRequest=null; relationshipsRequest=null;
relationships=result.stream().collect(Collectors.toMap(rel->rel.id, Function.identity())); relationships=result.stream().collect(Collectors.toMap(rel->rel.id, Function.identity()));
if (getActivity() == null) return; if(getActivity()==null) return;
if(list==null) if(list==null)
return; return;
for(int i=0;i<list.getChildCount();i++){ for(int i=0;i<list.getChildCount();i++){

View File

@@ -96,8 +96,6 @@ public class DiscoverFragment extends AppKitFragment implements ScrollableToTop,
pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback(){ pager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback(){
@Override @Override
public void onPageSelected(int position){ public void onPageSelected(int position){
if(position==0)
return;
Fragment _page=getFragmentForPage(position); Fragment _page=getFragmentForPage(position);
if(_page instanceof BaseRecyclerFragment<?> page){ if(_page instanceof BaseRecyclerFragment<?> page){
if(!page.loaded && !page.isDataLoading()) if(!page.loaded && !page.isDataLoading())

View File

@@ -18,6 +18,7 @@ import me.grishka.appkit.utils.MergeRecyclerAdapter;
public class DiscoverPostsFragment extends StatusListFragment{ public class DiscoverPostsFragment extends StatusListFragment{
private DiscoverInfoBannerHelper bannerHelper; private DiscoverInfoBannerHelper bannerHelper;
private int offset;
@Override @Override
public void onCreate(Bundle savedInstanceState){ public void onCreate(Bundle savedInstanceState){
@@ -26,13 +27,15 @@ public class DiscoverPostsFragment extends StatusListFragment{
} }
@Override @Override
protected void doLoadData(int offset, int count){ protected void doLoadData(int o, int count){
if(refreshing) offset=0;
currentRequest=new GetTrendingStatuses(offset, count) currentRequest=new GetTrendingStatuses(offset, count)
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
if(getActivity()==null) return; if(getActivity()==null) return;
boolean empty=result.isEmpty(); boolean empty=result.isEmpty();
offset+=result.size();
AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext()); AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext());
onDataLoaded(result, !empty); onDataLoaded(result, !empty);
bannerHelper.onBannerBecameVisible(); bannerHelper.onBannerBecameVisible();

View File

@@ -29,15 +29,14 @@ public class FederatedTimelineFragment extends StatusListFragment{
@Override @Override
protected void doLoadData(int offset, int count){ protected void doLoadData(int offset, int count){
currentRequest=new GetPublicTimeline(false, false, refreshing ? null : maxID, count, getLocalPrefs().timelineReplyVisibility) currentRequest=new GetPublicTimeline(false, false, getMaxID(), count, getLocalPrefs().timelineReplyVisibility)
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
if(getActivity()==null) return; if(getActivity()==null) return;
boolean empty=result.isEmpty(); boolean more=applyMaxID(result);
if(!empty) maxID=result.get(result.size()-1).id;
AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext()); AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext());
onDataLoaded(result, !empty); onDataLoaded(result, more);
bannerHelper.onBannerBecameVisible(); bannerHelper.onBannerBecameVisible();
} }
}) })

View File

@@ -29,15 +29,14 @@ public class LocalTimelineFragment extends StatusListFragment{
@Override @Override
protected void doLoadData(int offset, int count){ protected void doLoadData(int offset, int count){
currentRequest=new GetPublicTimeline(true, false, refreshing ? null : maxID, count, getLocalPrefs().timelineReplyVisibility) currentRequest=new GetPublicTimeline(true, false, getMaxID(), count, getLocalPrefs().timelineReplyVisibility)
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
if(getActivity()==null) return; if(getActivity()==null) return;
boolean empty=result.isEmpty(); boolean more=applyMaxID(result);
if(!empty) maxID=result.get(result.size()-1).id;
AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext()); AccountSessionManager.get(accountID).filterStatuses(result, getFilterContext());
onDataLoaded(result, !empty); onDataLoaded(result, more);
bannerHelper.onBannerBecameVisible(); bannerHelper.onBannerBecameVisible();
} }
}) })

View File

@@ -83,7 +83,7 @@ public class ReportAddPostsChoiceFragment extends StatusListFragment{
@Override @Override
protected void doLoadData(int offset, int count){ protected void doLoadData(int offset, int count){
currentRequest=new GetAccountStatuses(reportAccount.id, offset>0 ? getMaxID() : null, null, count, GetAccountStatuses.Filter.OWN_POSTS_AND_REPLIES) currentRequest=new GetAccountStatuses(reportAccount.id, getMaxID(), null, count, GetAccountStatuses.Filter.OWN_POSTS_AND_REPLIES)
.setCallback(new SimpleCallback<>(this){ .setCallback(new SimpleCallback<>(this){
@Override @Override
public void onSuccess(List<Status> result){ public void onSuccess(List<Status> result){
@@ -104,8 +104,8 @@ public class ReportAddPostsChoiceFragment extends StatusListFragment{
else else
selectedIDs.add(id); selectedIDs.add(id);
CheckableHeaderStatusDisplayItem.Holder holder=findHolderOfType(id, CheckableHeaderStatusDisplayItem.Holder.class); CheckableHeaderStatusDisplayItem.Holder holder=findHolderOfType(id, CheckableHeaderStatusDisplayItem.Holder.class);
if(holder!=null) if(holder!=null) holder.rebind();
holder.rebind(); else notifyItemChanged(id, CheckableHeaderStatusDisplayItem.class);
} }
@Override @Override

View File

@@ -97,7 +97,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
public void onViewCreated(View view, Bundle savedInstanceState){ public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
fab=view.findViewById(R.id.fab); fab=view.findViewById(R.id.fab);
fab.setImageResource(R.drawable.ic_add_24px); fab.setImageResource(R.drawable.ic_fluent_add_24_regular);
fab.setContentDescription(getString(R.string.add_muted_word)); fab.setContentDescription(getString(R.string.add_muted_word));
fab.setOnClickListener(v->onFabClick()); fab.setOnClickListener(v->onFabClick());
} }

View File

@@ -1,6 +1,7 @@
package org.joinmastodon.android.fragments.settings; package org.joinmastodon.android.fragments.settings;
import android.app.Activity; import android.app.Activity;
import android.app.AlertDialog;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.os.Build; import android.os.Build;
@@ -28,6 +29,8 @@ import org.joinmastodon.android.ui.views.TextInputFrameLayout;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream; import java.util.stream.IntStream;
import me.grishka.appkit.FragmentStackActivity; import me.grishka.appkit.FragmentStackActivity;
@@ -38,7 +41,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
private CheckableListItem<Void> revealCWsItem, hideSensitiveMediaItem, interactionCountsItem, emojiInNamesItem; private CheckableListItem<Void> revealCWsItem, hideSensitiveMediaItem, interactionCountsItem, emojiInNamesItem;
// MEGALODON // MEGALODON
private CheckableListItem<Void> trueBlackModeItem, marqueeItem, disableSwipeItem, reduceMotionItem, altIndicatorItem, noAltIndicatorItem, collapsePostsItem, spectatorModeItem, hideFabItem, translateOpenedItem, disablePillItem, showNavigationLabelsItem, likeIconItem; private CheckableListItem<Void> trueBlackModeItem, marqueeItem, disableSwipeItem, reduceMotionItem, altIndicatorItem, noAltIndicatorItem, collapsePostsItem, spectatorModeItem, hideFabItem, translateOpenedItem, disablePillItem, showNavigationLabelsItem, likeIconItem, underlinedLinksItem;
private ListItem<Void> colorItem, publishTextItem, autoRevealCWsItem; private ListItem<Void> colorItem, publishTextItem, autoRevealCWsItem;
private CheckableListItem<Void> pronounsInUserListingsItem, pronounsInTimelinesItem, pronounsInThreadsItem; private CheckableListItem<Void> pronounsInUserListingsItem, pronounsInTimelinesItem, pronounsInThreadsItem;
@@ -52,7 +55,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
lp=s.getLocalPreferences(); lp=s.getLocalPreferences();
onDataLoaded(List.of( onDataLoaded(List.of(
themeItem=new ListItem<>(R.string.settings_theme, getAppearanceValue(), R.drawable.ic_fluent_weather_moon_24_regular, this::onAppearanceClick), themeItem=new ListItem<>(R.string.settings_theme, getAppearanceValue(), R.drawable.ic_fluent_weather_moon_24_regular, this::onAppearanceClick),
colorItem=new ListItem<>(R.string.sk_settings_color_palette, getColorPaletteValue(), R.drawable.ic_fluent_color_24_regular, this::onColorClick), colorItem=new ListItem<>(getString(R.string.sk_settings_color_palette), getColorPaletteValue(), R.drawable.ic_fluent_color_24_regular, this::onColorClick),
trueBlackModeItem=new CheckableListItem<>(R.string.sk_settings_true_black, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.trueBlackTheme, R.drawable.ic_fluent_dark_theme_24_regular, this::onTrueBlackModeClick, true), trueBlackModeItem=new CheckableListItem<>(R.string.sk_settings_true_black, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.trueBlackTheme, R.drawable.ic_fluent_dark_theme_24_regular, this::onTrueBlackModeClick, true),
publishTextItem=new ListItem<>(getString(R.string.sk_settings_publish_button_text), getPublishButtonText(), R.drawable.ic_fluent_send_24_regular, this::onPublishTextClick), publishTextItem=new ListItem<>(getString(R.string.sk_settings_publish_button_text), getPublishButtonText(), R.drawable.ic_fluent_send_24_regular, this::onPublishTextClick),
autoRevealCWsItem=new ListItem<>(R.string.sk_settings_auto_reveal_equal_spoilers, getAutoRevealSpoilersText(), R.drawable.ic_fluent_eye_24_regular, this::onAutoRevealSpoilersClick), autoRevealCWsItem=new ListItem<>(R.string.sk_settings_auto_reveal_equal_spoilers, getAutoRevealSpoilersText(), R.drawable.ic_fluent_eye_24_regular, this::onAutoRevealSpoilersClick),
@@ -69,8 +72,9 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
spectatorModeItem=new CheckableListItem<>(R.string.sk_settings_hide_interaction, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.spectatorMode, R.drawable.ic_fluent_star_off_24_regular, ()->toggleCheckableItem(spectatorModeItem)), spectatorModeItem=new CheckableListItem<>(R.string.sk_settings_hide_interaction, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.spectatorMode, R.drawable.ic_fluent_star_off_24_regular, ()->toggleCheckableItem(spectatorModeItem)),
hideFabItem=new CheckableListItem<>(R.string.sk_settings_hide_fab, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.autoHideFab, R.drawable.ic_fluent_edit_24_regular, ()->toggleCheckableItem(hideFabItem)), hideFabItem=new CheckableListItem<>(R.string.sk_settings_hide_fab, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.autoHideFab, R.drawable.ic_fluent_edit_24_regular, ()->toggleCheckableItem(hideFabItem)),
translateOpenedItem=new CheckableListItem<>(R.string.sk_settings_translate_only_opened, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.translateButtonOpenedOnly, R.drawable.ic_fluent_translate_24_regular, ()->toggleCheckableItem(translateOpenedItem)), translateOpenedItem=new CheckableListItem<>(R.string.sk_settings_translate_only_opened, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.translateButtonOpenedOnly, R.drawable.ic_fluent_translate_24_regular, ()->toggleCheckableItem(translateOpenedItem)),
likeIconItem=new CheckableListItem<>(R.string.sk_settings_like_icon, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.likeIcon, R.drawable.ic_fluent_heart_24_regular, ()->toggleCheckableItem(likeIconItem)),
underlinedLinksItem=new CheckableListItem<>(R.string.sk_settings_underlined_links, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.underlinedLinks, R.drawable.ic_fluent_text_underline_24_regular, ()->toggleCheckableItem(underlinedLinksItem)),
disablePillItem=new CheckableListItem<>(R.string.sk_disable_pill_shaped_active_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableM3PillActiveIndicator, R.drawable.ic_fluent_pill_24_regular, ()->toggleCheckableItem(disablePillItem)), disablePillItem=new CheckableListItem<>(R.string.sk_disable_pill_shaped_active_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableM3PillActiveIndicator, R.drawable.ic_fluent_pill_24_regular, ()->toggleCheckableItem(disablePillItem)),
likeIconItem=new CheckableListItem<>(R.string.sk_settings_like_icon, 0, CheckableListItem.Style.SWITCH, lp.likeIcon, R.drawable.ic_fluent_heart_24_regular, ()->toggleCheckableItem(likeIconItem)),
showNavigationLabelsItem=new CheckableListItem<>(R.string.sk_settings_show_labels_in_navigation_bar, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNavigationLabels, R.drawable.ic_fluent_tag_24_regular, ()->toggleCheckableItem(showNavigationLabelsItem), true), showNavigationLabelsItem=new CheckableListItem<>(R.string.sk_settings_show_labels_in_navigation_bar, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNavigationLabels, R.drawable.ic_fluent_tag_24_regular, ()->toggleCheckableItem(showNavigationLabelsItem), true),
pronounsInTimelinesItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_timelines, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInTimelines, 0, ()->toggleCheckableItem(pronounsInTimelinesItem)), pronounsInTimelinesItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_timelines, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInTimelines, 0, ()->toggleCheckableItem(pronounsInTimelinesItem)),
pronounsInThreadsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_threads, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInThreads, 0, ()->toggleCheckableItem(pronounsInThreadsItem)), pronounsInThreadsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_threads, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInThreads, 0, ()->toggleCheckableItem(pronounsInThreadsItem)),
@@ -96,16 +100,14 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
protected void onHidden(){ protected void onHidden(){
super.onHidden(); super.onHidden();
boolean restartPlease= boolean restartPlease=GlobalUserPreferences.disableM3PillActiveIndicator!=disablePillItem.checked
GlobalUserPreferences.disableM3PillActiveIndicator!=disablePillItem.checked || || GlobalUserPreferences.showNavigationLabels!=showNavigationLabelsItem.checked
GlobalUserPreferences.showNavigationLabels!=showNavigationLabelsItem.checked || || GlobalUserPreferences.likeIcon!=likeIconItem.checked;
lp.likeIcon!=likeIconItem.checked;
lp.revealCWs=revealCWsItem.checked; lp.revealCWs=revealCWsItem.checked;
lp.hideSensitiveMedia=hideSensitiveMediaItem.checked; lp.hideSensitiveMedia=hideSensitiveMediaItem.checked;
lp.showInteractionCounts=interactionCountsItem.checked; lp.showInteractionCounts=interactionCountsItem.checked;
lp.customEmojiInNames=emojiInNamesItem.checked; lp.customEmojiInNames=emojiInNamesItem.checked;
lp.likeIcon=likeIconItem.checked;
lp.save(); lp.save();
GlobalUserPreferences.toolbarMarquee=marqueeItem.checked; GlobalUserPreferences.toolbarMarquee=marqueeItem.checked;
GlobalUserPreferences.reduceMotion=reduceMotionItem.checked; GlobalUserPreferences.reduceMotion=reduceMotionItem.checked;
@@ -116,6 +118,8 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
GlobalUserPreferences.spectatorMode=spectatorModeItem.checked; GlobalUserPreferences.spectatorMode=spectatorModeItem.checked;
GlobalUserPreferences.autoHideFab=hideFabItem.checked; GlobalUserPreferences.autoHideFab=hideFabItem.checked;
GlobalUserPreferences.translateButtonOpenedOnly=translateOpenedItem.checked; GlobalUserPreferences.translateButtonOpenedOnly=translateOpenedItem.checked;
GlobalUserPreferences.likeIcon=likeIconItem.checked;
GlobalUserPreferences.underlinedLinks=underlinedLinksItem.checked;
GlobalUserPreferences.disableM3PillActiveIndicator=disablePillItem.checked; GlobalUserPreferences.disableM3PillActiveIndicator=disablePillItem.checked;
GlobalUserPreferences.showNavigationLabels=showNavigationLabelsItem.checked; GlobalUserPreferences.showNavigationLabels=showNavigationLabelsItem.checked;
GlobalUserPreferences.displayPronounsInTimelines=pronounsInTimelinesItem.checked; GlobalUserPreferences.displayPronounsInTimelines=pronounsInTimelinesItem.checked;
@@ -134,17 +138,11 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
}; };
} }
private @StringRes int getColorPaletteValue(){ private String getColorPaletteValue(){
return switch(AccountSessionManager.get(accountID).getLocalPreferences().color){ ColorPreference color=AccountSessionManager.get(accountID).getLocalPreferences().color;
case MATERIAL3 -> R.string.sk_color_palette_material3; return color==null
case PINK -> R.string.sk_color_palette_pink; ? getString(R.string.sk_settings_color_palette_default, getString(GlobalUserPreferences.color.getName()))
case PURPLE -> R.string.sk_color_palette_purple; : getString(color.getName());
case GREEN -> R.string.sk_color_palette_green;
case BLUE -> R.string.sk_color_palette_blue;
case BROWN -> R.string.sk_color_palette_brown;
case RED -> R.string.sk_color_palette_red;
case YELLOW -> R.string.sk_color_palette_yellow;
};
} }
private String getPublishButtonText() { private String getPublishButtonText() {
@@ -200,26 +198,40 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
} }
private void onColorClick(){ private void onColorClick(){
int selected=lp.color.ordinal(); boolean multiple=AccountSessionManager.getInstance().getLoggedInAccounts().size() > 1;
int indexOffset=multiple ? 1 : 0;
int selected=lp.color==null ? 0 : lp.color.ordinal() + indexOffset;
int[] newSelected={selected}; int[] newSelected={selected};
String[] names=Arrays.stream(ColorPreference.values()).map(ColorPreference::getName).map(this::getString).toArray(String[]::new); List<String> items=Arrays.stream(ColorPreference.values()).map(ColorPreference::getName).map(this::getString).collect(Collectors.toList());
new M3AlertDialogBuilder(getActivity()) if(multiple)
items.add(0, getString(R.string.sk_settings_color_palette_default, items.get(GlobalUserPreferences.color.ordinal())));
Consumer<Boolean> save=(asDefault)->{
boolean defaultSelected=multiple && newSelected[0]==0;
ColorPreference pref=defaultSelected ? null : ColorPreference.values()[newSelected[0]-indexOffset];
if(pref!=lp.color){
ColorPreference prev=lp.color;
lp.color=asDefault ? null : pref;
lp.save();
if((asDefault || !multiple) && pref!=null){
GlobalUserPreferences.color=pref;
GlobalUserPreferences.save();
}
colorItem.subtitle=getColorPaletteValue();
rebindItem(colorItem);
if(prev==null && pref!=null) restartActivityToApplyNewTheme();
else maybeApplyNewThemeRightNow(null, prev, null);
}
};
AlertDialog.Builder alert=new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_settings_color_palette) .setTitle(R.string.sk_settings_color_palette)
.setSingleChoiceItems(names, .setSingleChoiceItems(items.toArray(String[]::new),
selected, (dlg, item)->newSelected[0]=item) selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->{ .setPositiveButton(R.string.ok, (dlg, item)->save.accept(false))
ColorPreference pref=ColorPreference.values()[newSelected[0]]; .setNegativeButton(R.string.cancel, null);
if(pref!=lp.color){ if(multiple) alert.setNeutralButton(R.string.sk_set_as_default, (dlg, item)->save.accept(true));
ColorPreference prev=lp.color; alert.show();
lp.color=pref;
GlobalUserPreferences.save();
colorItem.subtitleRes=getColorPaletteValue();
rebindItem(colorItem);
maybeApplyNewThemeRightNow(null, prev, null);
}
})
.setNegativeButton(R.string.cancel, null)
.show();
} }
private void onPublishTextClick(){ private void onPublishTextClick(){
@@ -264,14 +276,14 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
private void maybeApplyNewThemeRightNow(GlobalUserPreferences.ThemePreference prevTheme, ColorPreference prevColor, Boolean prevTrueBlack){ private void maybeApplyNewThemeRightNow(GlobalUserPreferences.ThemePreference prevTheme, ColorPreference prevColor, Boolean prevTrueBlack){
if(prevTheme==null) prevTheme=GlobalUserPreferences.theme; if(prevTheme==null) prevTheme=GlobalUserPreferences.theme;
if(prevTrueBlack==null) prevTrueBlack=GlobalUserPreferences.trueBlackTheme; if(prevTrueBlack==null) prevTrueBlack=GlobalUserPreferences.trueBlackTheme;
if(prevColor==null) prevColor=lp.color; if(prevColor==null) prevColor=lp.getCurrentColor();
boolean isCurrentDark=prevTheme==GlobalUserPreferences.ThemePreference.DARK || boolean isCurrentDark=prevTheme==GlobalUserPreferences.ThemePreference.DARK ||
(prevTheme==GlobalUserPreferences.ThemePreference.AUTO && Build.VERSION.SDK_INT>=30 && getResources().getConfiguration().isNightModeActive()); (prevTheme==GlobalUserPreferences.ThemePreference.AUTO && Build.VERSION.SDK_INT>=30 && getResources().getConfiguration().isNightModeActive());
boolean isNewDark=GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.DARK || boolean isNewDark=GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.DARK ||
(GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.AUTO && Build.VERSION.SDK_INT>=30 && getResources().getConfiguration().isNightModeActive()); (GlobalUserPreferences.theme==GlobalUserPreferences.ThemePreference.AUTO && Build.VERSION.SDK_INT>=30 && getResources().getConfiguration().isNightModeActive());
boolean isNewBlack=GlobalUserPreferences.trueBlackTheme; boolean isNewBlack=GlobalUserPreferences.trueBlackTheme;
if(isCurrentDark!=isNewDark || prevColor!=lp.color || (isNewDark && prevTrueBlack!=isNewBlack)){ if(isCurrentDark!=isNewDark || prevColor!=lp.getCurrentColor() || (isNewDark && prevTrueBlack!=isNewBlack)){
restartActivityToApplyNewTheme(); restartActivityToApplyNewTheme();
} }
} }

View File

@@ -55,7 +55,7 @@ public class SettingsFiltersFragment extends BaseSettingsFragment<Filter>{
MergeRecyclerAdapter adapter=new MergeRecyclerAdapter(); MergeRecyclerAdapter adapter=new MergeRecyclerAdapter();
adapter.addAdapter(super.getAdapter()); adapter.addAdapter(super.getAdapter());
adapter.addAdapter(new GenericListItemsAdapter<>(Collections.singletonList( adapter.addAdapter(new GenericListItemsAdapter<>(Collections.singletonList(
new ListItem<Void>(R.string.settings_add_filter, 0, R.drawable.ic_add_24px, this::onAddFilterClick) new ListItem<Void>(R.string.settings_add_filter, 0, R.drawable.ic_fluent_add_24_regular, this::onAddFilterClick)
))); )));
return adapter; return adapter;
} }

View File

@@ -55,8 +55,7 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
onDataLoaded(List.of( onDataLoaded(List.of(
new ListItem<>(R.string.settings_behavior, 0, R.drawable.ic_fluent_settings_24_regular, this::onBehaviorClick), new ListItem<>(R.string.settings_behavior, 0, R.drawable.ic_fluent_settings_24_regular, this::onBehaviorClick),
new ListItem<>(R.string.settings_display, 0, R.drawable.ic_fluent_color_24_regular, this::onDisplayClick), new ListItem<>(R.string.settings_display, 0, R.drawable.ic_fluent_color_24_regular, this::onDisplayClick),
new ListItem<>(R.string.settings_privacy, 0, R.drawable.ic_privacy_tip_24px, this::onPrivacyClick), new ListItem<>(R.string.settings_privacy, 0, R.drawable.ic_fluent_shield_24_regular, this::onPrivacyClick),
new ListItem<>(R.string.settings_filters, 0, R.drawable.ic_filter_alt_24px, this::onFiltersClick),
new ListItem<>(R.string.settings_notifications, 0, R.drawable.ic_fluent_alert_24_regular, this::onNotificationsClick), new ListItem<>(R.string.settings_notifications, 0, R.drawable.ic_fluent_alert_24_regular, this::onNotificationsClick),
new ListItem<>(R.string.sk_settings_instance, 0, R.drawable.ic_fluent_server_24_regular, this::onInstanceClick), new ListItem<>(R.string.sk_settings_instance, 0, R.drawable.ic_fluent_server_24_regular, this::onInstanceClick),
new ListItem<>(getString(R.string.about_app, getString(R.string.sk_app_name)), null, R.drawable.ic_fluent_info_24_regular, this::onAboutClick, null, 0, true), new ListItem<>(getString(R.string.about_app, getString(R.string.sk_app_name)), null, R.drawable.ic_fluent_info_24_regular, this::onAboutClick, null, 0, true),
@@ -65,7 +64,7 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
Instance instance = AccountSessionManager.getInstance().getInstanceInfo(account.domain); Instance instance = AccountSessionManager.getInstance().getInstanceInfo(account.domain);
if (!instance.isAkkoma()) if (!instance.isAkkoma())
data.add(2, new ListItem<>(R.string.settings_filters, 0, R.drawable.ic_fluent_filter_24_regular, this::onFiltersClick)); data.add(3, new ListItem<>(R.string.settings_filters, 0, R.drawable.ic_fluent_filter_24_regular, this::onFiltersClick));
if(BuildConfig.DEBUG || BuildConfig.BUILD_TYPE.equals("appcenterPrivateBeta")){ if(BuildConfig.DEBUG || BuildConfig.BUILD_TYPE.equals("appcenterPrivateBeta")){
data.add(0, new ListItem<>("Debug settings", null, R.drawable.ic_fluent_wrench_screwdriver_24_regular, ()->Nav.go(getActivity(), SettingsDebugFragment.class, makeFragmentArgs()), null, 0, true)); data.add(0, new ListItem<>("Debug settings", null, R.drawable.ic_fluent_wrench_screwdriver_24_regular, ()->Nav.go(getActivity(), SettingsDebugFragment.class, makeFragmentArgs()), null, 0, true));

View File

@@ -18,8 +18,8 @@ public class SettingsPrivacyFragment extends BaseSettingsFragment<Void>{
setTitle(R.string.settings_privacy); setTitle(R.string.settings_privacy);
Account self=AccountSessionManager.get(accountID).self; Account self=AccountSessionManager.get(accountID).self;
onDataLoaded(List.of( onDataLoaded(List.of(
discoverableItem=new CheckableListItem<>(R.string.settings_discoverable, 0, CheckableListItem.Style.SWITCH, self.discoverable, R.drawable.ic_thumbs_up_down_24px, ()->toggleCheckableItem(discoverableItem)), discoverableItem=new CheckableListItem<>(R.string.settings_discoverable, 0, CheckableListItem.Style.SWITCH, self.discoverable, R.drawable.ic_fluent_thumb_like_dislike_24_regular, ()->toggleCheckableItem(discoverableItem)),
indexableItem=new CheckableListItem<>(R.string.settings_indexable, 0, CheckableListItem.Style.SWITCH, self.source.indexable!=null ? self.source.indexable : true, R.drawable.ic_search_24px, ()->toggleCheckableItem(indexableItem)) indexableItem=new CheckableListItem<>(R.string.settings_indexable, 0, CheckableListItem.Style.SWITCH, self.source.indexable!=null ? self.source.indexable : true, R.drawable.ic_fluent_search_24_regular, ()->toggleCheckableItem(indexableItem))
)); ));
if(self.source.indexable==null) if(self.source.indexable==null)
indexableItem.isEnabled=false; indexableItem.isEnabled=false;

View File

@@ -52,7 +52,7 @@ public class Announcement extends BaseModel implements DisplayItemsParent {
public Status toStatus() { public Status toStatus() {
Status s=Status.ofFake(id, content, publishedAt); Status s=Status.ofFake(id, content, publishedAt);
s.createdAt=startsAt != null ? startsAt : publishedAt; s.createdAt=startsAt != null ? startsAt : publishedAt;
s.reactions=reactions; s.reactions=reactions;
if(updatedAt != null) s.editedAt=updatedAt; if(updatedAt != null) s.editedAt=updatedAt;
return s; return s;

View File

@@ -100,7 +100,7 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
public transient boolean spoilerRevealed; public transient boolean spoilerRevealed;
public transient boolean sensitiveRevealed; public transient boolean sensitiveRevealed;
public transient boolean textExpanded, textExpandable; public transient boolean textExpanded, textExpandable;
public transient boolean hasGapAfter; public transient String hasGapAfter;
private transient String strippedText; private transient String strippedText;
public transient TranslationState translationState=TranslationState.HIDDEN; public transient TranslationState translationState=TranslationState.HIDDEN;
public transient Translation translation; public transient Translation translation;

View File

@@ -43,7 +43,7 @@ public class AccountCardStatusDisplayItem extends StatusDisplayItem{
public CharSequence parsedName, parsedBio; public CharSequence parsedName, parsedBio;
public AccountCardStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, String accountID, Account account, Notification notification){ public AccountCardStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, String accountID, Account account, Notification notification){
super(parentID, parentFragment); super(parentID, null, parentFragment);
this.account=account; this.account=account;
this.notification=notification; this.notification=notification;
avaRequest=new UrlImageLoaderRequest( avaRequest=new UrlImageLoaderRequest(

View File

@@ -14,7 +14,7 @@ public class AccountStatusDisplayItem extends StatusDisplayItem{
public final AccountViewModel account; public final AccountViewModel account;
public AccountStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Account account){ public AccountStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Account account){
super(parentID, parentFragment); super(parentID, null, parentFragment);
this.account=new AccountViewModel(account, parentFragment.getAccountID()); this.account=new AccountViewModel(account, parentFragment.getAccountID());
} }

View File

@@ -37,7 +37,7 @@ public class AudioStatusDisplayItem extends StatusDisplayItem{
private final ImageLoaderRequest imageRequest; private final ImageLoaderRequest imageRequest;
public AudioStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status, Attachment attachment){ public AudioStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status, Attachment attachment){
super(parentID, parentFragment); super(parentID, status.id, parentFragment);
this.status=status; this.status=status;
this.attachment=attachment; this.attachment=attachment;
imageRequest=new UrlImageLoaderRequest(TextUtils.isEmpty(attachment.previewUrl) ? status.account.avatarStatic : attachment.previewUrl, V.dp(100), V.dp(100)); imageRequest=new UrlImageLoaderRequest(TextUtils.isEmpty(attachment.previewUrl) ? status.account.avatarStatic : attachment.previewUrl, V.dp(100), V.dp(100));

View File

@@ -12,8 +12,8 @@ import me.grishka.appkit.utils.V;
public class DummyStatusDisplayItem extends StatusDisplayItem { public class DummyStatusDisplayItem extends StatusDisplayItem {
public DummyStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment) { public DummyStatusDisplayItem(String parentID, String contentStatusID, BaseStatusListFragment<?> parentFragment) {
super(parentID, parentFragment); super(parentID, contentStatusID, parentFragment);
} }
@Override @Override

View File

@@ -65,7 +65,7 @@ public class EmojiReactionsStatusDisplayItem extends StatusDisplayItem {
private static final float ALPHA_DISABLED=0.55f; private static final float ALPHA_DISABLED=0.55f;
public EmojiReactionsStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status, String accountID, boolean hideEmpty, boolean forAnnouncement) { public EmojiReactionsStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status, String accountID, boolean hideEmpty, boolean forAnnouncement) {
super(parentID, parentFragment); super(parentID, status.id, parentFragment);
this.status=status; this.status=status;
this.hideEmpty=hideEmpty; this.hideEmpty=hideEmpty;
this.forAnnouncement=forAnnouncement; this.forAnnouncement=forAnnouncement;

View File

@@ -13,6 +13,7 @@ import android.widget.Button;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
@@ -41,7 +42,7 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
private static final DateTimeFormatter TIME_FORMATTER=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT); private static final DateTimeFormatter TIME_FORMATTER=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT);
public ExtendedFooterStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, String accountID, Status status){ public ExtendedFooterStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, String accountID, Status status){
super(parentID, parentFragment); super(parentID, status.id, parentFragment);
this.status=status; this.status=status;
this.accountID=accountID; this.accountID=accountID;
} }
@@ -76,9 +77,7 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
@Override @Override
public void onBind(ExtendedFooterStatusDisplayItem item){ public void onBind(ExtendedFooterStatusDisplayItem item){
Status s=item.status; Status s=item.status;
AccountSession session=AccountSessionManager.get(item.accountID); favorites.setCompoundDrawablesRelativeWithIntrinsicBounds(GlobalUserPreferences.likeIcon ? R.drawable.ic_fluent_heart_20_regular : R.drawable.ic_fluent_star_20_regular, 0, 0, 0);
boolean like=session!=null && session.getLocalPreferences().likeIcon;
favorites.setCompoundDrawablesRelativeWithIntrinsicBounds(like ? R.drawable.ic_fluent_heart_20_regular : R.drawable.ic_fluent_star_20_regular, 0, 0, 0);
favorites.setText(context.getResources().getQuantityString(R.plurals.x_favorites, (int)(s.favouritesCount%1000), s.favouritesCount)); favorites.setText(context.getResources().getQuantityString(R.plurals.x_favorites, (int)(s.favouritesCount%1000), s.favouritesCount));
reblogs.setText(context.getResources().getQuantityString(R.plurals.x_reblogs, (int) (s.reblogsCount % 1000), s.reblogsCount)); reblogs.setText(context.getResources().getQuantityString(R.plurals.x_reblogs, (int) (s.reblogsCount % 1000), s.reblogsCount));
reblogs.setVisibility(s.visibility != StatusPrivacy.DIRECT ? View.VISIBLE : View.GONE); reblogs.setVisibility(s.visibility != StatusPrivacy.DIRECT ? View.VISIBLE : View.GONE);

View File

@@ -1,29 +1,22 @@
package org.joinmastodon.android.ui.displayitems; package org.joinmastodon.android.ui.displayitems;
import android.content.Context; import android.content.Context;
import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Attachment; import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.Card;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.drawables.BlurhashCrossfadeDrawable;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
public class FileStatusDisplayItem extends StatusDisplayItem{ public class FileStatusDisplayItem extends StatusDisplayItem{
private final Attachment attachment; private final Attachment attachment;
public FileStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Attachment attachment) { public FileStatusDisplayItem(String parentID, String contentStatusID, BaseStatusListFragment<?> parentFragment, Attachment attachment) {
super(parentID, parentFragment); super(parentID, contentStatusID, parentFragment);
this.attachment=attachment; this.attachment=attachment;
} }

View File

@@ -43,7 +43,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
public boolean hideCounts; public boolean hideCounts;
public FooterStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status, String accountID){ public FooterStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status, String accountID){
super(parentID, parentFragment); super(parentID, status.id, parentFragment);
this.status=status; this.status=status;
this.accountID=accountID; this.accountID=accountID;
} }
@@ -133,13 +133,10 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
boolean condenseBottom = !item.isMainStatus && item.hasDescendantNeighbor && boolean condenseBottom = !item.isMainStatus && item.hasDescendantNeighbor &&
!nextIsWarning; !nextIsWarning;
AccountSession session=AccountSessionManager.get(item.accountID);
boolean like=session!=null && session.getLocalPreferences().likeIcon;
ColorStateList color=item.parentFragment.getResources().getColorStateList( ColorStateList color=item.parentFragment.getResources().getColorStateList(
like ? R.color.like_icon : R.color.favorite_icon, item.parentFragment.getContext().getTheme() GlobalUserPreferences.likeIcon ? R.color.like_icon : R.color.favorite_icon, item.parentFragment.getContext().getTheme()
); );
favIcon.setImageResource(like ? R.drawable.ic_fluent_heart_24_selector : R.drawable.ic_fluent_star_24_selector); favIcon.setImageResource(GlobalUserPreferences.likeIcon ? R.drawable.ic_fluent_heart_24_selector : R.drawable.ic_fluent_star_24_selector);
favIcon.setImageTintList(color); favIcon.setImageTintList(color);
favorites.setTextColor(color); favorites.setTextColor(color);
@@ -175,7 +172,6 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
} else if (action == MotionEvent.ACTION_DOWN) { } else if (action == MotionEvent.ACTION_DOWN) {
longClickPerformed = false; longClickPerformed = false;
touchingView = v; touchingView = v;
v.setPivotX(V.sp(28));
v.animate().scaleX(0.85f).scaleY(0.85f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(75).start(); v.animate().scaleX(0.85f).scaleY(0.85f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(75).start();
if (disabled) return true; if (disabled) return true;
v.postDelayed(longClickRunnable, ViewConfiguration.getLongPressTimeout()); v.postDelayed(longClickRunnable, ViewConfiguration.getLongPressTimeout());
@@ -321,7 +317,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
R.string.sk_favorite_as, R.string.sk_favorite_as,
R.string.sk_favorited_as, R.string.sk_favorited_as,
R.string.sk_already_favorited, R.string.sk_already_favorited,
R.drawable.ic_fluent_star_28_regular GlobalUserPreferences.likeIcon ? R.drawable.ic_fluent_heart_28_regular : R.drawable.ic_fluent_star_28_regular
); );
return true; return true;
} }

View File

@@ -18,13 +18,17 @@ import me.grishka.appkit.utils.V;
public class GapStatusDisplayItem extends StatusDisplayItem{ public class GapStatusDisplayItem extends StatusDisplayItem{
public boolean loading; public boolean loading;
private Status status; private final Status status;
public GapStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status){ public GapStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status){
super(parentID, parentFragment); super(parentID, null, parentFragment);
this.status=status; this.status=status;
} }
public String getMaxID(){
return status.hasGapAfter;
}
@Override @Override
public Type getType(){ public Type getType(){
return Type.GAP; return Type.GAP;
@@ -54,6 +58,8 @@ public class GapStatusDisplayItem extends StatusDisplayItem{
if(!item.loading){ if(!item.loading){
progressBottom.setVisibility(View.GONE); progressBottom.setVisibility(View.GONE);
progressTop.setVisibility(View.GONE); progressTop.setVisibility(View.GONE);
textTop.setAlpha(1);
textBottom.setAlpha(1);
} }
top.setClickable(!item.loading); top.setClickable(!item.loading);
bottom.setClickable(!item.loading); bottom.setClickable(!item.loading);

View File

@@ -14,7 +14,7 @@ public class HashtagStatusDisplayItem extends StatusDisplayItem{
public final Hashtag tag; public final Hashtag tag;
public HashtagStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Hashtag tag){ public HashtagStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Hashtag tag){
super(parentID, parentFragment); super(parentID, null, parentFragment);
this.tag=tag; this.tag=tag;
} }

View File

@@ -86,7 +86,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
private Consumer<String> consumeReadAnnouncement; private Consumer<String> consumeReadAnnouncement;
public HeaderStatusDisplayItem(String parentID, Account user, Instant createdAt, BaseStatusListFragment parentFragment, String accountID, Status status, CharSequence extraText, Notification notification, ScheduledStatus scheduledStatus){ public HeaderStatusDisplayItem(String parentID, Account user, Instant createdAt, BaseStatusListFragment parentFragment, String accountID, Status status, CharSequence extraText, Notification notification, ScheduledStatus scheduledStatus){
super(parentID, parentFragment); super(parentID, status.id, parentFragment);
AccountSession session = AccountSessionManager.get(accountID); AccountSession session = AccountSessionManager.get(accountID);
user=scheduledStatus != null ? session.self : user; user=scheduledStatus != null ? session.self : user;
this.user=user; this.user=user;
@@ -377,21 +377,32 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
markAsRead.setVisibility(View.GONE); markAsRead.setVisibility(View.GONE);
} }
if (item.status == null || !item.status.textExpandable) { bindCollapseButton();
collapseBtn.setVisibility(View.GONE);
} else {
String collapseText = item.parentFragment.getString(item.status.textExpanded ? R.string.sk_collapse : R.string.sk_expand);
collapseBtn.setVisibility(item.status.textExpandable ? View.VISIBLE : View.GONE);
collapseBtn.setContentDescription(collapseText);
if (GlobalUserPreferences.reduceMotion) collapseBtnIcon.setScaleY(item.status.textExpanded ? -1 : 1);
else collapseBtnIcon.animate().scaleY(item.status.textExpanded ? -1 : 1).start();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) collapseBtn.setTooltipText(collapseText);
}
itemView.setPaddingRelative(itemView.getPaddingStart(), itemView.getPaddingTop(), itemView.setPaddingRelative(itemView.getPaddingStart(), itemView.getPaddingTop(),
item.inset ? V.dp(10) : V.dp(4), itemView.getPaddingBottom()); item.inset ? V.dp(10) : V.dp(4), itemView.getPaddingBottom());
} }
public void bindCollapseButton(){
boolean expandable=item.status!=null && item.status.textExpandable;
collapseBtn.setVisibility(expandable ? View.VISIBLE : View.GONE);
if(expandable) {
bindCollapseButtonText();
collapseBtnIcon.setScaleY(item.status.textExpanded ? -1 : 1);
}
}
private void bindCollapseButtonText(){
String collapseText = item.parentFragment.getString(item.status.textExpanded ? R.string.sk_collapse : R.string.sk_expand);
collapseBtn.setContentDescription(collapseText);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) collapseBtn.setTooltipText(collapseText);
}
public void animateExpandToggle(){
bindCollapseButtonText();
collapseBtnIcon.animate().scaleY(item.status.textExpanded ? -1 : 1).start();
}
public void animateVisibilityToggle(boolean visible){ public void animateVisibilityToggle(boolean visible){
visibility.animate() visibility.animate()
.alpha(visible ? 1 : 0) .alpha(visible ? 1 : 0)

View File

@@ -28,7 +28,7 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
private final UrlImageLoaderRequest imgRequest; private final UrlImageLoaderRequest imgRequest;
public LinkCardStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status){ public LinkCardStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Status status){
super(parentID, parentFragment); super(parentID, status.id, parentFragment);
this.status=status; this.status=status;
if(status.card.image!=null) if(status.card.image!=null)
imgRequest=new UrlImageLoaderRequest(status.card.image, 1000, 1000); imgRequest=new UrlImageLoaderRequest(status.card.image, 1000, 1000);

View File

@@ -57,7 +57,7 @@ public class MediaGridStatusDisplayItem extends StatusDisplayItem{
public String sensitiveTitle; public String sensitiveTitle;
public MediaGridStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, PhotoLayoutHelper.TiledLayoutResult tiledLayout, List<Attachment> attachments, Status status){ public MediaGridStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, PhotoLayoutHelper.TiledLayoutResult tiledLayout, List<Attachment> attachments, Status status){
super(parentID, parentFragment); super(parentID, status.id, parentFragment);
this.tiledLayout=tiledLayout; this.tiledLayout=tiledLayout;
this.viewPool=parentFragment.getAttachmentViewsPool(); this.viewPool=parentFragment.getAttachmentViewsPool();
this.attachments=attachments; this.attachments=attachments;

View File

@@ -1,7 +1,6 @@
package org.joinmastodon.android.ui.displayitems; package org.joinmastodon.android.ui.displayitems;
import static org.joinmastodon.android.MastodonApp.context; import static org.joinmastodon.android.MastodonApp.context;
import static org.joinmastodon.android.model.Notification.Type.PLEROMA_EMOJI_REACTION;
import static org.joinmastodon.android.ui.utils.UiUtils.generateFormattedString; import static org.joinmastodon.android.ui.utils.UiUtils.generateFormattedString;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@@ -9,7 +8,6 @@ import android.app.Activity;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Bundle; import android.os.Bundle;
import android.text.Html;
import android.text.SpannableStringBuilder; import android.text.SpannableStringBuilder;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.TypedValue; import android.util.TypedValue;
@@ -20,9 +18,11 @@ import android.widget.TextView;
import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountLocalPreferences;
import org.joinmastodon.android.api.session.AccountSession; import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager; import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.BaseStatusListFragment; import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.fragments.NotificationsListFragment;
import org.joinmastodon.android.fragments.ProfileFragment; import org.joinmastodon.android.fragments.ProfileFragment;
import org.joinmastodon.android.model.Emoji; import org.joinmastodon.android.model.Emoji;
import org.joinmastodon.android.model.Notification; import org.joinmastodon.android.model.Notification;
@@ -49,7 +49,7 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{
private final CharSequence timestamp; private final CharSequence timestamp;
public NotificationHeaderStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Notification notification, String accountID){ public NotificationHeaderStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Notification notification, String accountID){
super(parentID, parentFragment); super(parentID, notification.status!=null ? notification.status.getContentStatus().id : null, parentFragment);
this.notification=notification; this.notification=notification;
this.accountID=accountID; this.accountID=accountID;
this.timestamp=notification.createdAt==null ? null : UiUtils.formatRelativeTimestamp(context, notification.createdAt); this.timestamp=notification.createdAt==null ? null : UiUtils.formatRelativeTimestamp(context, notification.createdAt);
@@ -113,7 +113,7 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{
} }
public static class Holder extends StatusDisplayItem.Holder<NotificationHeaderStatusDisplayItem> implements ImageLoaderViewHolder{ public static class Holder extends StatusDisplayItem.Holder<NotificationHeaderStatusDisplayItem> implements ImageLoaderViewHolder{
private final ImageView icon, avatar; private final ImageView icon, avatar, deleteNotification;
private final TextView text, timestamp; private final TextView text, timestamp;
private final int selectableItemBackground; private final int selectableItemBackground;
@@ -123,9 +123,15 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{
avatar=findViewById(R.id.avatar); avatar=findViewById(R.id.avatar);
text=findViewById(R.id.text); text=findViewById(R.id.text);
timestamp=findViewById(R.id.timestamp); timestamp=findViewById(R.id.timestamp);
deleteNotification=findViewById(R.id.delete_notification);
avatar.setOutlineProvider(OutlineProviders.roundedRect(8)); avatar.setOutlineProvider(OutlineProviders.roundedRect(8));
avatar.setClipToOutline(true); avatar.setClipToOutline(true);
deleteNotification.setOnClickListener(v->UiUtils.confirmDeleteNotification(activity, item.parentFragment.getAccountID(), item.notification, ()->{
if (item.parentFragment instanceof NotificationsListFragment fragment) {
fragment.removeNotification(item.notification);
}
}));
itemView.setOnClickListener(this::onItemClick); itemView.setOnClickListener(this::onItemClick);
TypedValue outValue = new TypedValue(); TypedValue outValue = new TypedValue();
@@ -158,7 +164,7 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{
timestamp.setText(item.timestamp); timestamp.setText(item.timestamp);
avatar.setVisibility(item.notification.type==Notification.Type.POLL ? View.GONE : View.VISIBLE); avatar.setVisibility(item.notification.type==Notification.Type.POLL ? View.GONE : View.VISIBLE);
icon.setImageResource(switch(item.notification.type){ icon.setImageResource(switch(item.notification.type){
case FAVORITE -> R.drawable.ic_fluent_star_24_filled; case FAVORITE -> GlobalUserPreferences.likeIcon ? R.drawable.ic_fluent_heart_24_filled : R.drawable.ic_fluent_star_24_filled;
case REBLOG -> R.drawable.ic_fluent_arrow_repeat_all_24_filled; case REBLOG -> R.drawable.ic_fluent_arrow_repeat_all_24_filled;
case FOLLOW, FOLLOW_REQUEST -> R.drawable.ic_fluent_person_add_24_filled; case FOLLOW, FOLLOW_REQUEST -> R.drawable.ic_fluent_person_add_24_filled;
case POLL -> R.drawable.ic_fluent_poll_24_filled; case POLL -> R.drawable.ic_fluent_poll_24_filled;
@@ -169,15 +175,18 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{
default -> throw new IllegalStateException("Unexpected value: "+item.notification.type); default -> throw new IllegalStateException("Unexpected value: "+item.notification.type);
}); });
icon.setImageTintList(ColorStateList.valueOf(UiUtils.getThemeColor(item.parentFragment.getActivity(), switch(item.notification.type){ icon.setImageTintList(ColorStateList.valueOf(UiUtils.getThemeColor(item.parentFragment.getActivity(), switch(item.notification.type){
case FAVORITE -> R.attr.colorFavorite; case FAVORITE -> GlobalUserPreferences.likeIcon ? R.attr.colorLike : R.attr.colorFavorite;
case REBLOG -> R.attr.colorBoost; case REBLOG -> R.attr.colorBoost;
case POLL -> R.attr.colorPoll; case POLL -> R.attr.colorPoll;
default -> android.R.attr.colorAccent; default -> android.R.attr.colorAccent;
}))); })));
deleteNotification.setVisibility(GlobalUserPreferences.enableDeleteNotifications && item.notification != null ? View.VISIBLE : View.GONE);
itemView.setBackgroundResource(item.notification.type != Notification.Type.POLL itemView.setBackgroundResource(item.notification.type != Notification.Type.POLL
&& item.notification.type != Notification.Type.REPORT ? && item.notification.type != Notification.Type.REPORT ?
selectableItemBackground : 0); selectableItemBackground : 0);
itemView.setClickable(item.notification.type != Notification.Type.POLL); itemView.setClickable(item.notification.type != Notification.Type.POLL);
itemView.setPaddingRelative(itemView.getPaddingStart(), itemView.getPaddingTop(),
GlobalUserPreferences.enableDeleteNotifications ? V.dp(4) : V.dp(16), itemView.getPaddingBottom());
} }
public void onItemClick(View v) { public void onItemClick(View v) {

View File

@@ -15,8 +15,8 @@ import org.joinmastodon.android.ui.utils.UiUtils;
public class PollFooterStatusDisplayItem extends StatusDisplayItem{ public class PollFooterStatusDisplayItem extends StatusDisplayItem{
public final Poll poll; public final Poll poll;
public PollFooterStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, Poll poll){ public PollFooterStatusDisplayItem(String parentID, String contentStatusID, BaseStatusListFragment parentFragment, Poll poll){
super(parentID, parentFragment); super(parentID, contentStatusID, parentFragment);
this.poll=poll; this.poll=poll;
} }

View File

@@ -31,8 +31,8 @@ public class PollOptionStatusDisplayItem extends StatusDisplayItem{
private final int optionIndex; private final int optionIndex;
public final Poll poll; public final Poll poll;
public PollOptionStatusDisplayItem(String parentID, Poll poll, int optionIndex, BaseStatusListFragment parentFragment){ public PollOptionStatusDisplayItem(String parentID, String contentStatusID, Poll poll, int optionIndex, BaseStatusListFragment parentFragment){
super(parentID, parentFragment); super(parentID, contentStatusID, parentFragment);
this.optionIndex=optionIndex; this.optionIndex=optionIndex;
option=poll.options.get(optionIndex); option=poll.options.get(optionIndex);
this.poll=poll; this.poll=poll;

View File

@@ -52,7 +52,7 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
} }
public ReblogOrReplyLineStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, CharSequence text, List<Emoji> emojis, @DrawableRes int icon, StatusPrivacy visibility, @Nullable View.OnClickListener handleClick, CharSequence fullText, Status status) { public ReblogOrReplyLineStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, CharSequence text, List<Emoji> emojis, @DrawableRes int icon, StatusPrivacy visibility, @Nullable View.OnClickListener handleClick, CharSequence fullText, Status status) {
super(parentID, parentFragment); super(parentID, status.getContentStatus().id, parentFragment);
SpannableStringBuilder ssb=new SpannableStringBuilder(text); SpannableStringBuilder ssb=new SpannableStringBuilder(text);
if(AccountSessionManager.get(parentFragment.getAccountID()).getLocalPreferences().customEmojiInNames) if(AccountSessionManager.get(parentFragment.getAccountID()).getLocalPreferences().customEmojiInNames)
HtmlParser.parseCustomEmoji(ssb, emojis); HtmlParser.parseCustomEmoji(ssb, emojis);

View File

@@ -14,7 +14,7 @@ public class SectionHeaderStatusDisplayItem extends StatusDisplayItem{
public final Runnable onButtonClick; public final Runnable onButtonClick;
public SectionHeaderStatusDisplayItem(BaseStatusListFragment parentFragment, String title, String buttonText, Runnable onButtonClick){ public SectionHeaderStatusDisplayItem(BaseStatusListFragment parentFragment, String title, String buttonText, Runnable onButtonClick){
super("", parentFragment); super("", null, parentFragment);
this.title=title; this.title=title;
this.buttonText=buttonText; this.buttonText=buttonText;
this.onButtonClick=onButtonClick; this.onButtonClick=onButtonClick;

View File

@@ -32,7 +32,7 @@ public class SpoilerStatusDisplayItem extends StatusDisplayItem{
private final int attachmentCount; private final int attachmentCount;
public SpoilerStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, String title, Status statusForContent, Type type){ public SpoilerStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, String title, Status statusForContent, Type type){
super(parentID, parentFragment); super(parentID, statusForContent.id, parentFragment);
this.status=statusForContent; this.status=statusForContent;
this.type=type; this.type=type;
this.attachmentCount=statusForContent.mediaAttachments.size(); this.attachmentCount=statusForContent.mediaAttachments.size();

View File

@@ -30,6 +30,7 @@ import org.joinmastodon.android.model.LegacyFilter;
import org.joinmastodon.android.model.FilterAction; import org.joinmastodon.android.model.FilterAction;
import org.joinmastodon.android.model.FilterContext; import org.joinmastodon.android.model.FilterContext;
import org.joinmastodon.android.model.FilterResult; import org.joinmastodon.android.model.FilterResult;
import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.model.Poll; import org.joinmastodon.android.model.Poll;
import org.joinmastodon.android.model.ScheduledStatus; import org.joinmastodon.android.model.ScheduledStatus;
import org.joinmastodon.android.model.Status; import org.joinmastodon.android.model.Status;
@@ -52,15 +53,15 @@ import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.views.UsableRecyclerView; import me.grishka.appkit.views.UsableRecyclerView;
public abstract class StatusDisplayItem{ public abstract class StatusDisplayItem{
public final String parentID; public final String parentID, contentStatusID;
public final BaseStatusListFragment<?> parentFragment; public final BaseStatusListFragment<?> parentFragment;
public boolean inset; public boolean inset;
public int index; public int index;
public boolean public boolean
hasDescendantNeighbor = false, hasDescendantNeighbor=false,
hasAncestoringNeighbor = false, hasAncestoringNeighbor=false,
isMainStatus = true, isMainStatus=true,
isDirectDescendant = false; isDirectDescendant=false;
public static final int FLAG_INSET=1; public static final int FLAG_INSET=1;
public static final int FLAG_NO_FOOTER=1 << 1; public static final int FLAG_NO_FOOTER=1 << 1;
@@ -82,8 +83,9 @@ public abstract class StatusDisplayItem{
this.isDirectDescendant = isDirectDescendant; this.isDirectDescendant = isDirectDescendant;
} }
public StatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment){ public StatusDisplayItem(String parentID, String contentStatusID, BaseStatusListFragment<?> parentFragment){
this.parentID=parentID; this.parentID=parentID;
this.contentStatusID=contentStatusID;
this.parentFragment=parentFragment; this.parentFragment=parentFragment;
} }
@@ -145,7 +147,7 @@ public abstract class StatusDisplayItem{
Status statusForContent=status.getContentStatus(); Status statusForContent=status.getContentStatus();
Bundle args=new Bundle(); Bundle args=new Bundle();
args.putString("account", accountID); args.putString("account", accountID);
ScheduledStatus scheduledStatus = parentObject instanceof ScheduledStatus ? (ScheduledStatus) parentObject : null; ScheduledStatus scheduledStatus = parentObject instanceof ScheduledStatus s ? s : null;
HeaderStatusDisplayItem header=null; HeaderStatusDisplayItem header=null;
boolean hideCounts=!AccountSessionManager.get(accountID).getLocalPreferences().showInteractionCounts; boolean hideCounts=!AccountSessionManager.get(accountID).getLocalPreferences().showInteractionCounts;
@@ -201,7 +203,7 @@ public abstract class StatusDisplayItem{
if((flags & FLAG_CHECKABLE)!=0) if((flags & FLAG_CHECKABLE)!=0)
items.add(header=new CheckableHeaderStatusDisplayItem(parentID, statusForContent.account, statusForContent.createdAt, fragment, accountID, statusForContent, null)); items.add(header=new CheckableHeaderStatusDisplayItem(parentID, statusForContent.account, statusForContent.createdAt, fragment, accountID, statusForContent, null));
else else
items.add(header=new HeaderStatusDisplayItem(parentID, statusForContent.account, statusForContent.createdAt, fragment, accountID, statusForContent, null, null, scheduledStatus)); items.add(header=new HeaderStatusDisplayItem(parentID, statusForContent.account, statusForContent.createdAt, fragment, accountID, statusForContent, null, parentObject instanceof Notification n ? n : null, scheduledStatus));
} }
LegacyFilter applyingFilter=null; LegacyFilter applyingFilter=null;
@@ -244,7 +246,7 @@ public abstract class StatusDisplayItem{
}else if(!hasSpoiler && header!=null){ }else if(!hasSpoiler && header!=null){
header.needBottomPadding=true; header.needBottomPadding=true;
}else if(hasSpoiler){ }else if(hasSpoiler){
contentItems.add(new DummyStatusDisplayItem(parentID, fragment)); contentItems.add(new DummyStatusDisplayItem(parentID, statusForContent.id, fragment));
} }
List<Attachment> imageAttachments=statusForContent.mediaAttachments.stream().filter(att->att.type.isImage()).collect(Collectors.toList()); List<Attachment> imageAttachments=statusForContent.mediaAttachments.stream().filter(att->att.type.isImage()).collect(Collectors.toList());
@@ -268,11 +270,11 @@ public abstract class StatusDisplayItem{
contentItems.add(new AudioStatusDisplayItem(parentID, fragment, statusForContent, att)); contentItems.add(new AudioStatusDisplayItem(parentID, fragment, statusForContent, att));
} }
if(att.type==Attachment.Type.UNKNOWN){ if(att.type==Attachment.Type.UNKNOWN){
contentItems.add(new FileStatusDisplayItem(parentID, fragment, att)); contentItems.add(new FileStatusDisplayItem(parentID, statusForContent.id, fragment, att));
} }
} }
if(statusForContent.poll!=null){ if(statusForContent.poll!=null){
buildPollItems(parentID, fragment, statusForContent.poll, contentItems); buildPollItems(parentID, statusForContent.id, fragment, statusForContent.poll, contentItems);
} }
if(statusForContent.card!=null && statusForContent.mediaAttachments.isEmpty()){ if(statusForContent.card!=null && statusForContent.mediaAttachments.isEmpty()){
contentItems.add(new LinkCardStatusDisplayItem(parentID, fragment, statusForContent)); contentItems.add(new LinkCardStatusDisplayItem(parentID, fragment, statusForContent));
@@ -292,14 +294,14 @@ public abstract class StatusDisplayItem{
footer=new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID); footer=new FooterStatusDisplayItem(parentID, fragment, statusForContent, accountID);
footer.hideCounts=hideCounts; footer.hideCounts=hideCounts;
items.add(footer); items.add(footer);
if(status.hasGapAfter && !(fragment instanceof ThreadFragment)) if(status.hasGapAfter!=null && !(fragment instanceof ThreadFragment))
items.add(new GapStatusDisplayItem(parentID, fragment, status)); items.add(new GapStatusDisplayItem(parentID, fragment, status));
} }
int i=1; int i=1;
boolean inset=(flags & FLAG_INSET)!=0; boolean inset=(flags & FLAG_INSET)!=0;
// add inset dummy so last content item doesn't clip out of inset bounds // add inset dummy so last content item doesn't clip out of inset bounds
if((inset || footer==null) && (flags & FLAG_CHECKABLE)==0){ if((inset || footer==null) && (flags & FLAG_CHECKABLE)==0){
items.add(new DummyStatusDisplayItem(parentID, fragment)); items.add(new DummyStatusDisplayItem(parentID, statusForContent.id, fragment));
// in case we ever need the dummy to display a margin for the media grid again: // in case we ever need the dummy to display a margin for the media grid again:
// (i forgot why we apparently don't need this anymore) // (i forgot why we apparently don't need this anymore)
// !contentItems.isEmpty() && contentItems // !contentItems.isEmpty() && contentItems
@@ -320,13 +322,13 @@ public abstract class StatusDisplayItem{
new ArrayList<>(List.of(new WarningFilteredStatusDisplayItem(parentID, fragment, statusForContent, items, applyingFilter))); new ArrayList<>(List.of(new WarningFilteredStatusDisplayItem(parentID, fragment, statusForContent, items, applyingFilter)));
} }
public static void buildPollItems(String parentID, BaseStatusListFragment fragment, Poll poll, List<StatusDisplayItem> items){ public static void buildPollItems(String parentID, String contentStatusID, BaseStatusListFragment fragment, Poll poll, List<StatusDisplayItem> items){
int i=0; int i=0;
for(Poll.Option opt:poll.options){ for(Poll.Option opt:poll.options){
items.add(new PollOptionStatusDisplayItem(parentID, poll, i, fragment)); items.add(new PollOptionStatusDisplayItem(parentID, contentStatusID, poll, i, fragment));
i++; i++;
} }
items.add(new PollFooterStatusDisplayItem(parentID, fragment, poll)); items.add(new PollFooterStatusDisplayItem(parentID, contentStatusID, fragment, poll));
} }
public enum Type{ public enum Type{

View File

@@ -42,7 +42,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
public final Status status; public final Status status;
public TextStatusDisplayItem(String parentID, CharSequence text, BaseStatusListFragment parentFragment, Status status, boolean disableTranslate){ public TextStatusDisplayItem(String parentID, CharSequence text, BaseStatusListFragment parentFragment, Status status, boolean disableTranslate){
super(parentID, parentFragment); super(parentID, status.id, parentFragment);
this.text=text; this.text=text;
this.status=status; this.status=status;
this.disableTranslate=disableTranslate; this.disableTranslate=disableTranslate;

View File

@@ -19,7 +19,7 @@ public class WarningFilteredStatusDisplayItem extends StatusDisplayItem{
public LegacyFilter applyingFilter; public LegacyFilter applyingFilter;
public WarningFilteredStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status, List<StatusDisplayItem> filteredItems, LegacyFilter applyingFilter){ public WarningFilteredStatusDisplayItem(String parentID, BaseStatusListFragment<?> parentFragment, Status status, List<StatusDisplayItem> filteredItems, LegacyFilter applyingFilter){
super(parentID, parentFragment); super(parentID, status.id, parentFragment);
this.status=status; this.status=status;
this.filteredItems = filteredItems; this.filteredItems = filteredItems;
this.applyingFilter = applyingFilter; this.applyingFilter = applyingFilter;

View File

@@ -564,7 +564,7 @@ public class PhotoViewer implements ZoomPanView.Listener{
if(player==null || !player.isPlaying()) if(player==null || !player.isPlaying())
return; return;
player.pause(); player.pause();
videoPlayPauseButton.setImageResource(R.drawable.ic_play_24); videoPlayPauseButton.setImageResource(R.drawable.ic_fluent_play_24_filled);
videoPlayPauseButton.setContentDescription(activity.getString(R.string.play)); videoPlayPauseButton.setContentDescription(activity.getString(R.string.play));
stopUpdatingVideoPosition(); stopUpdatingVideoPosition();
windowView.removeCallbacks(uiAutoHider); windowView.removeCallbacks(uiAutoHider);
@@ -575,7 +575,7 @@ public class PhotoViewer implements ZoomPanView.Listener{
if(player==null || player.isPlaying()) if(player==null || player.isPlaying())
return; return;
player.start(); player.start();
videoPlayPauseButton.setImageResource(R.drawable.ic_pause_24); videoPlayPauseButton.setImageResource(R.drawable.ic_fluent_pause_24_filled);
videoPlayPauseButton.setContentDescription(activity.getString(R.string.pause)); videoPlayPauseButton.setContentDescription(activity.getString(R.string.pause));
startUpdatingVideoPosition(player); startUpdatingVideoPosition(player);
} }
@@ -940,7 +940,7 @@ public class PhotoViewer implements ZoomPanView.Listener{
@Override @Override
public void onCompletion(MediaPlayer mp){ public void onCompletion(MediaPlayer mp){
videoPlayPauseButton.setImageResource(R.drawable.ic_play_24); videoPlayPauseButton.setImageResource(R.drawable.ic_fluent_play_24_filled);
videoPlayPauseButton.setContentDescription(activity.getString(R.string.play)); videoPlayPauseButton.setContentDescription(activity.getString(R.string.play));
stopUpdatingVideoPosition(); stopUpdatingVideoPosition();
if(!uiVisible) if(!uiVisible)

View File

@@ -210,6 +210,7 @@ public class HtmlParser{
} }
public static void parseCustomEmoji(SpannableStringBuilder ssb, List<Emoji> emojis){ public static void parseCustomEmoji(SpannableStringBuilder ssb, List<Emoji> emojis){
if(emojis==null) return;
Map<String, Emoji> emojiByCode = Map<String, Emoji> emojiByCode =
emojis.stream() emojis.stream()
.collect( .collect(

View File

@@ -5,6 +5,7 @@ import android.text.TextPaint;
import android.text.style.CharacterStyle; import android.text.style.CharacterStyle;
import android.view.View; import android.view.View;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.model.Hashtag; import org.joinmastodon.android.model.Hashtag;
import org.joinmastodon.android.ui.utils.UiUtils; import org.joinmastodon.android.ui.utils.UiUtils;
@@ -34,7 +35,7 @@ public class LinkSpan extends CharacterStyle {
@Override @Override
public void updateDrawState(TextPaint tp) { public void updateDrawState(TextPaint tp) {
tp.setColor(color=tp.linkColor); tp.setColor(color=tp.linkColor);
tp.setUnderlineText(true); tp.setUnderlineText(GlobalUserPreferences.underlinedLinks);
} }
public void onClick(Context context){ public void onClick(Context context){
@@ -45,7 +46,7 @@ public class LinkSpan extends CharacterStyle {
if(linkObject instanceof Hashtag ht) if(linkObject instanceof Hashtag ht)
UiUtils.openHashtagTimeline(context, accountID, ht); UiUtils.openHashtagTimeline(context, accountID, ht);
else else
UiUtils.openHashtagTimeline(context, accountID, text); UiUtils.openHashtagTimeline(context, accountID, link);
} }
case CUSTOM -> listener.onLinkClick(this); case CUSTOM -> listener.onLinkClick(this);
} }

View File

@@ -68,6 +68,7 @@ import org.joinmastodon.android.E;
import org.joinmastodon.android.GlobalUserPreferences; import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.MastodonApp; import org.joinmastodon.android.MastodonApp;
import org.joinmastodon.android.R; import org.joinmastodon.android.R;
import org.joinmastodon.android.api.CacheController;
import org.joinmastodon.android.api.MastodonAPIRequest; import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.MastodonErrorResponse; import org.joinmastodon.android.api.MastodonErrorResponse;
import org.joinmastodon.android.api.StatusInteractionController; import org.joinmastodon.android.api.StatusInteractionController;
@@ -630,18 +631,24 @@ public class UiUtils {
} }
public static void confirmDeletePost(Activity activity, String accountID, Status status, Consumer<Status> resultCallback, boolean forRedraft) { public static void confirmDeletePost(Activity activity, String accountID, Status status, Consumer<Status> resultCallback, boolean forRedraft) {
Status s=status.getContentStatus();
showConfirmationAlert(activity, showConfirmationAlert(activity,
forRedraft ? R.string.sk_confirm_delete_and_redraft_title : R.string.confirm_delete_title, forRedraft ? R.string.sk_confirm_delete_and_redraft_title : R.string.confirm_delete_title,
forRedraft ? R.string.sk_confirm_delete_and_redraft : R.string.confirm_delete, forRedraft ? R.string.sk_confirm_delete_and_redraft : R.string.confirm_delete,
forRedraft ? R.string.sk_delete_and_redraft : R.string.delete, forRedraft ? R.string.sk_delete_and_redraft : R.string.delete,
forRedraft ? R.drawable.ic_fluent_arrow_clockwise_28_regular : R.drawable.ic_fluent_delete_28_regular, forRedraft ? R.drawable.ic_fluent_arrow_clockwise_28_regular : R.drawable.ic_fluent_delete_28_regular,
() -> new DeleteStatus(status.id) () -> new DeleteStatus(s.id)
.setCallback(new Callback<>() { .setCallback(new Callback<>() {
@Override @Override
public void onSuccess(Status result) { public void onSuccess(Status result) {
resultCallback.accept(result); resultCallback.accept(result);
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().deleteStatus(status.id); CacheController cache=AccountSessionManager.get(accountID).getCacheController();
E.post(new StatusDeletedEvent(status.id, accountID)); cache.deleteStatus(s.id);
E.post(new StatusDeletedEvent(s.id, accountID));
if(status!=s){
cache.deleteStatus(status.id);
E.post(new StatusDeletedEvent(status.id, accountID));
}
} }
@Override @Override
@@ -973,8 +980,8 @@ public class UiUtils {
default -> R.style.Theme_Mastodon_AutoLightDark; default -> R.style.Theme_Mastodon_AutoLightDark;
}); });
AccountLocalPreferences prefs=session != null ? session.getLocalPreferences() : null; AccountLocalPreferences prefs=session!=null ? session.getLocalPreferences() : null;
AccountLocalPreferences.ColorPreference color=prefs != null ? prefs.color : AccountLocalPreferences.ColorPreference.MATERIAL3; AccountLocalPreferences.ColorPreference color=prefs!=null ? prefs.getCurrentColor() : AccountLocalPreferences.ColorPreference.MATERIAL3;
ColorPalette palette = ColorPalette.palettes.get(color); ColorPalette palette = ColorPalette.palettes.get(color);
if (palette != null) palette.apply(context, theme); if (palette != null) palette.apply(context, theme);
@@ -1711,7 +1718,7 @@ public class UiUtils {
} }
public static Optional<String> extractPronouns(Context context, @Nullable Account account) { public static Optional<String> extractPronouns(Context context, @Nullable Account account) {
if (account == null) return Optional.empty(); if (account==null || account.fields==null) return Optional.empty();
String localizedPronouns=context.getString(R.string.sk_pronouns_label).toLowerCase(); String localizedPronouns=context.getString(R.string.sk_pronouns_label).toLowerCase();
// higher = worse. the lowest number wins. also i'm sorry for writing this // higher = worse. the lowest number wins. also i'm sorry for writing this

View File

@@ -1,9 +1,11 @@
package org.joinmastodon.android.ui.views; package org.joinmastodon.android.ui.views;
import android.content.Context; import android.content.Context;
import android.graphics.Typeface;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.View; import android.view.View;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.function.IntConsumer; import java.util.function.IntConsumer;
import java.util.function.IntPredicate; import java.util.function.IntPredicate;
@@ -45,9 +47,7 @@ public class TabBar extends LinearLayout{
listener.accept(v.getId()); listener.accept(v.getId());
if(v.getId()==selectedTabID) if(v.getId()==selectedTabID)
return; return;
findViewById(selectedTabID).setSelected(false); selectTab(v.getId());
v.setSelected(true);
selectedTabID=v.getId();
} }
private boolean onChildLongClick(View v){ private boolean onChildLongClick(View v){
@@ -60,8 +60,17 @@ public class TabBar extends LinearLayout{
} }
public void selectTab(int id){ public void selectTab(int id){
findViewById(selectedTabID).setSelected(false); toggleSelected(selectedTabID, false);
selectedTabID=id; selectedTabID=id;
findViewById(selectedTabID).setSelected(true); toggleSelected(id, true);
}
private void toggleSelected(int selectedTabID, boolean selected){
LinearLayout tab=findViewById(selectedTabID);
tab.setSelected(selected);
View v=tab.findViewWithTag("label");
if(v instanceof TextView text){
text.setTypeface(Typeface.create(text.getTypeface(), selected ? Typeface.BOLD : Typeface.NORMAL));
}
} }
} }

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="?colorM3OnPrimary"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M11,19V13H5V11H11V5H13V11H19V13H13V19Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M14,3V5H5Q5,5 5,5Q5,5 5,5V19Q5,19 5,19Q5,19 5,19H19Q19,19 19,19Q19,19 19,19V10H21V19Q21,19.825 20.413,20.413Q19.825,21 19,21H5Q4.175,21 3.587,20.413Q3,19.825 3,19V5Q3,4.175 3.587,3.587Q4.175,3 5,3ZM19,3V5H21V7H19V9H17V7H15V5H17V3ZM6,17H18L14.25,12L11.25,16L9,13ZM5,5V8V10V19Q5,19 5,19Q5,19 5,19Q5,19 5,19Q5,19 5,19V5Q5,5 5,5Q5,5 5,5Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="@android:color/white"
android:pathData="M29.45,6V9H9Q9,9 9,9Q9,9 9,9V39Q9,39 9,39Q9,39 9,39H39Q39,39 39,39Q39,39 39,39V18.6H42V39Q42,40.2 41.1,41.1Q40.2,42 39,42H9Q7.8,42 6.9,41.1Q6,40.2 6,39V9Q6,7.8 6.9,6.9Q7.8,6 9,6ZM38,6V10.05H42.05V13.05H38V17.1H35V13.05H30.95V10.05H35V6ZM12,33.9H36L28.8,24.3L22.45,32.65L17.75,26.45ZM9,9V14.55V18.6V39Q9,39 9,39Q9,39 9,39Q9,39 9,39Q9,39 9,39V9Q9,9 9,9Q9,9 9,9Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="@color/m3_sys_dark_on_surface"
android:pathData="M29.45,6V9H9Q9,9 9,9Q9,9 9,9V39Q9,39 9,39Q9,39 9,39H39Q39,39 39,39Q39,39 39,39V18.6H42V39Q42,40.2 41.1,41.1Q40.2,42 39,42H9Q7.8,42 6.9,41.1Q6,40.2 6,39V9Q6,7.8 6.9,6.9Q7.8,6 9,6ZM38,6V10.05H42.05V13.05H38V17.1H35V13.05H30.95V10.05H35V6ZM12,33.9H36L28.8,24.3L22.45,32.65L17.75,26.45ZM9,9V14.55V18.6V39Q9,39 9,39Q9,39 9,39Q9,39 9,39Q9,39 9,39V9Q9,9 9,9Q9,9 9,9Z"/>
</vector>

View File

@@ -1,16 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M3,16V10.167C3,9.836 3.11,9.564 3.33,9.35C3.57,9.117 3.86,9 4.2,9H7.8C8.14,9 8.42,9.117 8.64,9.35C8.88,9.564 9,9.836 9,10.167V16H7.2V14.25H4.8V16H3ZM4.8,12.5H7.2V10.75H4.8V12.5Z"
android:fillColor="#49454F"
android:fillType="evenOdd"/>
<path
android:pathData="M17.1,10.75V16H18.9V10.75H21V9H15V10.75H17.1Z"
android:fillColor="#49454F"/>
<path
android:pathData="M10.2,9V16H15V14.25H12V9H10.2Z"
android:fillColor="#49454F"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:fillColor="@android:color/white"
android:pathData="M10,18.333Q8.271,18.333 6.75,17.677Q5.229,17.021 4.104,15.896Q2.979,14.771 2.323,13.25Q1.667,11.729 1.667,10Q1.667,8.271 2.323,6.75Q2.979,5.229 4.104,4.104Q5.229,2.979 6.75,2.323Q8.271,1.667 10,1.667Q11.729,1.667 13.25,2.323Q14.771,2.979 15.896,4.104Q17.021,5.229 17.677,6.75Q18.333,8.271 18.333,10V11.271Q18.333,12.5 17.49,13.354Q16.646,14.208 15.417,14.208Q14.688,14.208 14.042,13.906Q13.396,13.604 12.958,13.042Q12.375,13.625 11.604,13.927Q10.833,14.229 10,14.229Q8.229,14.229 7,13Q5.771,11.771 5.771,10Q5.771,8.229 7,7Q8.229,5.771 10,5.771Q11.771,5.771 13,7Q14.229,8.229 14.229,10V11.271Q14.229,11.75 14.583,12.104Q14.938,12.458 15.417,12.458Q15.896,12.458 16.24,12.104Q16.583,11.75 16.583,11.271V10Q16.583,7.25 14.667,5.333Q12.75,3.417 10,3.417Q7.25,3.417 5.333,5.333Q3.417,7.25 3.417,10Q3.417,12.75 5.333,14.667Q7.25,16.583 10,16.583H14.125V18.333ZM10,12.479Q11.042,12.479 11.76,11.76Q12.479,11.042 12.479,10Q12.479,8.958 11.76,8.24Q11.042,7.521 10,7.521Q8.958,7.521 8.24,8.24Q7.521,8.958 7.521,10Q7.521,11.042 8.24,11.76Q8.958,12.479 10,12.479Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M9,22Q7.55,22 6.275,21.45Q5,20.9 4.05,19.95Q3.1,19 2.55,17.725Q2,16.45 2,15Q2,12.975 3.05,11.3Q4.1,9.625 5.8,8.75Q6.3,7.775 7.038,7.037Q7.775,6.3 8.75,5.8Q9.575,4.1 11.275,3.05Q12.975,2 15,2Q16.45,2 17.725,2.55Q19,3.1 19.95,4.05Q20.9,5 21.45,6.275Q22,7.55 22,9Q22,11.125 20.95,12.75Q19.9,14.375 18.2,15.25Q17.7,16.225 16.962,16.962Q16.225,17.7 15.25,18.2Q14.375,19.9 12.7,20.95Q11.025,22 9,22ZM9,20Q9.825,20 10.588,19.75Q11.35,19.5 12,19Q10.55,19 9.275,18.45Q8,17.9 7.05,16.95Q6.1,16 5.55,14.725Q5,13.45 5,12Q4.5,12.65 4.25,13.412Q4,14.175 4,15Q4,16.05 4.4,16.95Q4.8,17.85 5.475,18.525Q6.15,19.2 7.05,19.6Q7.95,20 9,20ZM12,17Q12.825,17 13.613,16.75Q14.4,16.5 15.05,16Q13.575,16 12.3,15.438Q11.025,14.875 10.075,13.925Q9.125,12.975 8.562,11.7Q8,10.425 8,8.95Q7.5,9.6 7.25,10.387Q7,11.175 7,12Q7,13.05 7.388,13.95Q7.775,14.85 8.475,15.525Q9.15,16.225 10.05,16.613Q10.95,17 12,17ZM15,14Q15.45,14 15.863,13.925Q16.275,13.85 16.7,13.7Q17.25,12.2 16.863,10.812Q16.475,9.425 15.525,8.475Q14.575,7.525 13.188,7.137Q11.8,6.75 10.3,7.3Q10.15,7.725 10.075,8.137Q10,8.55 10,9Q10,10.05 10.387,10.95Q10.775,11.85 11.475,12.525Q12.15,13.225 13.05,13.613Q13.95,14 15,14ZM19,12.05Q19.5,11.4 19.75,10.612Q20,9.825 20,9Q20,7.95 19.613,7.05Q19.225,6.15 18.525,5.475Q17.85,4.775 16.95,4.387Q16.05,4 15,4Q14.125,4 13.363,4.25Q12.6,4.5 11.95,5Q13.425,5 14.7,5.562Q15.975,6.125 16.925,7.075Q17.875,8.025 18.438,9.3Q19,10.575 19,12.05Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M4,22Q3.175,22 2.588,21.413Q2,20.825 2,20V4Q2,3.175 2.588,2.587Q3.175,2 4,2H12L18,8V12.25H16V9H11V4H4Q4,4 4,4Q4,4 4,4V20Q4,20 4,20Q4,20 4,20H15V22ZM4,20V12.25V9V4Q4,4 4,4Q4,4 4,4V20Q4,20 4,20Q4,20 4,20ZM5,19Q5.1,17.775 5.75,16.75Q6.4,15.725 7.45,15.125L6.5,13.425Q6.5,13.4 6.6,13.05Q6.725,13 6.838,13Q6.95,13 7,13.125L7.975,14.875Q8.475,14.675 8.975,14.562Q9.475,14.45 10,14.45Q10.525,14.45 11.025,14.562Q11.525,14.675 12.025,14.875L13,13.125Q13,13.125 13.375,13.025Q13.5,13.075 13.525,13.2Q13.55,13.325 13.5,13.425L12.55,15.125Q13.6,15.725 14.25,16.75Q14.9,17.775 15,19ZM7.75,17.5Q7.95,17.5 8.1,17.35Q8.25,17.2 8.25,17Q8.25,16.8 8.1,16.65Q7.95,16.5 7.75,16.5Q7.55,16.5 7.4,16.65Q7.25,16.8 7.25,17Q7.25,17.2 7.4,17.35Q7.55,17.5 7.75,17.5ZM12.25,17.5Q12.45,17.5 12.6,17.35Q12.75,17.2 12.75,17Q12.75,16.8 12.6,16.65Q12.45,16.5 12.25,16.5Q12.05,16.5 11.9,16.65Q11.75,16.8 11.75,17Q11.75,17.2 11.9,17.35Q12.05,17.5 12.25,17.5ZM20,22 L16,18 17.4,16.575 19,18.15V14H21V18.15L22.6,16.575L24,18Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480ZM80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q507,80 533,83.5Q559,87 584,94Q568,109 555.5,127Q543,145 535,165Q521,163 507.5,161.5Q494,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800Q614,800 707,707Q800,614 800,480Q800,466 798.5,452.5Q797,439 795,425Q815,417 833,404.5Q851,392 866,376Q873,401 876.5,427Q880,453 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480ZM720,360Q670,360 635,325Q600,290 600,240Q600,190 635,155Q670,120 720,120Q770,120 805,155Q840,190 840,240Q840,290 805,325Q770,360 720,360Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M11.4,16 L14,13.4 16.6,16 18,14.6 15.4,12 18,9.4 16.6,8 14,10.6 11.4,8 10,9.4 12.6,12 10,14.6ZM3,12 L7.35,5.85Q7.625,5.45 8.062,5.225Q8.5,5 9,5H19Q19.825,5 20.413,5.588Q21,6.175 21,7V17Q21,17.825 20.413,18.413Q19.825,19 19,19H9Q8.5,19 8.062,18.775Q7.625,18.55 7.35,18.15ZM5.45,12 L9,17Q9,17 9,17Q9,17 9,17H19Q19,17 19,17Q19,17 19,17V7Q19,7 19,7Q19,7 19,7H9Q9,7 9,7Q9,7 9,7ZM19,12V7Q19,7 19,7Q19,7 19,7Q19,7 19,7Q19,7 19,7V17Q19,17 19,17Q19,17 19,17Q19,17 19,17Q19,17 19,17Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:fillColor="@android:color/white"
android:pathData="M10,18Q8.354,18 6.896,17.375Q5.438,16.75 4.344,15.656Q3.25,14.562 2.625,13.104Q2,11.646 2,10Q2,8.333 2.625,6.885Q3.25,5.438 4.344,4.344Q5.438,3.25 6.896,2.625Q8.354,2 10,2Q11.667,2 13.115,2.625Q14.562,3.25 15.656,4.344Q16.75,5.438 17.375,6.885Q18,8.333 18,10Q18,11.646 17.375,13.104Q16.75,14.562 15.656,15.656Q14.562,16.75 13.115,17.375Q11.667,18 10,18ZM10,16.5Q12.708,16.5 14.604,14.604Q16.5,12.708 16.5,10Q16.5,8.854 16.125,7.833Q15.75,6.812 15.083,5.979L5.979,15.083Q6.812,15.75 7.833,16.125Q8.854,16.5 10,16.5ZM4.917,14.021 L14.021,4.917Q13.188,4.25 12.167,3.875Q11.146,3.5 10,3.5Q7.292,3.5 5.396,5.396Q3.5,7.292 3.5,10Q3.5,11.146 3.875,12.167Q4.25,13.188 4.917,14.021Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M7,17.95 L12,15.8 17,17.95V5Q17,5 17,5Q17,5 17,5H7Q7,5 7,5Q7,5 7,5ZM5,21V5Q5,4.175 5.588,3.587Q6.175,3 7,3H17Q17.825,3 18.413,3.587Q19,4.175 19,5V21L12,18ZM17,5H12H7Q7,5 7,5Q7,5 7,5H17Q17,5 17,5Q17,5 17,5Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:fillColor="@android:color/white"
android:pathData="M8.229,14.062 L4.708,10.521 5.75,9.479 8.229,11.938 14.25,5.938 15.292,7Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M9.55,18 L3.85,12.3 5.275,10.875 9.55,15.15 18.725,5.975 20.15,7.4Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:fillColor="@android:color/white"
android:pathData="M6.333,11.729 L3,8.396 4.062,7.333 6.333,9.604 11.938,4 13,5.062Z"/>
</vector>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/ic_warning_fill1_24px"/>
<item android:drawable="@drawable/ic_warning_24px"/>
</selector>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/ic_mood_fill1_24px"/>
<item android:drawable="@drawable/ic_mood_24px"/>
</selector>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="@drawable/ic_insert_chart_fill1_24px"/>
<item android:drawable="@drawable/ic_insert_chart_24px"/>
</selector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M12,21Q8.25,21 5.625,18.375Q3,15.75 3,12Q3,8.25 5.625,5.625Q8.25,3 12,3Q12.35,3 12.688,3.025Q13.025,3.05 13.35,3.1Q12.325,3.825 11.713,4.987Q11.1,6.15 11.1,7.5Q11.1,9.75 12.675,11.325Q14.25,12.9 16.5,12.9Q17.875,12.9 19.025,12.287Q20.175,11.675 20.9,10.65Q20.95,10.975 20.975,11.312Q21,11.65 21,12Q21,15.75 18.375,18.375Q15.75,21 12,21ZM12,19Q14.2,19 15.95,17.788Q17.7,16.575 18.5,14.625Q18,14.75 17.5,14.825Q17,14.9 16.5,14.9Q13.425,14.9 11.262,12.738Q9.1,10.575 9.1,7.5Q9.1,7 9.175,6.5Q9.25,6 9.375,5.5Q7.425,6.3 6.213,8.05Q5,9.8 5,12Q5,14.9 7.05,16.95Q9.1,19 12,19ZM11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Q11.75,12.25 11.75,12.25Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M7.5,6Q6.875,6 6.438,6.438Q6,6.875 6,7.5Q6,8.125 6.438,8.562Q6.875,9 7.5,9Q8.125,9 8.562,8.562Q9,8.125 9,7.5Q9,6.875 8.562,6.438Q8.125,6 7.5,6ZM7.5,16Q6.875,16 6.438,16.438Q6,16.875 6,17.5Q6,18.125 6.438,18.562Q6.875,19 7.5,19Q8.125,19 8.562,18.562Q9,18.125 9,17.5Q9,16.875 8.562,16.438Q8.125,16 7.5,16ZM4,3H20Q20.425,3 20.712,3.287Q21,3.575 21,4V11Q21,11.425 20.712,11.712Q20.425,12 20,12H4Q3.575,12 3.288,11.712Q3,11.425 3,11V4Q3,3.575 3.288,3.287Q3.575,3 4,3ZM5,5V10H19V5ZM4,13H20Q20.425,13 20.712,13.287Q21,13.575 21,14V21Q21,21.425 20.712,21.712Q20.425,22 20,22H4Q3.575,22 3.288,21.712Q3,21.425 3,21V14Q3,13.575 3.288,13.287Q3.575,13 4,13ZM5,15V20H19V15ZM5,5V10ZM5,15V20Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M6,20Q5.175,20 4.588,19.413Q4,18.825 4,18V15H6V18Q6,18 6,18Q6,18 6,18H18Q18,18 18,18Q18,18 18,18V15H20V18Q20,18.825 19.413,19.413Q18.825,20 18,20ZM12,16 L7,11 8.4,9.55 11,12.15V4H13V12.15L15.6,9.55L17,11Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:fillColor="@android:color/white"
android:pathData="M7.5,16Q6.875,16 6.438,15.562Q6,15.125 6,14.5Q6,13.875 6.438,13.438Q6.875,13 7.5,13Q8.125,13 8.562,13.438Q9,13.875 9,14.5Q9,15.125 8.562,15.562Q8.125,16 7.5,16ZM12.5,16Q11.875,16 11.438,15.562Q11,15.125 11,14.5Q11,13.875 11.438,13.438Q11.875,13 12.5,13Q13.125,13 13.562,13.438Q14,13.875 14,14.5Q14,15.125 13.562,15.562Q13.125,16 12.5,16ZM7.5,11.5Q6.875,11.5 6.438,11.062Q6,10.625 6,10Q6,9.375 6.438,8.938Q6.875,8.5 7.5,8.5Q8.125,8.5 8.562,8.938Q9,9.375 9,10Q9,10.625 8.562,11.062Q8.125,11.5 7.5,11.5ZM12.5,11.5Q11.875,11.5 11.438,11.062Q11,10.625 11,10Q11,9.375 11.438,8.938Q11.875,8.5 12.5,8.5Q13.125,8.5 13.562,8.938Q14,9.375 14,10Q14,10.625 13.562,11.062Q13.125,11.5 12.5,11.5ZM7.5,7Q6.875,7 6.438,6.562Q6,6.125 6,5.5Q6,4.875 6.438,4.438Q6.875,4 7.5,4Q8.125,4 8.562,4.438Q9,4.875 9,5.5Q9,6.125 8.562,6.562Q8.125,7 7.5,7ZM12.5,7Q11.875,7 11.438,6.562Q11,6.125 11,5.5Q11,4.875 11.438,4.438Q11.875,4 12.5,4Q13.125,4 13.562,4.438Q14,4.875 14,5.5Q14,6.125 13.562,6.562Q13.125,7 12.5,7Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M5,19H6.4L15.025,10.375L13.625,8.975L5,17.6ZM19.3,8.925 L15.05,4.725 16.45,3.325Q17.025,2.75 17.863,2.75Q18.7,2.75 19.275,3.325L20.675,4.725Q21.25,5.3 21.275,6.113Q21.3,6.925 20.725,7.5ZM17.85,10.4 L7.25,21H3V16.75L13.6,6.15ZM14.325,9.675 L13.625,8.975 15.025,10.375Z"/>
</vector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="@android:color/white"
android:pathData="M260,680Q234,680 217,663Q200,646 200,620Q200,595 217,577.5Q234,560 260,560Q285,560 302.5,577.5Q320,595 320,620Q320,646 302.5,663Q285,680 260,680ZM260,400Q234,400 217,383Q200,366 200,340Q200,315 217,297.5Q234,280 260,280Q285,280 302.5,297.5Q320,315 320,340Q320,366 302.5,383Q285,400 260,400ZM400,520L400,440L560,440L560,520L400,520ZM688,720L622,676Q650,633 665,583.5Q680,534 680,480Q680,414 658.5,356Q637,298 598,251L659,200Q707,257 733.5,328.5Q760,400 760,480Q760,547 741,607.5Q722,668 688,720Z"/>
</vector>

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