Compare commits

...

94 Commits

Author SHA1 Message Date
sk22
95fa547f15 Translated using Weblate (German)
Currently translated at 100.0% (398 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-10-19 15:13:41 +00:00
sk22
3198c9adb1 Translated using Weblate (German)
Currently translated at 99.2% (395 of 398 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2023-10-19 15:07:29 +00:00
SomeTr
e1af6f4643 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-19 15:07:29 +00:00
SomeTr
cc52e491b0 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (396 of 396 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-19 15:07:29 +00:00
Choukajohn
b0db0d9f2e Translated using Weblate (French)
Currently translated at 100.0% (396 of 396 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-10-19 15:07:29 +00:00
sk
d699788a12 fix string 2023-10-19 17:07:18 +02:00
sk
bdbf441e1a Merge remote-tracking branch 'upstream/l10n_master' 2023-10-19 17:01:46 +02:00
sk
0deba2885b Merge remote-tracking branch 'weblate/main' 2023-10-19 17:01:13 +02:00
sk
48b39fd3bc boop version 2023-10-19 16:59:45 +02:00
sk
875b235e6d restart when show replies/boosts changes
closes sk22#879
2023-10-19 16:58:26 +02:00
sk
1711682322 don't display extra text if visibility == local 2023-10-19 16:54:23 +02:00
sk
70f5ec7500 update header layout 2023-10-19 16:54:07 +02:00
sk
d34c73c210 add options for locking account and default vis 2023-10-19 16:49:23 +02:00
sk
50a0586e8a fix content type index and title 2023-10-19 16:02:51 +02:00
Jacoco
1d2ca1e500 fix: hiding discovery on Akkoma + hiding privacy settings (#867)
* Hide privacy settings on Akkoma

* Fix Akkoma skipping discovery

* Make settings order more clear in the code
2023-10-19 15:42:29 +02:00
EndermanCo
34b7123a8d Translated using Weblate (Persian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fa/
2023-10-19 10:17:38 +00:00
butterflyoffire
ec718ff58e Translated using Weblate (Arabic)
Currently translated at 80.4% (317 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ar/
2023-10-19 10:17:38 +00:00
ihor_ck
20a442e27f Translated using Weblate (Ukrainian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-19 10:17:38 +00:00
SomeTr
47cb74abc9 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-19 10:17:37 +00:00
SomeTr
a11e53c89a Translated using Weblate (Ukrainian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2023-10-19 10:17:37 +00:00
David Lapshin
d721e8ca46 Translated using Weblate (Russian)
Currently translated at 99.7% (393 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ru/
2023-10-19 10:17:37 +00:00
alextecplayz
23e5dcd030 Translated using Weblate (Romanian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ro/
2023-10-19 10:17:37 +00:00
Linerly
25dd2cfab8 Translated using Weblate (Indonesian)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2023-10-19 10:17:37 +00:00
Choukajohn
8537c7a7ae Translated using Weblate (French)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2023-10-19 10:17:37 +00:00
gallegonovato
ebd7f9c36c Translated using Weblate (Spanish)
Currently translated at 100.0% (394 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2023-10-19 10:17:37 +00:00
poesty
49cda3aeb2 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.7% (393 of 394 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2023-10-19 10:17:37 +00:00
sk
67cbc8aff2 don't load new posts every time we hit the top 2023-10-19 01:06:03 +02:00
sk
5db44cbf9d don't save bidi-safe string in account
also support custom emoji in account switcher
closes sk22#859
2023-10-19 01:01:53 +02:00
sk
95858e3280 remove debug println 2023-10-19 00:44:10 +02:00
sk
36846acbe5 fix null pointer when content language is null 2023-10-19 00:38:06 +02:00
sk
b95d944003 save own posts from timeline before removing them 2023-10-19 00:22:52 +02:00
sk
f52886af74 don't add own boosts to home
closes sk22#875
2023-10-19 00:09:09 +02:00
sk
6cbe406cef load new posts on reload 2023-10-19 00:04:54 +02:00
sk
3097bc7168 oops: put home timeline if result NOT empty 2023-10-18 23:28:44 +02:00
sk
5f7faa69e8 remove existing statuses to move them up 2023-10-18 22:07:10 +02:00
sk
ed24e89a96 don't compare newly fetched posts to created post
closes sk22#866
2023-10-18 21:48:11 +02:00
sk
8ea05c6ebd fix menu grouping 2023-10-18 21:24:59 +02:00
sk
a30fcbbe34 reorder profile menu
closes sk22#873
2023-10-18 21:23:58 +02:00
sk
39f76f9988 always show "boosted" text in reply/boost line
closes sk22#874
2023-10-18 21:21:03 +02:00
sk
5135653cd3 wow!! configurable first fraction 2023-10-18 21:11:48 +02:00
sk
2e4f04cd88 fix divide by zero error 2023-10-18 20:40:23 +02:00
Eugen Rochko
a44e0e036a New translations strings.xml (Persian) 2023-10-18 20:27:30 +02:00
Eugen Rochko
5d54c1bae4 New translations strings.xml (Spanish) 2023-10-18 20:27:29 +02:00
sk
09577074a9 merge settings changes 2023-10-18 20:26:20 +02:00
sk
53f0e2a933 change extra text size 2023-10-18 19:39:12 +02:00
sk
b8dccbbef1 now hopefully fixing header/subtitle extra sizing 2023-10-18 19:23:13 +02:00
Eugen Rochko
2ef17ba051 New translations strings.xml (Spanish) 2023-10-18 19:15:17 +02:00
Eugen Rochko
f63daf3a4e New translations strings.xml (Thai) 2023-10-18 19:15:16 +02:00
Eugen Rochko
52b079be2a New translations strings.xml (Thai) 2023-10-18 18:11:40 +02:00
Eugen Rochko
efeca17106 New translations strings.xml (Chinese Traditional) 2023-10-18 11:34:03 +02:00
Eugen Rochko
6827166c1d New translations strings.xml (Galician) 2023-10-18 08:51:11 +02:00
Eugen Rochko
04483e61e8 New translations strings.xml (Galician) 2023-10-18 07:49:15 +02:00
Eugen Rochko
22fe174922 New translations strings.xml (Icelandic) 2023-10-17 20:07:09 +02:00
Eugen Rochko
f143da3913 New translations strings.xml (Kabyle) 2023-10-17 04:25:08 +02:00
Eugen Rochko
7e9f41c74b New translations strings.xml (Scottish Gaelic) 2023-10-17 04:25:05 +02:00
Eugen Rochko
a1474d0d29 New translations strings.xml (Filipino) 2023-10-17 04:25:03 +02:00
Eugen Rochko
0dce936ad3 New translations strings.xml (Persian) 2023-10-17 04:24:58 +02:00
Eugen Rochko
6ebbbb4c6c New translations strings.xml (Indonesian) 2023-10-17 04:24:57 +02:00
Eugen Rochko
dc6ddbd0ee New translations strings.xml (Portuguese, Brazilian) 2023-10-17 04:24:56 +02:00
Eugen Rochko
86c81d6b53 New translations strings.xml (Galician) 2023-10-17 04:24:55 +02:00
Eugen Rochko
451a92aa36 New translations strings.xml (Vietnamese) 2023-10-17 04:24:53 +02:00
Eugen Rochko
5c42e67e73 New translations strings.xml (Chinese Simplified) 2023-10-17 04:24:52 +02:00
Eugen Rochko
d20d36d964 New translations strings.xml (Turkish) 2023-10-17 04:24:51 +02:00
Eugen Rochko
1a8d46c71e New translations strings.xml (Slovenian) 2023-10-17 04:24:50 +02:00
Eugen Rochko
91da10eca3 New translations strings.xml (Portuguese) 2023-10-17 04:24:49 +02:00
Eugen Rochko
3bb0dcee53 New translations strings.xml (Polish) 2023-10-17 04:24:48 +02:00
Eugen Rochko
d3fd4b200f New translations strings.xml (Norwegian) 2023-10-17 04:24:47 +02:00
Eugen Rochko
fed96864e1 New translations strings.xml (Dutch) 2023-10-17 04:24:46 +02:00
Eugen Rochko
3b351bea27 New translations strings.xml (Korean) 2023-10-17 04:24:45 +02:00
Eugen Rochko
254e01dca1 New translations strings.xml (Armenian) 2023-10-17 04:24:44 +02:00
Eugen Rochko
19158e1d48 New translations strings.xml (Hungarian) 2023-10-17 04:24:43 +02:00
Eugen Rochko
bffb78fccf New translations strings.xml (Basque) 2023-10-17 04:24:41 +02:00
Eugen Rochko
a3800592a2 New translations strings.xml (Greek) 2023-10-17 04:24:39 +02:00
Eugen Rochko
22a498dfc9 New translations strings.xml (German) 2023-10-17 04:24:38 +02:00
Eugen Rochko
9ea96e32bd New translations strings.xml (Danish) 2023-10-17 04:24:37 +02:00
Eugen Rochko
68f51a123e New translations strings.xml (Czech) 2023-10-17 04:24:36 +02:00
Eugen Rochko
43b1b63581 New translations strings.xml (Catalan) 2023-10-17 04:24:35 +02:00
Eugen Rochko
43b4a2c515 New translations strings.xml (Belarusian) 2023-10-17 04:24:34 +02:00
Eugen Rochko
5b9cfdb689 New translations strings.xml (Arabic) 2023-10-17 04:24:33 +02:00
Eugen Rochko
b43cd7103a New translations strings.xml (Spanish) 2023-10-17 04:24:32 +02:00
Eugen Rochko
30e4f6e0f5 New translations strings.xml (French) 2023-10-17 04:24:30 +02:00
Eugen Rochko
1d0ebf889b New translations strings.xml (Chinese Traditional) 2023-10-17 04:24:28 +02:00
Eugen Rochko
7c4f1da485 New translations strings.xml (Finnish) 2023-10-17 04:24:27 +02:00
Eugen Rochko
8163921014 New translations strings.xml (Russian) 2023-10-17 04:24:26 +02:00
Eugen Rochko
993393dd96 New translations strings.xml (Swedish) 2023-10-17 04:24:25 +02:00
Eugen Rochko
82aed43934 New translations strings.xml (Italian) 2023-10-17 04:24:24 +02:00
Eugen Rochko
fa65134c26 New translations strings.xml (Ukrainian) 2023-10-17 04:24:23 +02:00
Eugen Rochko
af4266c739 New translations strings.xml (Japanese) 2023-10-17 04:24:22 +02:00
Eugen Rochko
f72ea2e763 New translations strings.xml (Icelandic) 2023-10-17 04:24:21 +02:00
Eugen Rochko
c5540270a3 New translations strings.xml (Thai) 2023-10-17 04:24:20 +02:00
sk
5840c94395 isolate bi-directional text in display name 2023-10-17 01:03:06 +02:00
sk
92d7ae67ef don't break custom emoji in pronouns 2023-10-17 00:38:27 +02:00
sk
fc09514a4d the pronouns are stored in the balls (extra text)
also, improve max-width behavior
2023-10-17 00:28:00 +02:00
sk
300fa97781 remove comment 2023-10-16 19:36:30 +02:00
103 changed files with 758 additions and 442 deletions

View File

@@ -15,8 +15,8 @@ android {
applicationId "org.joinmastodon.android.sk"
minSdk 23
targetSdk 33
versionCode 105
versionName "2.1.6+fork.105"
versionCode 106
versionName "2.1.6+fork.106"
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']
}

View File

@@ -266,7 +266,7 @@ public class AudioPlayerService extends Service{
private void updateNotification(boolean dismissable, boolean removeNotification){
Notification.Builder bldr=new Notification.Builder(this)
.setSmallIcon(R.drawable.ic_ntf_logo)
.setContentTitle(status.account.displayName)
.setContentTitle(status.account.getDisplayName())
.setContentText(HtmlParser.strip(status.content))
.setOngoing(!dismissable)
.setShowWhen(false)

View File

@@ -120,6 +120,8 @@ public class CacheController{
values.put("time", s.createdAt.getEpochSecond());
db.insertWithOnConflict("home_timeline", null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
if(!clear)
db.delete("home_timeline", "`id` NOT IN (SELECT `id` FROM `home_timeline` ORDER BY `time` DESC LIMIT ?)", new String[]{"1000"});
});
}

View File

@@ -218,7 +218,7 @@ public class AccountSession{
public void savePreferencesIfPending(){
if(preferencesNeedSaving){
new UpdateAccountCredentialsPreferences(preferences, null, self.discoverable, self.source.indexable)
new UpdateAccountCredentialsPreferences(preferences, self.locked, self.discoverable, self.source.indexable)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Account result){

View File

@@ -9,5 +9,6 @@ public class StatusCreatedEvent{
public StatusCreatedEvent(Status status, String accountID){
this.status=status;
this.accountID=accountID;
status.fromStatusCreated=true;
}
}

View File

@@ -150,7 +150,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
public LinearLayout mainLayout;
private SizeListenerLinearLayout contentView;
private TextView selfName, selfUsername, selfExtraText, extraText, pronouns;
private TextView selfName, selfUsername, selfExtraText, extraText;
private ImageView selfAvatar;
private Account self;
private String instanceDomain;
@@ -326,7 +326,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
selfUsername=view.findViewById(R.id.self_username);
selfAvatar=view.findViewById(R.id.self_avatar);
selfExtraText=view.findViewById(R.id.self_extra_text);
HtmlParser.setTextWithCustomEmoji(selfName, self.displayName, self.emojis);
HtmlParser.setTextWithCustomEmoji(selfName, self.getDisplayName(), self.emojis);
selfUsername.setText('@'+self.username+'@'+instanceDomain);
if(self.avatar!=null)
ViewImageLoader.load(selfAvatar, null, new UrlImageLoaderRequest(self.avatar));
@@ -626,7 +626,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
});
View originalPost=view.findViewById(R.id.original_post);
extraText=view.findViewById(R.id.extra_text);
pronouns=view.findViewById(R.id.pronouns);
originalPost.setVisibility(View.VISIBLE);
originalPost.setOnClickListener(v->{
Bundle args=new Bundle();
@@ -666,7 +665,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
moreBtn.setBackground(null);
TextView name = view.findViewById(R.id.name);
name.setText(HtmlParser.parseCustomEmoji(status.account.displayName, status.account.emojis));
name.setText(HtmlParser.parseCustomEmoji(status.account.getDisplayName(), status.account.emojis));
UiUtils.loadCustomEmojiInTextView(name);
String time = status==null || status.editedAt==null
@@ -700,7 +699,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(16)));
}
replyText.setText(getString(quote!=null? R.string.sk_quoting_user : R.string.in_reply_to, status.account.displayName));
replyText.setText(getString(quote!=null? R.string.sk_quoting_user : R.string.in_reply_to, status.account.getDisplayName()));
int visibilityNameRes = switch (status.visibility) {
case PUBLIC -> R.string.visibility_public;
case UNLISTED -> R.string.sk_visibility_unlisted;
@@ -708,7 +707,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
case DIRECT -> R.string.visibility_private;
case LOCAL -> R.string.sk_local_only;
};
replyText.setContentDescription(getString(R.string.in_reply_to, status.account.displayName) + ", " + getString(visibilityNameRes));
replyText.setContentDescription(getString(R.string.in_reply_to, status.account.getDisplayName()) + ", " + getString(visibilityNameRes));
replyText.setOnClickListener(v->{
scrollView.smoothScrollTo(0, 0);
});
@@ -1455,8 +1454,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
private void updateHeaders() {
UiUtils.setExtraTextInfo(getContext(), selfExtraText, null, false, false, localOnly || statusVisibility==StatusPrivacy.LOCAL, null);
if (replyTo != null) UiUtils.setExtraTextInfo(getContext(), extraText, pronouns, true, false, replyTo.localOnly || replyTo.visibility==StatusPrivacy.LOCAL, replyTo.account);
UiUtils.setExtraTextInfo(getContext(), selfExtraText, false, false, localOnly, null);
if (replyTo != null) UiUtils.setExtraTextInfo(getContext(), extraText, true, false, replyTo.localOnly || replyTo.visibility==StatusPrivacy.LOCAL, replyTo.account);
}
private void buildVisibilityPopup(View v){

View File

@@ -20,7 +20,6 @@ import org.joinmastodon.android.api.requests.accounts.GetFollowRequests;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.HeaderPaginationList;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Relationship;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.text.HtmlParser;
@@ -271,7 +270,7 @@ public class FollowRequestsListFragment extends MastodonRecyclerFragment<FollowR
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
relationship=relationships.get(item.account.id);
UiUtils.setExtraTextInfo(getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
UiUtils.setExtraTextInfo(getContext(), null, true, false, false, item.account);
if(relationship==null || !relationship.followedBy){
actionWrap.setVisibility(View.GONE);
@@ -366,9 +365,9 @@ public class FollowRequestsListFragment extends MastodonRecyclerFragment<FollowR
coverRequest=new UrlImageLoaderRequest(account.header, 1000, 1000);
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
if(account.emojis.isEmpty()){
parsedName=account.displayName;
parsedName= account.getDisplayName();
}else{
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
emojiHelper.setText(new SpannableStringBuilder(parsedName).append(parsedBio));
}
}

View File

@@ -32,7 +32,6 @@ import org.joinmastodon.android.events.NotificationsMarkerUpdatedEvent;
import org.joinmastodon.android.events.StatusDisplaySettingsChangedEvent;
import org.joinmastodon.android.fragments.discover.DiscoverFragment;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.model.PaginatedResponse;
import org.joinmastodon.android.ui.AccountSwitcherSheet;
@@ -71,14 +70,12 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
private TextView notificationsBadge;
private String accountID;
private boolean isAkkoma;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
accountID=getArguments().getString("account");
setTitle(R.string.sk_app_name);
isAkkoma = getInstance().map(Instance::isAkkoma).orElse(false);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
setRetainInstance(true);
@@ -89,7 +86,6 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
homeTabFragment=new HomeTabFragment();
homeTabFragment.setArguments(args);
args=new Bundle(args);
args.putBoolean("disableDiscover", isAkkoma);
args.putBoolean("noAutoLoad", true);
discoverFragment=new DiscoverFragment();
discoverFragment.setArguments(args);
@@ -296,7 +292,7 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
if(tab==R.id.tab_profile){
ArrayList<String> options=new ArrayList<>();
for(AccountSession session:AccountSessionManager.getInstance().getLoggedInAccounts()){
options.add(session.self.displayName+"\n("+session.self.username+"@"+session.domain+")");
options.add(session.self.getDisplayName()+"\n("+session.self.username+"@"+session.domain+")");
}
new AccountSwitcherSheet(getActivity(), this).show();
return true;

View File

@@ -61,7 +61,7 @@ public class HomeTimelineFragment extends StatusListFragment {
maxID=result.maxID;
AccountSessionManager.get(accountID).filterStatuses(result.items, getFilterContext());
onDataLoaded(result.items, !empty);
if(result.isFromCache())
if(result.isFromCache() && GlobalUserPreferences.loadNewPosts)
loadNewPosts();
}
});
@@ -74,7 +74,7 @@ public class HomeTimelineFragment extends StatusListFragment {
list.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){
if(parent != null && parent.isNewPostsBtnShown() && list.getChildAdapterPosition(list.getChildAt(0))<=getMainAdapterOffset()){
if(parent!=null && parent.isNewPostsBtnShown() && list.getChildAdapterPosition(list.getChildAt(0))<=getMainAdapterOffset()){
parent.hideNewPostsButton();
}
}
@@ -87,7 +87,7 @@ public class HomeTimelineFragment extends StatusListFragment {
if(!getArguments().getBoolean("noAutoLoad")){
if(!loaded && !dataLoading){
loadData();
}else if(!dataLoading){
}else if(!dataLoading && GlobalUserPreferences.loadNewPosts){
loadNewPosts();
}
}
@@ -117,16 +117,19 @@ public class HomeTimelineFragment extends StatusListFragment {
}
public void onStatusCreated(Status status){
if(status.reblog!=null) return;
prependItems(Collections.singletonList(status), true);
}
private void loadNewPosts(){
if (!GlobalUserPreferences.loadNewPosts) return;
dataLoading=true;
// we only care about the data that was actually retrieved from the timeline api since
// user-created statuses are probably in the wrong position
List<Status> dataFromTimeline=data.stream().filter(s->!s.fromStatusCreated).collect(Collectors.toList());
// The idea here is that we request the timeline such that if there are fewer than `limit` posts,
// we'll get the currently topmost post as last in the response. This way we know there's no gap
// between the existing and newly loaded parts of the timeline.
String sinceID=data.size()>1 ? data.get(1).id : "1";
String sinceID=dataFromTimeline.size()>1 ? dataFromTimeline.get(1).id : "1";
currentRequest=new GetHomeTimeline(null, null, 20, sinceID, getLocalPrefs().timelineReplyVisibility)
.setCallback(new Callback<>(){
@Override
@@ -137,28 +140,31 @@ public class HomeTimelineFragment extends StatusListFragment {
return;
Status last=result.get(result.size()-1);
List<Status> toAdd;
if(!data.isEmpty() && last.id.equals(data.get(0).id)){ // This part intersects with the existing one
if(!dataFromTimeline.isEmpty() && last.id.equals(dataFromTimeline.get(0).id)){ // This part intersects with the existing one
toAdd=new ArrayList<>(result.subList(0, result.size()-1)); // Remove the already known last post
}else{
last.hasGapAfter=last.id;
toAdd=result;
}
if(!toAdd.isEmpty())
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(new ArrayList<>(toAdd), false);
// removing statuses that come up as duplicates (hopefully only posts and boosts that were locally created
// and thus were already prepended to the timeline earlier)
List<String> existingIds=data.stream().map(Status::getID).collect(Collectors.toList());
toAdd.removeIf(s->existingIds.contains(s.getID()));
List<Status> toAddUnfiltered=new ArrayList<>(toAdd);
AccountSessionManager.get(accountID).filterStatuses(toAdd, getFilterContext());
if(!toAdd.isEmpty()){
prependItems(toAdd, true);
if(parent != null && GlobalUserPreferences.showNewPostsButton) parent.showNewPostsButton();
}
if(toAddUnfiltered.isEmpty())
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(toAddUnfiltered, false);
refreshDone();
}
@Override
public void onError(ErrorResponse error){
currentRequest=null;
dataLoading=false;
refreshDone();
}
})
.exec(accountID);
@@ -325,8 +331,8 @@ public class HomeTimelineFragment extends StatusListFragment {
currentRequest=null;
dataLoading=false;
}
if (parent != null) parent.hideNewPostsButton();
super.onRefresh();
if(parent!=null) parent.hideNewPostsButton();
loadNewPosts();
}
@Override

View File

@@ -621,14 +621,14 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
@SuppressLint("SetTextI18n")
private void bindHeaderView(){
setTitle(account.displayName);
setTitle(account.getDisplayName());
setSubtitle(getResources().getQuantityString(R.plurals.x_posts, (int)(account.statusesCount%1000), account.statusesCount));
ViewImageLoader.load(avatar, null, new UrlImageLoaderRequest(
TextUtils.isEmpty(account.avatar) ? getSession().getDefaultAvatarUrl() :
GlobalUserPreferences.playGifs ? account.avatar : account.avatarStatic,
V.dp(100), V.dp(100)));
ViewImageLoader.load(cover, null, new UrlImageLoaderRequest(GlobalUserPreferences.playGifs ? account.header : account.headerStatic, 1000, 1000));
SpannableStringBuilder ssb=new SpannableStringBuilder(account.displayName);
SpannableStringBuilder ssb=new SpannableStringBuilder(account.getDisplayName());
if(AccountSessionManager.get(accountID).getLocalPreferences().customEmojiInNames)
HtmlParser.parseCustomEmoji(ssb, account.emojis);
name.setText(ssb);

View File

@@ -64,7 +64,7 @@ public class ThreadFragment extends StatusListFragment implements ProvidesAssist
knownAccounts.put(inReplyToAccount.id, inReplyToAccount);
data.add(mainStatus);
onAppendItems(Collections.singletonList(mainStatus));
setTitle(HtmlParser.parseCustomEmoji(getString(R.string.post_from_user, mainStatus.account.displayName), mainStatus.account.emojis));
setTitle(HtmlParser.parseCustomEmoji(getString(R.string.post_from_user, mainStatus.account.getDisplayName()), mainStatus.account.emojis));
transitionFinished = getArguments().getBoolean("noTransition", false);
}

View File

@@ -261,7 +261,7 @@ public class DiscoverAccountsFragment extends MastodonRecyclerFragment<DiscoverA
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
relationship=relationships.get(item.account.id);
UiUtils.setExtraTextInfo(getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
UiUtils.setExtraTextInfo(getContext(), null, true, false, false, item.account);
if(relationship==null){
actionWrap.setVisibility(View.GONE);
@@ -330,9 +330,9 @@ public class DiscoverAccountsFragment extends MastodonRecyclerFragment<DiscoverA
coverRequest=new UrlImageLoaderRequest(account.header, 1000, 1000);
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
if(account.emojis.isEmpty()){
parsedName=account.displayName;
parsedName= account.getDisplayName();
}else{
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
emojiHelper.setText(new SpannableStringBuilder(parsedName).append(parsedBio));
}
}

View File

@@ -13,8 +13,10 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.IsOnTop;
import org.joinmastodon.android.fragments.ScrollableToTop;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.SearchResult;
import org.joinmastodon.android.ui.OutlineProviders;
import org.joinmastodon.android.ui.SimpleViewHolder;
@@ -155,7 +157,7 @@ public class DiscoverFragment extends AppKitFragment implements ScrollableToTop,
}
});
disableDiscover=getArguments().getBoolean("disableDiscover");
disableDiscover=AccountSessionManager.get(accountID).getInstance().map(Instance::isAkkoma).orElse(false);
searchView=view.findViewById(R.id.search_fragment);
if(searchFragment==null){
searchFragment=new SearchFragment();

View File

@@ -115,7 +115,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
onDataLoaded(results.stream().map(sr->{
SearchResultViewModel vm=new SearchResultViewModel(sr, accountID, true);
if(sr.type==SearchResult.Type.HASHTAG){
vm.hashtagItem.onClick=()->openHashtag(sr);
vm.hashtagItem.setOnClick(i->openHashtag(sr));
}
return vm;
}).collect(Collectors.toList()), false);
@@ -132,7 +132,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
.map(sr->{
SearchResultViewModel vm=new SearchResultViewModel(sr, accountID, false);
if(sr.type==SearchResult.Type.HASHTAG){
vm.hashtagItem.onClick=()->openHashtag(sr);
vm.hashtagItem.setOnClick(i->openHashtag(sr));
}
return vm;
})
@@ -429,11 +429,11 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
wrapSuicideDialog(()->deliverResult(currentQuery, null));
}
private void onOpenURLClick(){
private void onOpenURLClick(ListItem<?> item_){
UiUtils.openURL(getContext(), accountID, searchViewHelper.getQuery(), false);
}
private void onGoToHashtagClick(){
private void onGoToHashtagClick(ListItem<?> item_){
wrapSuicideDialog(()->{
String q=searchViewHelper.getQuery();
if(q.startsWith("#"))
@@ -442,7 +442,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
});
}
private void onGoToAccountClick(){
private void onGoToAccountClick(ListItem<?> item_){
String q=searchViewHelper.getQuery();
if(!q.startsWith("@")){
q="@"+q;
@@ -459,11 +459,11 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
}).ifPresent(progress -> progress.wrapProgress((Activity) getContext(), R.string.loading, true));
}
private void onGoToStatusSearchClick(){
private void onGoToStatusSearchClick(ListItem<?> item_){
wrapSuicideDialog(()->deliverResult(searchViewHelper.getQuery(), SearchResult.Type.STATUS));
}
private void onGoToAccountSearchClick(){
private void onGoToAccountSearchClick(ListItem<?> item_){
wrapSuicideDialog(()->deliverResult(searchViewHelper.getQuery(), SearchResult.Type.ACCOUNT));
}

View File

@@ -3,7 +3,6 @@ package org.joinmastodon.android.fragments.onboarding;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;

View File

@@ -73,7 +73,7 @@ public class EditFilterFragment extends BaseSettingsFragment<Void> implements On
durationItem=new ListItem<>(R.string.settings_filter_duration, 0, this::onDurationClick),
wordsItem=new ListItem<>(R.string.settings_filter_muted_words, 0, this::onWordsClick),
contextItem=new ListItem<>(R.string.settings_filter_context, 0, this::onContextClick),
cwItem=new CheckableListItem<>(R.string.settings_filter_show_cw, R.string.settings_filter_show_cw_explanation, CheckableListItem.Style.SWITCH, filter==null || filter.filterAction==FilterAction.WARN, ()->toggleCheckableItem(cwItem))
cwItem=new CheckableListItem<>(R.string.settings_filter_show_cw, R.string.settings_filter_show_cw_explanation, CheckableListItem.Style.SWITCH, filter==null || filter.filterAction==FilterAction.WARN, this::toggleCheckableItem)
));
if(filter!=null){
@@ -113,7 +113,7 @@ public class EditFilterFragment extends BaseSettingsFragment<Void> implements On
return 1;
}
private void onDurationClick(){
private void onDurationClick(ListItem<Void> item_){
int[] durationOptions={
1800,
3600,
@@ -182,21 +182,21 @@ public class EditFilterFragment extends BaseSettingsFragment<Void> implements On
alert.setOnDismissListener(dialog->callback.accept(null));
}
private void onWordsClick(){
private void onWordsClick(ListItem<Void> item){
Bundle args=new Bundle();
args.putString("account", accountID);
args.putParcelableArrayList("words", (ArrayList<? extends Parcelable>) keywords.stream().map(Parcels::wrap).collect(Collectors.toCollection(ArrayList::new)));
Nav.goForResult(getActivity(), FilterWordsFragment.class, args, WORDS_RESULT, this);
}
private void onContextClick(){
private void onContextClick(ListItem<Void> item){
Bundle args=new Bundle();
args.putString("account", accountID);
args.putSerializable("context", context);
Nav.goForResult(getActivity(), FilterContextFragment.class, args, CONTEXT_RESULT, this);
}
private void onDeleteClick(){
private void onDeleteClick(ListItem<Void> item_){
AlertDialog alert=new M3AlertDialogBuilder(getActivity())
.setTitle(getString(R.string.settings_delete_filter_title, filter.title))
.setMessage(R.string.settings_delete_filter_confirmation)

View File

@@ -22,10 +22,9 @@ public class FilterContextFragment extends BaseSettingsFragment<FilterContext> i
setTitle(R.string.settings_filter_context);
context=(EnumSet<FilterContext>) getArguments().getSerializable("context");
onDataLoaded(Arrays.stream(FilterContext.values()).map(c->{
CheckableListItem<FilterContext> item=new CheckableListItem<>(c.getDisplayNameRes(), 0, CheckableListItem.Style.CHECKBOX, context.contains(c), null);
CheckableListItem<FilterContext> item=new CheckableListItem<>(c.getDisplayNameRes(), 0, CheckableListItem.Style.CHECKBOX, context.contains(c), this::toggleCheckableItem);
item.parentObject=c;
item.isEnabled=true;
item.onClick=()->toggleCheckableItem(item);
return item;
}).collect(Collectors.toList()));
}

View File

@@ -1,11 +1,6 @@
package org.joinmastodon.android.fragments.settings;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.IntEvaluator;
import android.animation.ObjectAnimator;
import android.app.AlertDialog;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
@@ -27,6 +22,7 @@ import org.joinmastodon.android.model.FilterKeyword;
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.ActionModeHelper;
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.FloatingHintEditTextLayout;
@@ -37,7 +33,6 @@ import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import me.grishka.appkit.FragmentStackActivity;
import me.grishka.appkit.fragments.OnBackPressedListener;
import me.grishka.appkit.utils.V;
@@ -60,7 +55,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
FilterKeyword word=Parcels.unwrap(p);
ListItem<FilterKeyword> item=new ListItem<>(word.keyword, null, null, word);
item.isEnabled=true;
item.onClick=()->onWordClick(item);
item.setOnClick(this::onWordClick);
return item;
}).collect(Collectors.toList()));
setHasOptionsMenu(true);
@@ -114,7 +109,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
inflater.inflate(R.menu.settings_filter_words, menu);
inflater.inflate(R.menu.selectable_list, menu);
}
@Override
@@ -174,7 +169,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
w.keyword=input;
ListItem<FilterKeyword> item=new ListItem<>(w.keyword, null, null, w);
item.isEnabled=true;
item.onClick=()->onWordClick(item);
item.setOnClick(this::onWordClick);
data.add(item);
itemsAdapter.notifyItemInserted(data.size()-1);
}else{
@@ -228,29 +223,15 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
return;
V.setVisibilityAnimated(fab, View.GONE);
actionMode=getActivity().startActionMode(new ActionMode.Callback(){
actionMode=ActionModeHelper.startActionMode(this, ()->elevationOnScrollListener.getCurrentStatusBarColor(), new ActionMode.Callback(){
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu){
ObjectAnimator anim=ObjectAnimator.ofInt(getActivity().getWindow(), "statusBarColor", elevationOnScrollListener.getCurrentStatusBarColor(), UiUtils.getThemeColor(getActivity(), R.attr.colorM3Primary));
anim.setEvaluator(new IntEvaluator(){
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
}
});
anim.start();
((FragmentStackActivity) getActivity()).invalidateSystemBarColors(FilterWordsFragment.this);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu){
mode.getMenuInflater().inflate(R.menu.settings_filter_words_action_mode, menu);
for(int i=0;i<menu.size();i++){
Drawable icon=menu.getItem(i).getIcon().mutate();
icon.setTint(UiUtils.getThemeColor(getActivity(), R.attr.colorM3OnPrimary));
menu.getItem(i).setIcon(icon);
}
deleteItem=menu.findItem(R.id.delete);
return true;
}
@@ -266,21 +247,6 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
@Override
public void onDestroyActionMode(ActionMode mode){
leaveSelectionMode(true);
ObjectAnimator anim=ObjectAnimator.ofInt(getActivity().getWindow(), "statusBarColor", UiUtils.getThemeColor(getActivity(), R.attr.colorM3Primary), elevationOnScrollListener.getCurrentStatusBarColor());
anim.setEvaluator(new IntEvaluator(){
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
}
});
anim.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
getActivity().getWindow().setStatusBarColor(0);
}
});
anim.start();
((FragmentStackActivity) getActivity()).invalidateSystemBarColors(FilterWordsFragment.this);
}
});
@@ -289,7 +255,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
ListItem<FilterKeyword> item=data.get(i);
CheckableListItem<FilterKeyword> newItem=new CheckableListItem<>(item.title, null, CheckableListItem.Style.CHECKBOX, selectAll, null);
newItem.isEnabled=true;
newItem.onClick=()->onSelectionModeWordClick(newItem);
newItem.setOnClick(this::onSelectionModeWordClick);
newItem.parentObject=item.parentObject;
if(selectAll)
selectedItems.add(newItem);
@@ -313,7 +279,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
ListItem<FilterKeyword> item=data.get(i);
ListItem<FilterKeyword> newItem=new ListItem<>(item.title, null, null);
newItem.isEnabled=true;
newItem.onClick=()->onWordClick(newItem);
newItem.setOnClick(this::onWordClick);
newItem.parentObject=item.parentObject;
data.set(i, newItem);
}

View File

@@ -16,7 +16,6 @@ import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.utils.UiUtils;
import java.util.List;
import java.util.Objects;
import androidx.recyclerview.widget.RecyclerView;
import me.grishka.appkit.imageloader.ImageCache;
@@ -26,23 +25,32 @@ import me.grishka.appkit.utils.V;
public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
private ListItem<Void> mediaCacheItem;
private AccountSession session;
private boolean timelineCacheCleared=false;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setTitle(getString(R.string.about_app, getString(R.string.sk_app_name)));
AccountSession s=AccountSessionManager.get(accountID);
session=AccountSessionManager.get(accountID);
onDataLoaded(List.of(
new ListItem<>(R.string.sk_settings_donate, 0, R.drawable.ic_fluent_heart_24_regular, ()->UiUtils.openHashtagTimeline(getActivity(), accountID, getString(R.string.donate_hashtag))),
new ListItem<>(R.string.sk_settings_contribute, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), getString(R.string.repo_url))),
new ListItem<>(R.string.settings_tos, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/terms")),
new ListItem<>(R.string.settings_privacy_policy, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), getString(R.string.privacy_policy_url)), 0, true),
mediaCacheItem=new ListItem<>(R.string.settings_clear_cache, 0, this::onClearMediaCacheClick)
new ListItem<>(R.string.sk_settings_donate, 0, R.drawable.ic_fluent_heart_24_regular, i->UiUtils.openHashtagTimeline(getActivity(), accountID, getString(R.string.donate_hashtag))),
new ListItem<>(R.string.sk_settings_contribute, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), getString(R.string.repo_url))),
new ListItem<>(R.string.settings_tos, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/terms")),
new ListItem<>(R.string.settings_privacy_policy, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), getString(R.string.privacy_policy_url)), 0, true),
mediaCacheItem=new ListItem<>(R.string.settings_clear_cache, 0, this::onClearMediaCacheClick),
new ListItem<>(getString(R.string.sk_settings_clear_timeline_cache), session.domain, this::onClearTimelineCacheClick)
));
updateMediaCacheItem();
}
@Override
protected void onHidden(){
super.onHidden();
if(timelineCacheCleared) getActivity().recreate();
}
@Override
protected void doLoadData(int offset, int count){}
@@ -63,7 +71,7 @@ public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
return adapter;
}
private void onClearMediaCacheClick(){
private void onClearMediaCacheClick(ListItem<?> item){
MastodonAPIController.runInBackground(()->{
Activity activity=getActivity();
ImageCache.getInstance(getActivity()).clear();
@@ -74,6 +82,12 @@ public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
});
}
private void onClearTimelineCacheClick(ListItem<?> item){
session.getCacheController().putHomeTimeline(List.of(), true);
Toast.makeText(getContext(), R.string.sk_timeline_cache_cleared, Toast.LENGTH_SHORT).show();
timelineCacheCleared=true;
}
private void updateMediaCacheItem(){
long size=ImageCache.getInstance(getActivity()).getDiskCache().size();
mediaCacheItem.subtitle=UiUtils.formatFileSize(getActivity(), size, false);

View File

@@ -46,20 +46,20 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
List<ListItem<Void>> items = new ArrayList<>(List.of(
languageItem=new ListItem<>(getString(R.string.default_post_language), postLanguage!=null ? postLanguage.getDisplayName(getContext()) : null, R.drawable.ic_fluent_local_language_24_regular, this::onDefaultLanguageClick),
altTextItem=new CheckableListItem<>(R.string.settings_alt_text_reminders, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.altTextReminders, R.drawable.ic_fluent_image_alt_text_24_regular, ()->toggleCheckableItem(altTextItem)),
playGifsItem=new CheckableListItem<>(R.string.settings_gif, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.playGifs, R.drawable.ic_fluent_gif_24_regular, ()->toggleCheckableItem(playGifsItem)),
overlayMediaItem=new CheckableListItem<>(R.string.sk_settings_continues_playback, R.string.sk_settings_continues_playback_summary, CheckableListItem.Style.SWITCH, GlobalUserPreferences.overlayMedia, R.drawable.ic_fluent_play_circle_hint_24_regular, ()->toggleCheckableItem(overlayMediaItem)),
customTabsItem=new CheckableListItem<>(R.string.settings_custom_tabs, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.useCustomTabs, R.drawable.ic_fluent_link_24_regular, ()->toggleCheckableItem(customTabsItem)),
confirmUnfollowItem=new CheckableListItem<>(R.string.settings_confirm_unfollow, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmUnfollow, R.drawable.ic_fluent_person_delete_24_regular, ()->toggleCheckableItem(confirmUnfollowItem)),
confirmBoostItem=new CheckableListItem<>(R.string.settings_confirm_boost, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmBoost, R.drawable.ic_fluent_arrow_repeat_all_24_regular, ()->toggleCheckableItem(confirmBoostItem)),
confirmDeleteItem=new CheckableListItem<>(R.string.settings_confirm_delete_post, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmDeletePost, R.drawable.ic_fluent_delete_24_regular, ()->toggleCheckableItem(confirmDeleteItem)),
altTextItem=new CheckableListItem<>(R.string.settings_alt_text_reminders, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.altTextReminders, R.drawable.ic_fluent_image_alt_text_24_regular, i->toggleCheckableItem(altTextItem)),
playGifsItem=new CheckableListItem<>(R.string.settings_gif, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.playGifs, R.drawable.ic_fluent_gif_24_regular, i->toggleCheckableItem(playGifsItem)),
overlayMediaItem=new CheckableListItem<>(R.string.sk_settings_continues_playback, R.string.sk_settings_continues_playback_summary, CheckableListItem.Style.SWITCH, GlobalUserPreferences.overlayMedia, R.drawable.ic_fluent_play_circle_hint_24_regular, i->toggleCheckableItem(overlayMediaItem)),
customTabsItem=new CheckableListItem<>(R.string.settings_custom_tabs, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.useCustomTabs, R.drawable.ic_fluent_link_24_regular, i->toggleCheckableItem(customTabsItem)),
confirmUnfollowItem=new CheckableListItem<>(R.string.settings_confirm_unfollow, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmUnfollow, R.drawable.ic_fluent_person_delete_24_regular, i->toggleCheckableItem(confirmUnfollowItem)),
confirmBoostItem=new CheckableListItem<>(R.string.settings_confirm_boost, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmBoost, R.drawable.ic_fluent_arrow_repeat_all_24_regular, i->toggleCheckableItem(confirmBoostItem)),
confirmDeleteItem=new CheckableListItem<>(R.string.settings_confirm_delete_post, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmDeletePost, R.drawable.ic_fluent_delete_24_regular, i->toggleCheckableItem(confirmDeleteItem)),
prefixRepliesItem=new ListItem<>(R.string.sk_settings_prefix_reply_cw_with_re, getPrefixWithRepliesString(), R.drawable.ic_fluent_arrow_reply_24_regular, this::onPrefixRepliesClick),
forwardReportsItem=new CheckableListItem<>(R.string.sk_settings_forward_report_default, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.forwardReportDefault, R.drawable.ic_fluent_arrow_forward_24_regular, ()->toggleCheckableItem(forwardReportsItem)),
loadNewPostsItem=new CheckableListItem<>(R.string.sk_settings_load_new_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.loadNewPosts, R.drawable.ic_fluent_arrow_sync_24_regular, this::onLoadNewPostsClick),
seeNewPostsBtnItem=new CheckableListItem<>(R.string.sk_settings_see_new_posts_button, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNewPostsButton, R.drawable.ic_fluent_arrow_up_24_regular, ()->toggleCheckableItem(seeNewPostsBtnItem)),
remoteLoadingItem=new CheckableListItem<>(R.string.sk_settings_allow_remote_loading, R.string.sk_settings_allow_remote_loading_explanation, CheckableListItem.Style.SWITCH, GlobalUserPreferences.allowRemoteLoading, R.drawable.ic_fluent_communication_24_regular, ()->toggleCheckableItem(remoteLoadingItem), true),
showBoostsItem=new CheckableListItem<>(R.string.sk_settings_show_boosts, 0, CheckableListItem.Style.SWITCH, lp.showBoosts, R.drawable.ic_fluent_arrow_repeat_all_24_regular, ()->toggleCheckableItem(showBoostsItem)),
showRepliesItem=new CheckableListItem<>(R.string.sk_settings_show_replies, 0, CheckableListItem.Style.SWITCH, lp.showReplies, R.drawable.ic_fluent_arrow_reply_24_regular, ()->toggleCheckableItem(showRepliesItem))
forwardReportsItem=new CheckableListItem<>(R.string.sk_settings_forward_report_default, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.forwardReportDefault, R.drawable.ic_fluent_arrow_forward_24_regular, i->toggleCheckableItem(forwardReportsItem)),
loadNewPostsItem=new CheckableListItem<>(R.string.sk_settings_load_new_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.loadNewPosts, R.drawable.ic_fluent_arrow_sync_24_regular, i->onLoadNewPostsClick()),
seeNewPostsBtnItem=new CheckableListItem<>(R.string.sk_settings_see_new_posts_button, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNewPostsButton, R.drawable.ic_fluent_arrow_up_24_regular, i->toggleCheckableItem(seeNewPostsBtnItem)),
remoteLoadingItem=new CheckableListItem<>(R.string.sk_settings_allow_remote_loading, R.string.sk_settings_allow_remote_loading_explanation, CheckableListItem.Style.SWITCH, GlobalUserPreferences.allowRemoteLoading, R.drawable.ic_fluent_communication_24_regular, i->toggleCheckableItem(remoteLoadingItem), true),
showBoostsItem=new CheckableListItem<>(R.string.sk_settings_show_boosts, 0, CheckableListItem.Style.SWITCH, lp.showBoosts, R.drawable.ic_fluent_arrow_repeat_all_24_regular, i->toggleCheckableItem(showBoostsItem)),
showRepliesItem=new CheckableListItem<>(R.string.sk_settings_show_replies, 0, CheckableListItem.Style.SWITCH, lp.showReplies, R.drawable.ic_fluent_arrow_reply_24_regular, i->toggleCheckableItem(showRepliesItem))
));
if(isInstanceAkkoma()) items.add(
@@ -93,7 +93,7 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
@Override
protected void doLoadData(int offset, int count){}
private void onDefaultLanguageClick(){
private void onDefaultLanguageClick(ListItem<?> item){
if (languageResolver == null) return;
ComposeLanguageAlertViewController vc=new ComposeLanguageAlertViewController(getActivity(), null, new ComposeLanguageAlertViewController.SelectedOption(postLanguage), null, languageResolver);
new M3AlertDialogBuilder(getActivity())
@@ -112,14 +112,14 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
.show();
}
private void onPrefixRepliesClick(){
private void onPrefixRepliesClick(ListItem<?> item){
int selected=GlobalUserPreferences.prefixReplies.ordinal();
int[] newSelected={selected};
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_settings_prefix_reply_cw_with_re)
.setSingleChoiceItems((String[]) IntStream.of(R.string.sk_settings_prefix_replies_never, R.string.sk_settings_prefix_replies_always, R.string.sk_settings_prefix_replies_to_others).mapToObj(this::getString).toArray(String[]::new),
selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->{
selected, (dlg, which)->newSelected[0]=which)
.setPositiveButton(R.string.ok, (dlg, which)->{
GlobalUserPreferences.prefixReplies=GlobalUserPreferences.PrefixRepliesMode.values()[newSelected[0]];
prefixRepliesItem.subtitleRes=getPrefixWithRepliesString();
rebindItem(prefixRepliesItem);
@@ -128,7 +128,7 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
.show();
}
private void onReplyVisibilityClick(){
private void onReplyVisibilityClick(ListItem<?> item){
AccountLocalPreferences lp=getLocalPrefs();
int selected=lp.timelineReplyVisibility==null ? 2 : switch(lp.timelineReplyVisibility){
case "following" -> 0;
@@ -139,8 +139,8 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_settings_prefix_reply_cw_with_re)
.setSingleChoiceItems((String[]) IntStream.of(R.string.sk_settings_reply_visibility_following, R.string.sk_settings_reply_visibility_self, R.string.sk_settings_reply_visibility_all).mapToObj(this::getString).toArray(String[]::new),
selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->{
selected, (dlg, which)->newSelected[0]=which)
.setPositiveButton(R.string.ok, (dlg, which)->{
lp.timelineReplyVisibility=switch(newSelected[0]){
case 0 -> "following";
case 1 -> "self";
@@ -176,6 +176,8 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
GlobalUserPreferences.allowRemoteLoading=remoteLoadingItem.checked;
GlobalUserPreferences.save();
AccountLocalPreferences lp=getLocalPrefs();
boolean restartPlease=lp.showBoosts!=showBoostsItem.checked
|| lp.showReplies!=showRepliesItem.checked;
lp.showBoosts=showBoostsItem.checked;
lp.showReplies=showRepliesItem.checked;
lp.save();
@@ -186,6 +188,7 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
s.preferences.postingDefaultLanguage=newPostLanguage.language.getLanguage();
s.savePreferencesLater();
}
if(restartPlease) getActivity().recreate();
}
@Override

View File

@@ -39,7 +39,7 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
@Override
protected void doLoadData(int offset, int count){}
private void onTestEmailConfirmClick(){
private void onTestEmailConfirmClick(ListItem<?> item){
AccountSession sess=AccountSessionManager.getInstance().getAccount(accountID);
sess.activated=false;
sess.activationInfo=new AccountActivationInfo("test@email", System.currentTimeMillis());
@@ -49,18 +49,18 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
Nav.goClearingStack(getActivity(), AccountActivationFragment.class, args);
}
private void onForceSelfUpdateClick(){
private void onForceSelfUpdateClick(ListItem<?> item){
GithubSelfUpdater.forceUpdate=true;
GithubSelfUpdater.getInstance().maybeCheckForUpdates();
restartUI();
}
private void onResetUpdaterClick(){
private void onResetUpdaterClick(ListItem<?> item){
GithubSelfUpdater.getInstance().reset();
restartUI();
}
private void onResetDiscoverBannersClick(){
private void onResetDiscoverBannersClick(ListItem<?> item){
DiscoverInfoBannerHelper.reset();
restartUI();
}

View File

@@ -56,29 +56,29 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
onDataLoaded(List.of(
themeItem=new ListItem<>(R.string.settings_theme, getAppearanceValue(), R.drawable.ic_fluent_weather_moon_24_regular, this::onAppearanceClick),
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, i->onTrueBlackModeClick(), true),
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),
revealCWsItem=new CheckableListItem<>(R.string.sk_settings_always_reveal_content_warnings, 0, CheckableListItem.Style.SWITCH, lp.revealCWs, R.drawable.ic_fluent_chat_warning_24_regular, ()->toggleCheckableItem(revealCWsItem)),
hideSensitiveMediaItem=new CheckableListItem<>(R.string.settings_hide_sensitive_media, 0, CheckableListItem.Style.SWITCH, lp.hideSensitiveMedia, R.drawable.ic_fluent_flag_24_regular, ()->toggleCheckableItem(hideSensitiveMediaItem)),
interactionCountsItem=new CheckableListItem<>(R.string.settings_show_interaction_counts, 0, CheckableListItem.Style.SWITCH, lp.showInteractionCounts, R.drawable.ic_fluent_number_row_24_regular, ()->toggleCheckableItem(interactionCountsItem)),
emojiInNamesItem=new CheckableListItem<>(R.string.settings_show_emoji_in_names, 0, CheckableListItem.Style.SWITCH, lp.customEmojiInNames, R.drawable.ic_fluent_emoji_24_regular, ()->toggleCheckableItem(emojiInNamesItem)),
marqueeItem=new CheckableListItem<>(R.string.sk_settings_enable_marquee, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.toolbarMarquee, R.drawable.ic_fluent_text_more_24_regular, ()->toggleCheckableItem(marqueeItem)),
reduceMotionItem=new CheckableListItem<>(R.string.sk_settings_reduce_motion, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.reduceMotion, R.drawable.ic_fluent_star_emphasis_24_regular, ()->toggleCheckableItem(reduceMotionItem)),
disableSwipeItem=new CheckableListItem<>(R.string.sk_settings_tabs_disable_swipe, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableSwipe, R.drawable.ic_fluent_swipe_right_24_regular, ()->toggleCheckableItem(disableSwipeItem)),
altIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showAltIndicator, R.drawable.ic_fluent_scan_text_24_regular, ()->toggleCheckableItem(altIndicatorItem)),
noAltIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_no_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNoAltIndicator, R.drawable.ic_fluent_important_24_regular, ()->toggleCheckableItem(noAltIndicatorItem)),
collapsePostsItem=new CheckableListItem<>(R.string.sk_settings_collapse_long_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.collapseLongPosts, R.drawable.ic_fluent_chevron_down_24_regular, ()->toggleCheckableItem(collapsePostsItem)),
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)),
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)),
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)),
pronounsInThreadsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_threads, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInThreads, 0, ()->toggleCheckableItem(pronounsInThreadsItem)),
pronounsInUserListingsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_user_listings, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInUserListings, 0, ()->toggleCheckableItem(pronounsInUserListingsItem))
revealCWsItem=new CheckableListItem<>(R.string.sk_settings_always_reveal_content_warnings, 0, CheckableListItem.Style.SWITCH, lp.revealCWs, R.drawable.ic_fluent_chat_warning_24_regular, i->toggleCheckableItem(revealCWsItem)),
hideSensitiveMediaItem=new CheckableListItem<>(R.string.settings_hide_sensitive_media, 0, CheckableListItem.Style.SWITCH, lp.hideSensitiveMedia, R.drawable.ic_fluent_flag_24_regular, i->toggleCheckableItem(hideSensitiveMediaItem)),
interactionCountsItem=new CheckableListItem<>(R.string.settings_show_interaction_counts, 0, CheckableListItem.Style.SWITCH, lp.showInteractionCounts, R.drawable.ic_fluent_number_row_24_regular, i->toggleCheckableItem(interactionCountsItem)),
emojiInNamesItem=new CheckableListItem<>(R.string.settings_show_emoji_in_names, 0, CheckableListItem.Style.SWITCH, lp.customEmojiInNames, R.drawable.ic_fluent_emoji_24_regular, i->toggleCheckableItem(emojiInNamesItem)),
marqueeItem=new CheckableListItem<>(R.string.sk_settings_enable_marquee, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.toolbarMarquee, R.drawable.ic_fluent_text_more_24_regular, i->toggleCheckableItem(marqueeItem)),
reduceMotionItem=new CheckableListItem<>(R.string.sk_settings_reduce_motion, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.reduceMotion, R.drawable.ic_fluent_star_emphasis_24_regular, i->toggleCheckableItem(reduceMotionItem)),
disableSwipeItem=new CheckableListItem<>(R.string.sk_settings_tabs_disable_swipe, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableSwipe, R.drawable.ic_fluent_swipe_right_24_regular, i->toggleCheckableItem(disableSwipeItem)),
altIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showAltIndicator, R.drawable.ic_fluent_scan_text_24_regular, i->toggleCheckableItem(altIndicatorItem)),
noAltIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_no_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNoAltIndicator, R.drawable.ic_fluent_important_24_regular, i->toggleCheckableItem(noAltIndicatorItem)),
collapsePostsItem=new CheckableListItem<>(R.string.sk_settings_collapse_long_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.collapseLongPosts, R.drawable.ic_fluent_chevron_down_24_regular, i->toggleCheckableItem(collapsePostsItem)),
spectatorModeItem=new CheckableListItem<>(R.string.sk_settings_hide_interaction, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.spectatorMode, R.drawable.ic_fluent_star_off_24_regular, i->toggleCheckableItem(spectatorModeItem)),
hideFabItem=new CheckableListItem<>(R.string.sk_settings_hide_fab, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.autoHideFab, R.drawable.ic_fluent_edit_24_regular, i->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, i->toggleCheckableItem(translateOpenedItem)),
likeIconItem=new CheckableListItem<>(R.string.sk_settings_like_icon, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.likeIcon, R.drawable.ic_fluent_heart_24_regular, i->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, i->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, i->toggleCheckableItem(disablePillItem)),
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, i->toggleCheckableItem(showNavigationLabelsItem), true),
pronounsInTimelinesItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_timelines, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInTimelines, 0, i->toggleCheckableItem(pronounsInTimelinesItem)),
pronounsInThreadsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_threads, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInThreads, 0, i->toggleCheckableItem(pronounsInThreadsItem)),
pronounsInUserListingsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_user_listings, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInUserListings, 0, i->toggleCheckableItem(pronounsInUserListingsItem))
));
trueBlackModeItem.checkedChangeListener=checked->onTrueBlackModeClick();
}
@@ -166,7 +166,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
maybeApplyNewThemeRightNow(null, null, prev);
}
private void onAppearanceClick(){
private void onAppearanceClick(ListItem<?> item_){
int selected=switch(GlobalUserPreferences.theme){
case LIGHT -> 0;
case DARK -> 1;
@@ -197,7 +197,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
.show();
}
private void onColorClick(){
private void onColorClick(ListItem<?> item_){
boolean multiple=AccountSessionManager.getInstance().getLoggedInAccounts().size() > 1;
int indexOffset=multiple ? 1 : 0;
int selected=lp.color==null ? 0 : lp.color.ordinal() + indexOffset;
@@ -234,7 +234,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
alert.show();
}
private void onPublishTextClick(){
private void onPublishTextClick(ListItem<?> item_){
TextInputFrameLayout input = new TextInputFrameLayout(
getContext(),
getString(R.string.publish),
@@ -257,7 +257,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
.show();
}
private void onAutoRevealSpoilersClick(){
private void onAutoRevealSpoilersClick(ListItem<?> item_){
int selected=GlobalUserPreferences.autoRevealEqualSpoilers.ordinal();
int[] newSelected={selected};
new M3AlertDialogBuilder(getActivity())

View File

@@ -67,16 +67,14 @@ public class SettingsFiltersFragment extends BaseSettingsFragment<Filter>{
Nav.go(getActivity(), EditFilterFragment.class, args);
}
private void onAddFilterClick(){
private void onAddFilterClick(ListItem<?> item){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), EditFilterFragment.class, args);
}
private ListItem<Filter> makeListItem(Filter f){
ListItem<Filter> item=new ListItem<>(f.title, getString(f.isActive() ? R.string.filter_active : R.string.filter_inactive), null, f);
item.onClick=()->onFilterClick(item);
item.isEnabled=true;
ListItem<Filter> item=new ListItem<>(f.title, getString(f.isActive() ? R.string.filter_active : R.string.filter_inactive), this::onFilterClick, f);
return item;
}

View File

@@ -19,6 +19,7 @@ import org.joinmastodon.android.ui.utils.UiUtils;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import me.grishka.appkit.Nav;
@@ -36,15 +37,15 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
lp=s.getLocalPreferences();
onDataLoaded(List.of(
new ListItem<>(AccountSessionManager.get(accountID).domain, getString(R.string.settings_server_explanation), R.drawable.ic_fluent_server_24_regular, this::onServerClick),
new ListItem<>(R.string.sk_settings_profile, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/profile")),
new ListItem<>(R.string.sk_settings_posting, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/preferences/other")),
new ListItem<>(R.string.sk_settings_auth, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/auth/edit"), 0, true),
contentTypesItem=new CheckableListItem<>(R.string.sk_settings_content_types, R.string.sk_settings_content_types_explanation, CheckableListItem.Style.SWITCH, lp.contentTypesEnabled, R.drawable.ic_fluent_text_edit_style_24_regular, this::onContentTypeClick),
new ListItem<>(R.string.sk_settings_profile, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/profile")),
new ListItem<>(R.string.sk_settings_posting, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/preferences/other")),
new ListItem<>(R.string.sk_settings_auth, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/auth/edit"), 0, true),
contentTypesItem=new CheckableListItem<>(R.string.sk_settings_content_types, R.string.sk_settings_content_types_explanation, CheckableListItem.Style.SWITCH, lp.contentTypesEnabled, R.drawable.ic_fluent_text_edit_style_24_regular, i->onContentTypeClick()),
defaultContentTypeItem=new ListItem<>(R.string.sk_settings_default_content_type, lp.defaultContentType.getName(), R.drawable.ic_fluent_text_bold_24_regular, this::onDefaultContentTypeClick, 0, true),
emojiReactionsItem=new CheckableListItem<>(R.string.sk_settings_emoji_reactions, R.string.sk_settings_emoji_reactions_explanation, CheckableListItem.Style.SWITCH, lp.emojiReactionsEnabled, R.drawable.ic_fluent_emoji_laugh_24_regular, this::onEmojiReactionsClick),
emojiReactionsItem=new CheckableListItem<>(R.string.sk_settings_emoji_reactions, R.string.sk_settings_emoji_reactions_explanation, CheckableListItem.Style.SWITCH, lp.emojiReactionsEnabled, R.drawable.ic_fluent_emoji_laugh_24_regular, i->onEmojiReactionsClick()),
showEmojiReactionsItem=new ListItem<>(R.string.sk_settings_show_emoji_reactions, getShowEmojiReactionsString(), R.drawable.ic_fluent_emoji_24_regular, this::onShowEmojiReactionsClick, 0, true),
localOnlyItem=new CheckableListItem<>(R.string.sk_settings_support_local_only, R.string.sk_settings_local_only_explanation, CheckableListItem.Style.SWITCH, lp.localOnlySupported, R.drawable.ic_fluent_eye_24_regular, this::onLocalOnlyClick),
glitchModeItem=new CheckableListItem<>(R.string.sk_settings_glitch_instance, R.string.sk_settings_glitch_mode_explanation, CheckableListItem.Style.SWITCH, lp.glitchInstance, R.drawable.ic_fluent_eye_24_filled, ()->toggleCheckableItem(glitchModeItem))
localOnlyItem=new CheckableListItem<>(R.string.sk_settings_support_local_only, R.string.sk_settings_local_only_explanation, CheckableListItem.Style.SWITCH, lp.localOnlySupported, R.drawable.ic_fluent_eye_24_regular, i->onLocalOnlyClick()),
glitchModeItem=new CheckableListItem<>(R.string.sk_settings_glitch_instance, R.string.sk_settings_glitch_mode_explanation, CheckableListItem.Style.SWITCH, lp.glitchInstance, R.drawable.ic_fluent_eye_24_filled, i->toggleCheckableItem(glitchModeItem))
));
contentTypesItem.checkedChangeListener=checked->onContentTypeClick();
defaultContentTypeItem.isEnabled=contentTypesItem.checked;
@@ -68,7 +69,7 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
E.post(new StatusDisplaySettingsChangedEvent(accountID));
}
private void onServerClick(){
private void onServerClick(ListItem<?> item){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), SettingsServerFragment.class, args);
@@ -87,23 +88,23 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
defaultContentTypeItem.subtitleRes=lp.defaultContentType.getName();
}
private void onDefaultContentTypeClick(){
int selected=lp.defaultContentType.ordinal();
int[] newSelected={selected};
ContentType[] supportedContentTypes=Arrays.stream(ContentType.values())
private void onDefaultContentTypeClick(ListItem<?> item_){
List<ContentType> supportedContentTypes=Arrays.stream(ContentType.values())
.filter(t->t.supportedByInstance(getInstance().orElse(null)))
.toArray(ContentType[]::new);
String[] names=Arrays.stream(supportedContentTypes)
.collect(Collectors.toList());
int selected=supportedContentTypes.indexOf(lp.defaultContentType);
int[] newSelected={selected};
String[] names=supportedContentTypes.stream()
.map(ContentType::getName)
.map(this::getString)
.toArray(String[]::new);
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.settings_theme)
.setTitle(R.string.sk_settings_default_content_type)
.setSingleChoiceItems(names,
selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->{
ContentType type=supportedContentTypes[newSelected[0]];
ContentType type=supportedContentTypes.get(newSelected[0]);
lp.defaultContentType=type;
defaultContentTypeItem.subtitleRes=type.getName();
rebindItem(defaultContentTypeItem);
@@ -112,7 +113,7 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
.show();
}
private void onShowEmojiReactionsClick(){
private void onShowEmojiReactionsClick(ListItem<?> item_){
int selected=lp.showEmojiReactions.ordinal();
int[] newSelected={selected};
new M3AlertDialogBuilder(getActivity())

View File

@@ -18,6 +18,7 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.AccountSwitcherSheet;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.HideableSingleViewRecyclerAdapter;
import org.joinmastodon.android.ui.utils.UiUtils;
@@ -49,7 +50,7 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
account = AccountSessionManager.get(accountID);
account=AccountSessionManager.get(accountID);
setTitle(R.string.settings);
setSubtitle(account.getFullUsername());
onDataLoaded(List.of(
@@ -59,15 +60,17 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
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<>(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<>(R.string.manage_accounts, 0, R.drawable.ic_fluent_person_swap_24_regular, this::onManageAccountsClick),
new ListItem<>(R.string.log_out, 0, R.drawable.ic_fluent_sign_out_24_regular, this::onLogOutClick, R.attr.colorM3Error, false)
));
Instance instance = AccountSessionManager.getInstance().getInstanceInfo(account.domain);
if (!instance.isAkkoma())
Instance instance=AccountSessionManager.getInstance().getInstanceInfo(account.domain);
if(!instance.isAkkoma()){
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")){
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, i->Nav.go(getActivity(), SettingsDebugFragment.class, makeFragmentArgs()), null, 0, true));
}
AccountSession session=AccountSessionManager.get(accountID);
@@ -128,35 +131,39 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
return args;
}
private void onBehaviorClick(){
private void onBehaviorClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsBehaviorFragment.class, makeFragmentArgs());
}
private void onDisplayClick(){
private void onDisplayClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsDisplayFragment.class, makeFragmentArgs());
}
private void onPrivacyClick(){
private void onPrivacyClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsPrivacyFragment.class, makeFragmentArgs());
}
private void onFiltersClick(){
private void onFiltersClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsFiltersFragment.class, makeFragmentArgs());
}
private void onNotificationsClick(){
private void onNotificationsClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsNotificationsFragment.class, makeFragmentArgs());
}
private void onInstanceClick(){
private void onInstanceClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsInstanceFragment.class, makeFragmentArgs());
}
private void onAboutClick(){
private void onAboutClick(ListItem<?> item_){
Nav.go(getActivity(), SettingsAboutAppFragment.class, makeFragmentArgs());
}
private void onLogOutClick(){
private void onManageAccountsClick(ListItem<?> item){
new AccountSwitcherSheet(getActivity(), null).show();
}
private void onLogOutClick(ListItem<?> item_){
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
new M3AlertDialogBuilder(getActivity())
.setMessage(getString(R.string.confirm_log_out, session.getFullUsername()))

View File

@@ -27,7 +27,6 @@ import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.HideableSingleViewRecyclerAdapter;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.unifiedpush.android.connector.RegistrationDialogContent;
import org.unifiedpush.android.connector.UnifiedPush;
import java.time.Instant;
@@ -73,21 +72,21 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
useUnifiedPush=!getDistributor(getContext()).isEmpty();
onDataLoaded(List.of(
pauseItem=new CheckableListItem<>(getString(R.string.pause_all_notifications), getPauseItemSubtitle(), CheckableListItem.Style.SWITCH, false, R.drawable.ic_fluent_alert_snooze_24_regular, ()->onPauseNotificationsClick(false)),
pauseItem=new CheckableListItem<>(getString(R.string.pause_all_notifications), getPauseItemSubtitle(), CheckableListItem.Style.SWITCH, false, R.drawable.ic_fluent_alert_snooze_24_regular, i->onPauseNotificationsClick(false)),
policyItem=new ListItem<>(R.string.settings_notifications_policy, 0, R.drawable.ic_fluent_people_24_regular, this::onNotificationsPolicyClick, 0, true),
mentionsItem=new CheckableListItem<>(R.string.notification_type_mentions_and_replies, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.mention, R.drawable.ic_fluent_mention_24_regular, ()->toggleCheckableItem(mentionsItem)),
boostsItem=new CheckableListItem<>(R.string.notification_type_reblog, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.reblog, R.drawable.ic_fluent_arrow_repeat_all_24_regular, ()->toggleCheckableItem(boostsItem)),
favoritesItem=new CheckableListItem<>(R.string.notification_type_favorite, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.favourite, R.drawable.ic_fluent_star_24_regular, ()->toggleCheckableItem(favoritesItem)),
followersItem=new CheckableListItem<>(R.string.notification_type_follow, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.follow, R.drawable.ic_fluent_person_add_24_regular, ()->toggleCheckableItem(followersItem)),
pollsItem=new CheckableListItem<>(R.string.notification_type_poll, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.poll, R.drawable.ic_fluent_poll_24_regular, ()->toggleCheckableItem(pollsItem)),
updateItem=new CheckableListItem<>(R.string.sk_notification_type_update, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.update, R.drawable.ic_fluent_history_24_regular, ()->toggleCheckableItem(updateItem)),
postsItem=new CheckableListItem<>(R.string.sk_notification_type_posts, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.status, R.drawable.ic_fluent_chat_24_regular, ()->toggleCheckableItem(postsItem), true),
mentionsItem=new CheckableListItem<>(R.string.notification_type_mentions_and_replies, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.mention, R.drawable.ic_fluent_mention_24_regular, i->toggleCheckableItem(mentionsItem)),
boostsItem=new CheckableListItem<>(R.string.notification_type_reblog, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.reblog, R.drawable.ic_fluent_arrow_repeat_all_24_regular, i->toggleCheckableItem(boostsItem)),
favoritesItem=new CheckableListItem<>(R.string.notification_type_favorite, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.favourite, R.drawable.ic_fluent_star_24_regular, i->toggleCheckableItem(favoritesItem)),
followersItem=new CheckableListItem<>(R.string.notification_type_follow, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.follow, R.drawable.ic_fluent_person_add_24_regular, i->toggleCheckableItem(followersItem)),
pollsItem=new CheckableListItem<>(R.string.notification_type_poll, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.poll, R.drawable.ic_fluent_poll_24_regular, i->toggleCheckableItem(pollsItem)),
updateItem=new CheckableListItem<>(R.string.sk_notification_type_update, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.update, R.drawable.ic_fluent_history_24_regular, i->toggleCheckableItem(updateItem)),
postsItem=new CheckableListItem<>(R.string.sk_notification_type_posts, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.status, R.drawable.ic_fluent_chat_24_regular, i->toggleCheckableItem(postsItem), true),
uniformIconItem=new CheckableListItem<>(R.string.sk_settings_uniform_icon_for_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.uniformNotificationIcon, R.drawable.ic_ntf_logo, ()->toggleCheckableItem(uniformIconItem)),
deleteItem=new CheckableListItem<>(R.string.sk_settings_enable_delete_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.enableDeleteNotifications, R.drawable.ic_fluent_mail_inbox_dismiss_24_regular, ()->toggleCheckableItem(deleteItem)),
onlyLatestItem=new CheckableListItem<>(R.string.sk_settings_single_notification, 0, CheckableListItem.Style.SWITCH, lp.keepOnlyLatestNotification, R.drawable.ic_fluent_convert_range_24_regular, ()->toggleCheckableItem(onlyLatestItem), true),
unifiedPushItem=new CheckableListItem<>(R.string.sk_settings_unifiedpush, 0, CheckableListItem.Style.SWITCH, useUnifiedPush, R.drawable.ic_fluent_alert_arrow_up_24_regular, this::onUnifiedPush, true)
uniformIconItem=new CheckableListItem<>(R.string.sk_settings_uniform_icon_for_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.uniformNotificationIcon, R.drawable.ic_ntf_logo, i->toggleCheckableItem(uniformIconItem)),
deleteItem=new CheckableListItem<>(R.string.sk_settings_enable_delete_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.enableDeleteNotifications, R.drawable.ic_fluent_mail_inbox_dismiss_24_regular, i->toggleCheckableItem(deleteItem)),
onlyLatestItem=new CheckableListItem<>(R.string.sk_settings_single_notification, 0, CheckableListItem.Style.SWITCH, lp.keepOnlyLatestNotification, R.drawable.ic_fluent_convert_range_24_regular, i->toggleCheckableItem(onlyLatestItem), true),
unifiedPushItem=new CheckableListItem<>(R.string.sk_settings_unifiedpush, 0, CheckableListItem.Style.SWITCH, useUnifiedPush, R.drawable.ic_fluent_alert_arrow_up_24_regular, i->onUnifiedPushClick(), true)
));
//only enable when distributors, who can receive notifications, are available
@@ -98,7 +97,7 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
typeItems=List.of(mentionsItem, boostsItem, favoritesItem, followersItem, pollsItem, updateItem, postsItem);
pauseItem.checkedChangeListener=checked->onPauseNotificationsClick(true);
unifiedPushItem.checkedChangeListener=checked->onUnifiedPush();
unifiedPushItem.checkedChangeListener=checked->onUnifiedPushClick();
updatePolicyItem(null);
updatePauseItem();
}
@@ -254,7 +253,7 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
alert.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
}
private void onNotificationsPolicyClick(){
private void onNotificationsPolicyClick(ListItem<?> item_){
String[] items=Stream.of(
R.string.notifications_policy_anyone,
R.string.notifications_policy_followed,
@@ -328,7 +327,7 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
}
}
private void onUnifiedPush(){
private void onUnifiedPushClick(){
if(getDistributor(getContext()).isEmpty()){
List<String> distributors = UnifiedPush.getDistributors(getContext(), new ArrayList<>());
showUnifiedPushRegisterDialog(distributors);

View File

@@ -2,40 +2,98 @@ package org.joinmastodon.android.fragments.settings;
import android.os.Bundle;
import androidx.annotation.StringRes;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.StatusPrivacy;
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
import org.joinmastodon.android.model.viewmodel.ListItem;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import java.util.ArrayList;
import java.util.List;
public class SettingsPrivacyFragment extends BaseSettingsFragment<Void>{
private CheckableListItem<Void> discoverableItem, indexableItem;
private CheckableListItem<Void> discoverableItem, indexableItem, lockedItem;
private ListItem<Void> privacyItem;
private StatusPrivacy privacy=null;
private Instance instance;
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setTitle(R.string.settings_privacy);
Account self=AccountSessionManager.get(accountID).self;
AccountSession session=AccountSessionManager.get(accountID);
Account self=session.self;
instance=AccountSessionManager.getInstance().getInstanceInfo(session.domain);
privacy=self.source.privacy;
onDataLoaded(List.of(
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_fluent_search_24_regular, ()->toggleCheckableItem(indexableItem))
privacyItem=new ListItem<>(R.string.sk_settings_default_visibility, getPrivacyString(privacy), R.drawable.ic_fluent_eye_24_regular, this::onPrivacyClick, 0, true),
lockedItem=new CheckableListItem<>(R.string.sk_settings_lock_account, 0, CheckableListItem.Style.SWITCH, self.locked, R.drawable.ic_fluent_person_available_24_regular, i->toggleCheckableItem(lockedItem))
));
if(self.source.indexable==null)
indexableItem.isEnabled=false;
if(!instance.isAkkoma()){
data.addAll(List.of(
discoverableItem=new CheckableListItem<>(R.string.settings_discoverable, 0, CheckableListItem.Style.SWITCH, self.discoverable, R.drawable.ic_fluent_thumb_like_dislike_24_regular, i->toggleCheckableItem(discoverableItem)),
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, i->toggleCheckableItem(indexableItem))
));
if(self.source.indexable==null)
indexableItem.isEnabled=false;
}
}
@Override
protected void doLoadData(int offset, int count){}
private @StringRes int getPrivacyString(StatusPrivacy p){
if(p==null) return R.string.visibility_public;
return switch(p){
case PUBLIC -> R.string.visibility_public;
case UNLISTED -> R.string.sk_visibility_unlisted;
case PRIVATE -> R.string.visibility_followers_only;
case DIRECT -> R.string.visibility_private;
case LOCAL -> R.string.sk_local_only;
};
}
private void onPrivacyClick(ListItem<?> item_){
Account self=AccountSessionManager.get(accountID).self;
List<StatusPrivacy> options=new ArrayList<>(List.of(StatusPrivacy.PUBLIC, StatusPrivacy.UNLISTED, StatusPrivacy.PRIVATE, StatusPrivacy.DIRECT));
if(instance.isAkkoma()) options.add(StatusPrivacy.LOCAL);
int selected=options.indexOf(self.source.privacy);
int[] newSelected={selected};
new M3AlertDialogBuilder(getActivity())
.setTitle(R.string.sk_settings_default_visibility)
.setSingleChoiceItems(options.stream().map(this::getPrivacyString).map(this::getString).toArray(String[]::new),
selected, (dlg, item)->newSelected[0]=item)
.setPositiveButton(R.string.ok, (dlg, item)->{
privacy=options.get(newSelected[0]);
privacyItem.subtitleRes=getPrivacyString(privacy);
rebindItem(privacyItem);
})
.setNegativeButton(R.string.cancel, null)
.show();
}
@Override
public void onPause(){
super.onPause();
Account self=AccountSessionManager.get(accountID).self;
if(self.discoverable!=discoverableItem.checked || (self.source.indexable!=null && self.source.indexable!=indexableItem.checked)){
self.discoverable=discoverableItem.checked;
self.source.indexable=indexableItem.checked;
AccountSessionManager.get(accountID).savePreferencesLater();
AccountSession s=AccountSessionManager.get(accountID);
Account self=s.self;
boolean savePlease=self.locked!=lockedItem.checked
|| self.source.privacy!=privacy
|| (discoverableItem!=null && self.discoverable!=discoverableItem.checked)
|| (indexableItem!=null && self.source.indexable!=null && self.source.indexable!=indexableItem.checked);
if(savePlease){
if(discoverableItem!=null) self.discoverable=discoverableItem.checked;
if(indexableItem!=null) self.source.indexable=indexableItem.checked;
self.locked=lockedItem.checked;
s.preferences.postingDefaultVisibility=privacy;
s.savePreferencesLater();
}
}
}

View File

@@ -145,7 +145,7 @@ public class SettingsServerAboutFragment extends LoaderFragment{
if(!TextUtils.isEmpty(instance.email)){
needDivider=true;
SimpleListItemViewHolder holder=new SimpleListItemViewHolder(getActivity(), scrollingLayout);
ListItem<Void> item=new ListItem<>(R.string.send_email_to_server_admin, 0, R.drawable.ic_fluent_mail_24_regular, ()->{});
ListItem<Void> item=new ListItem<>(R.string.send_email_to_server_admin, 0, R.drawable.ic_fluent_mail_24_regular, i->{});
holder.bind(item);
holder.itemView.setBackground(UiUtils.getThemeDrawable(getActivity(), android.R.attr.selectableItemBackground));
holder.itemView.setOnClickListener(v->openAdminEmail());

View File

@@ -6,8 +6,6 @@ import android.text.TextUtils;
import androidx.annotation.Nullable;
import org.joinmastodon.android.api.ObjectValidationException;
import org.joinmastodon.android.api.RequiredField;
import org.joinmastodon.android.api.requests.instance.GetInstance;
import org.parceler.Parcel;
import java.time.Instant;
@@ -15,9 +13,6 @@ import java.time.LocalDate;
import java.util.Collections;
import java.util.List;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
/**
* Represents a user of Mastodon and their associated profile.
*/
@@ -163,26 +158,26 @@ public class Account extends BaseModel implements Searchable{
if(fields!=null){
for(AccountField f:fields)
f.postprocess();
} else {
fields = Collections.emptyList();
}else{
fields=Collections.emptyList();
}
if(emojis!=null){
for(Emoji e:emojis)
e.postprocess();
} else {
emojis = Collections.emptyList();
}else{
emojis=Collections.emptyList();
}
if(moved!=null)
moved.postprocess();
if(fqn == null) fqn = getFullyQualifiedName();
if(id == null) id = "";
if(username == null) username = "";
if(fqn==null) fqn=getFullyQualifiedName();
if(id==null) id="";
if(username==null) username="";
if(TextUtils.isEmpty(displayName))
displayName = !TextUtils.isEmpty(username) ? username : "";
if(acct == null) acct = "";
if(url == null) url = "";
if(note == null) note = "";
if(avatar == null) avatar = "";
displayName=!TextUtils.isEmpty(username) ? username : "";
if(acct==null) acct="";
if(url==null) url="";
if(note==null) note="";
if(avatar==null) avatar="";
}
public boolean isLocal(){
@@ -212,6 +207,10 @@ public class Account extends BaseModel implements Searchable{
return fqn != null ? fqn : acct.split("@")[0] + "@" + getDomainFromURL();
}
public String getDisplayName(){
return '\u2068'+displayName+'\u2069';
}
@Override
public String toString(){
return "Account{"+

View File

@@ -26,22 +26,13 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import org.joinmastodon.android.api.ObjectValidationException;
import org.joinmastodon.android.api.RequiredField;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.EmojiReactionsUpdatedEvent;
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.utils.StatusTextEncoder;
import org.parceler.Parcel;
import java.lang.reflect.Type;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.regex.Pattern;
@Parcel
@@ -104,6 +95,7 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
private transient String strippedText;
public transient TranslationState translationState=TranslationState.HIDDEN;
public transient Translation translation;
public transient boolean fromStatusCreated;
public Status(){}

View File

@@ -33,9 +33,9 @@ public class AccountViewModel{
V.dp(50), V.dp(50));
emojiHelper=new CustomEmojiHelper();
if(session.getLocalPreferences().customEmojiInNames)
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
else
parsedName=account.displayName;
parsedName=account.getDisplayName();
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName);
ssb.append(parsedBio);

View File

@@ -9,42 +9,42 @@ public class CheckableListItem<T> extends ListItem<T>{
public boolean checked;
public Consumer<Boolean> checkedChangeListener;
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick, T parentObject, boolean dividerAfter){
super(title, subtitle, iconRes, onClick, parentObject, 0, dividerAfter);
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick, T parentObject, boolean dividerAfter){
super(title, subtitle, iconRes, (Consumer<ListItem<T>>)(Object)onClick, parentObject, 0, dividerAfter);
this.style=style;
this.checked=checked;
}
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Runnable onClick){
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick){
this(title, subtitle, style, checked, 0, onClick, null, false);
}
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Runnable onClick, T parentObject){
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick, T parentObject){
this(title, subtitle, style, checked, 0, onClick, parentObject, false);
}
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick){
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick){
this(title, subtitle, style, checked, iconRes, onClick, null, false);
}
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick, T parentObject){
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick, T parentObject){
this(title, subtitle, style, checked, iconRes, onClick, parentObject, false);
}
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Runnable onClick){
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick){
this(titleRes, subtitleRes, style, checked, 0, onClick, false);
}
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Runnable onClick, boolean dividerAfter){
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick, boolean dividerAfter){
this(titleRes, subtitleRes, style, checked, 0, onClick, dividerAfter);
}
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Runnable onClick){
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick){
this(titleRes, subtitleRes, style, checked, iconRes, onClick, false);
}
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Runnable onClick, boolean dividerAfter){
super(titleRes, subtitleRes, iconRes, onClick, 0, dividerAfter);
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick, boolean dividerAfter){
super(titleRes, subtitleRes, iconRes, (Consumer<ListItem<T>>)(Object)onClick, 0, dividerAfter);
this.style=style;
this.checked=checked;
}

View File

@@ -2,6 +2,8 @@ package org.joinmastodon.android.model.viewmodel;
import org.joinmastodon.android.R;
import java.util.function.Consumer;
import androidx.annotation.DrawableRes;
import androidx.annotation.StringRes;
@@ -16,11 +18,11 @@ public class ListItem<T>{
public int iconRes;
public int colorOverrideAttr;
public boolean dividerAfter;
public Runnable onClick;
private Consumer<ListItem<T>> onClick;
public boolean isEnabled=true;
public T parentObject;
public ListItem(String title, String subtitle, int iconRes, Runnable onClick, T parentObject, int colorOverrideAttr, boolean dividerAfter){
public ListItem(String title, String subtitle, int iconRes, Consumer<ListItem<T>> onClick, T parentObject, int colorOverrideAttr, boolean dividerAfter){
this.title=title;
this.subtitle=subtitle;
this.iconRes=iconRes;
@@ -32,45 +34,41 @@ public class ListItem<T>{
isEnabled=false;
}
public ListItem(String title, String subtitle, Runnable onClick){
public ListItem(String title, String subtitle, Consumer<ListItem<T>> onClick){
this(title, subtitle, 0, onClick, null, 0, false);
}
public ListItem(String title, String subtitle, Runnable onClick, T parentObject){
public ListItem(String title, String subtitle, Consumer<ListItem<T>> onClick, T parentObject){
this(title, subtitle, 0, onClick, parentObject, 0, false);
}
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick){
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick){
this(title, subtitle, iconRes, onClick, null, 0, false);
}
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick, boolean dividerAfter){
this(title, subtitle, iconRes, onClick, null, 0, dividerAfter);
}
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick, T parentObject){
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick, T parentObject){
this(title, subtitle, iconRes, onClick, parentObject, 0, false);
}
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Runnable onClick){
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Consumer<ListItem<T>> onClick){
this(null, null, 0, onClick, null, 0, false);
this.titleRes=titleRes;
this.subtitleRes=subtitleRes;
}
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Runnable onClick, int colorOverrideAttr, boolean dividerAfter){
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Consumer<ListItem<T>> onClick, int colorOverrideAttr, boolean dividerAfter){
this(null, null, 0, onClick, null, colorOverrideAttr, dividerAfter);
this.titleRes=titleRes;
this.subtitleRes=subtitleRes;
}
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Runnable onClick){
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick){
this(null, null, iconRes, onClick, null, 0, false);
this.titleRes=titleRes;
this.subtitleRes=subtitleRes;
}
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Runnable onClick, int colorOverrideAttr, boolean dividerAfter){
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick, int colorOverrideAttr, boolean dividerAfter){
this(null, null, iconRes, onClick, null, colorOverrideAttr, dividerAfter);
this.titleRes=titleRes;
this.subtitleRes=subtitleRes;
@@ -79,4 +77,13 @@ public class ListItem<T>{
public int getItemViewType(){
return colorOverrideAttr==0 ? R.id.list_item_simple : R.id.list_item_simple_tinted;
}
public void performClick(){
if(onClick!=null)
onClick.accept(this);
}
public <I extends ListItem<T>> void setOnClick(Consumer<I> onClick){
this.onClick=(Consumer<ListItem<T>>) onClick;
}
}

View File

@@ -8,7 +8,7 @@ import android.graphics.drawable.Animatable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
@@ -27,6 +27,8 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.HomeFragment;
import org.joinmastodon.android.fragments.SplashFragment;
import org.joinmastodon.android.fragments.onboarding.CustomWelcomeFragment;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.CheckableRelativeLayout;
@@ -40,7 +42,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.recyclerview.widget.LinearLayoutManager;
import me.grishka.appkit.FragmentStackActivity;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.Callback;
import me.grishka.appkit.api.ErrorResponse;
@@ -282,7 +283,7 @@ public class AccountSwitcherSheet extends BottomSheet{
@SuppressLint("SetTextI18n")
@Override
public void onBind(AccountSession item){
name.setText(item.self.displayName);
HtmlParser.setTextWithCustomEmoji(name, item.self.getDisplayName(), item.self.emojis);
username.setText(item.getFullUsername());
radioButton.setVisibility(externalShare ? View.GONE : View.VISIBLE);
extraBtnWrap.setVisibility(externalShare && openInApp ? View.VISIBLE : View.GONE);

View File

@@ -26,9 +26,7 @@ import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.views.ProgressBarButton;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
@@ -53,9 +51,9 @@ public class AccountCardStatusDisplayItem extends StatusDisplayItem{
coverRequest=new UrlImageLoaderRequest(account.header, 1000, 1000);
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), parentFragment.getAccountID());
if(account.emojis.isEmpty()){
parsedName=account.displayName;
parsedName=account.getDisplayName();
}else{
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
emojiHelper.setText(new SpannableStringBuilder(parsedName).append(parsedBio));
}
}
@@ -149,7 +147,7 @@ public class AccountCardStatusDisplayItem extends StatusDisplayItem{
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
relationship=item.parentFragment.getRelationship(item.account.id);
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), null,true, false, false, item.account);
if(item.notification.type==Notification.Type.FOLLOW_REQUEST && (relationship==null || !relationship.followedBy)){
actionWrap.setVisibility(View.GONE);

View File

@@ -96,7 +96,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
GlobalUserPreferences.playGifs ? user.avatar : user.avatarStatic,
V.dp(50), V.dp(50));
this.accountID=accountID;
parsedName=new SpannableStringBuilder(user.displayName);
parsedName=new SpannableStringBuilder(user.getDisplayName());
this.status=status;
this.notification=notification;
this.scheduledStatus=scheduledStatus;
@@ -137,7 +137,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
}
public static class Holder extends StatusDisplayItem.Holder<HeaderStatusDisplayItem> implements ImageLoaderViewHolder{
private final TextView name, time, username, extraText, pronouns;
private final TextView name, time, username, extraText;
private final View collapseBtn, timeUsernameSeparator;
private final ImageView avatar, more, visibility, deleteNotification, unreadIndicator, markAsRead, collapseBtnIcon, botIcon;
private final PopupMenu optionsMenu;
@@ -164,7 +164,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
collapseBtn=findViewById(R.id.collapse_btn);
collapseBtnIcon=findViewById(R.id.collapse_btn_icon);
extraText=findViewById(R.id.extra_text);
pronouns=findViewById(R.id.pronouns);
avatar.setOnClickListener(this::onAvaClick);
avatar.setOutlineProvider(OutlineProviders.roundedRect(12));
avatar.setClipToOutline(true);
@@ -332,7 +331,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
if(TextUtils.isEmpty(item.extraText)){
if (item.status != null) {
boolean displayPronouns=item.parentFragment instanceof ThreadFragment ? GlobalUserPreferences.displayPronounsInThreads : GlobalUserPreferences.displayPronounsInTimelines;
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), extraText, pronouns, displayPronouns, item.status.visibility==StatusPrivacy.DIRECT, item.status.localOnly || item.status.visibility==StatusPrivacy.LOCAL, item.status.account);
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), extraText, displayPronouns, item.status.visibility==StatusPrivacy.DIRECT, item.status.localOnly || item.status.visibility==StatusPrivacy.LOCAL, item.status.account);
}
}else{
extraText.setVisibility(View.VISIBLE);

View File

@@ -18,7 +18,6 @@ import android.widget.TextView;
import org.joinmastodon.android.GlobalUserPreferences;
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.AccountSessionManager;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
@@ -62,7 +61,7 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{
TextUtils.isEmpty(notification.account.avatar) ? session.getDefaultAvatarUrl() :
GlobalUserPreferences.playGifs ? notification.account.avatar : notification.account.avatarStatic,
V.dp(50), V.dp(50));
SpannableStringBuilder parsedName=new SpannableStringBuilder(notification.account.displayName);
SpannableStringBuilder parsedName=new SpannableStringBuilder(notification.account.getDisplayName());
HtmlParser.parseCustomEmoji(parsedName, notification.account.emojis);
String str = parentFragment.getString(switch(notification.type){
case FOLLOW -> R.string.user_followed_you;

View File

@@ -87,8 +87,9 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
@Override
public ImageLoaderRequest getImageRequest(int index){
CustomEmojiHelper helper=index<emojiHelper.getImageCount() ? emojiHelper : extra.emojiHelper;
return helper.getImageRequest(index%emojiHelper.getImageCount());
int firstHelperCount=emojiHelper.getImageCount();
CustomEmojiHelper helper=index<firstHelperCount ? emojiHelper : extra.emojiHelper;
return helper.getImageRequest(firstHelperCount>0 ? index%firstHelperCount : index);
}
public static class Holder extends StatusDisplayItem.Holder<ReblogOrReplyLineStatusDisplayItem> implements ImageLoaderViewHolder{
@@ -136,8 +137,9 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
@Override
public void setImage(int index, Drawable image){
CustomEmojiHelper helper=index<item.emojiHelper.getImageCount() ? item.emojiHelper : item.extra.emojiHelper;
helper.setImageDrawable(index%item.emojiHelper.getImageCount(), image);
int firstHelperCount=item.emojiHelper.getImageCount();
CustomEmojiHelper helper=index<firstHelperCount ? item.emojiHelper : item.extra.emojiHelper;
helper.setImageDrawable(firstHelperCount>0 ? index%firstHelperCount : index, image);
text.invalidate();
extraText.invalidate();
}

View File

@@ -15,7 +15,6 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountLocalPreferences;
import org.joinmastodon.android.api.session.AccountSessionManager;
@@ -30,7 +29,6 @@ import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Attachment;
import org.joinmastodon.android.model.DisplayItemsParent;
import org.joinmastodon.android.model.LegacyFilter;
import org.joinmastodon.android.model.FilterAction;
import org.joinmastodon.android.model.FilterContext;
import org.joinmastodon.android.model.FilterResult;
import org.joinmastodon.android.model.Notification;
@@ -41,7 +39,6 @@ import org.joinmastodon.android.ui.PhotoLayoutHelper;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.joinmastodon.android.ui.viewholders.AccountViewHolder;
import org.joinmastodon.android.utils.StatusFilterPredicate;
import org.parceler.Parcels;
import java.util.ArrayList;
@@ -142,11 +139,11 @@ public abstract class StatusDisplayItem{
String parentID = parent.getID();
String text = threadReply ? fragment.getString(R.string.sk_show_thread)
: account == null ? fragment.getString(R.string.sk_in_reply)
: status.reblog != null ? account.displayName
: fragment.getString(R.string.in_reply_to, account.displayName);
: status.reblog != null ? account.getDisplayName()
: fragment.getString(R.string.in_reply_to, account.getDisplayName());
String fullText = threadReply ? fragment.getString(R.string.sk_show_thread)
: account == null ? fragment.getString(R.string.sk_in_reply)
: fragment.getString(R.string.in_reply_to, account.displayName);
: fragment.getString(R.string.in_reply_to, account.getDisplayName());
return new ReblogOrReplyLineStatusDisplayItem(
parentID, fragment, text, account == null ? List.of() : account.emojis,
R.drawable.ic_fluent_arrow_reply_20sp_filled, null, null, fullText, status
@@ -176,12 +173,11 @@ public abstract class StatusDisplayItem{
if(status.reblog!=null){
boolean isOwnPost = AccountSessionManager.getInstance().isSelf(fragment.getAccountID(), status.account);
String fullText = fragment.getString(R.string.user_boosted, status.account.displayName);
String text = replyLine != null ? status.account.displayName : fullText;
String text=fragment.getString(R.string.user_boosted, status.account.getDisplayName());
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, text, status.account.emojis, R.drawable.ic_fluent_arrow_repeat_all_20sp_filled, isOwnPost ? status.visibility : null, i->{
args.putParcelable("profileAccount", Parcels.wrap(status.account));
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
}, fullText, status));
}, null, status));
} else if (!(status.tags.isEmpty() ||
fragment instanceof HashtagTimelineFragment ||
fragment instanceof ListTimelineFragment

View File

@@ -210,9 +210,10 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
Translation existingTrans=item.status.getContentStatus().translation;
String existingTransLang=existingTrans!=null ? existingTrans.detectedSourceLanguage : null;
String lang=existingTransLang!=null ? existingTransLang : item.status.getContentStatus().language;
String displayLang=Locale.forLanguageTag(lang != null ? lang
: AccountSessionManager.get(item.parentFragment.getAccountID()).preferences.postingDefaultLanguage).getDisplayLanguage();
translationButton.setText(item.parentFragment.getString(R.string.translate_post, !displayLang.isBlank() ? displayLang : lang));
Locale locale=lang!=null ? Locale.forLanguageTag(lang) : null;
translationButton.setText(locale!=null
? item.parentFragment.getString(R.string.translate_post, locale.getDisplayLanguage())
: item.parentFragment.getString(R.string.sk_translate_post));
translationButton.setClickable(true);
translationButton.animate().alpha(1).setDuration(100).start();
translationInfo.setVisibility(View.GONE);

View File

@@ -0,0 +1,88 @@
package org.joinmastodon.android.ui.utils;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.IntEvaluator;
import android.animation.ObjectAnimator;
import android.graphics.drawable.Drawable;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import org.joinmastodon.android.R;
import java.util.function.IntSupplier;
import me.grishka.appkit.FragmentStackActivity;
import me.grishka.appkit.fragments.AppKitFragment;
public class ActionModeHelper{
public static ActionMode startActionMode(AppKitFragment fragment, IntSupplier statusBarColorSupplier, ActionMode.Callback callback){
FragmentStackActivity activity=(FragmentStackActivity) fragment.getActivity();
return activity.startActionMode(new ActionMode.Callback(){
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu){
if(!callback.onCreateActionMode(mode, menu))
return false;
ObjectAnimator anim=ObjectAnimator.ofInt(activity.getWindow(), "statusBarColor", statusBarColorSupplier.getAsInt(), UiUtils.getThemeColor(activity, R.attr.colorM3Primary));
anim.setEvaluator(new IntEvaluator(){
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
}
});
anim.start();
activity.invalidateSystemBarColors(fragment);
View fakeView=new View(activity);
// mode.setCustomView(fakeView);
// int buttonID=activity.getResources().getIdentifier("action_mode_close_button", "id", "android");
// View btn=activity.getWindow().getDecorView().findViewById(buttonID);
// if(btn!=null){
// ((ViewGroup.MarginLayoutParams)btn.getLayoutParams()).setMarginEnd(0);
// }
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu){
if(!callback.onPrepareActionMode(mode, menu))
return false;
for(int i=0;i<menu.size();i++){
Drawable icon=menu.getItem(i).getIcon();
if(icon!=null){
icon=icon.mutate();
icon.setTint(UiUtils.getThemeColor(activity, R.attr.colorM3OnPrimary));
menu.getItem(i).setIcon(icon);
}
}
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item){
return callback.onActionItemClicked(mode, item);
}
@Override
public void onDestroyActionMode(ActionMode mode){
ObjectAnimator anim=ObjectAnimator.ofInt(activity.getWindow(), "statusBarColor", UiUtils.getThemeColor(activity, R.attr.colorM3Primary), statusBarColorSupplier.getAsInt());
anim.setEvaluator(new IntEvaluator(){
@Override
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
}
});
anim.addListener(new AnimatorListenerAdapter(){
@Override
public void onAnimationEnd(Animator animation){
activity.getWindow().setStatusBarColor(0);
}
});
anim.start();
activity.invalidateSystemBarColors(fragment);
callback.onDestroyActionMode(mode);
}
});
}
}

View File

@@ -480,7 +480,7 @@ public class UiUtils {
public static void confirmToggleBlockUser(Activity activity, String accountID, Account account, boolean currentlyBlocked, Consumer<Relationship> resultCallback) {
showConfirmationAlert(activity, activity.getString(currentlyBlocked ? R.string.confirm_unblock_title : R.string.confirm_block_title),
activity.getString(currentlyBlocked ? R.string.confirm_unblock : R.string.confirm_block, account.displayName),
activity.getString(currentlyBlocked ? R.string.confirm_unblock : R.string.confirm_block, account.getDisplayName()),
activity.getString(currentlyBlocked ? R.string.do_unblock : R.string.do_block),
R.drawable.ic_fluent_person_prohibited_28_regular,
() -> {
@@ -508,7 +508,7 @@ public class UiUtils {
public static void confirmSoftBlockUser(Activity activity, String accountID, Account account, Consumer<Relationship> resultCallback) {
showConfirmationAlert(activity,
activity.getString(R.string.sk_remove_follower),
activity.getString(R.string.sk_remove_follower_confirm, account.displayName),
activity.getString(R.string.sk_remove_follower_confirm, account.getDisplayName()),
activity.getString(R.string.sk_do_remove_follower),
R.drawable.ic_fluent_person_delete_24_regular,
() -> new SetAccountBlocked(account.id, true).setCallback(new Callback<>() {
@@ -566,7 +566,7 @@ public class UiUtils {
params.setMargins(0, V.dp(-12), 0, 0);
durationView.setLayoutParams(params);
Button button=durationView.findViewById(R.id.button);
((TextView) durationView.findViewById(R.id.message)).setText(context.getString(R.string.confirm_mute, account.displayName));
((TextView) durationView.findViewById(R.id.message)).setText(context.getString(R.string.confirm_mute, account.getDisplayName()));
AtomicReference<Duration> muteDuration=new AtomicReference<>(Duration.ZERO);
@@ -600,7 +600,7 @@ public class UiUtils {
new M3AlertDialogBuilder(context)
.setTitle(context.getString(currentlyMuted ? R.string.confirm_unmute_title : R.string.confirm_mute_title))
.setMessage(currentlyMuted ? context.getString(R.string.confirm_unmute, account.displayName) : null)
.setMessage(currentlyMuted ? context.getString(R.string.confirm_unmute, account.getDisplayName()) : null)
.setView(currentlyMuted ? null : durationView)
.setPositiveButton(context.getString(currentlyMuted ? R.string.do_unmute : R.string.do_mute), (dlg, i)->{
new SetAccountMuted(account.id, !currentlyMuted, muteDuration.get().getSeconds())
@@ -1110,23 +1110,21 @@ public class UiUtils {
return back;
}
public static boolean setExtraTextInfo(Context ctx, @Nullable TextView extraText, @Nullable TextView pronouns, boolean displayPronouns, boolean mentionedOnly, boolean localOnly, @Nullable Account account) {
List<String> extraParts = extraText!=null && (localOnly || mentionedOnly) ? new ArrayList<>() : null;
Optional<String> p=pronouns==null || !displayPronouns ? Optional.empty() : extractPronouns(ctx, account);
if(p.isPresent()) {
HtmlParser.setTextWithCustomEmoji(pronouns, p.get(), account.emojis);
pronouns.setVisibility(View.VISIBLE);
}else if(pronouns!=null){
pronouns.setVisibility(View.GONE);
}
public static boolean setExtraTextInfo(Context ctx, @Nullable TextView extraText, boolean displayPronouns, boolean mentionedOnly, boolean localOnly, @Nullable Account account) {
List<String> extraParts=new ArrayList<>();
Optional<String> p=!displayPronouns ? Optional.empty() : extractPronouns(ctx, account);
if(localOnly)
extraParts.add(ctx.getString(R.string.sk_inline_local_only));
if(mentionedOnly)
extraParts.add(ctx.getString(R.string.sk_inline_direct));
if(extraText!=null && extraParts!=null && !extraParts.isEmpty()) {
String sepp = ctx.getString(R.string.sk_separator);
String text = String.join(" " + sepp + " ", extraParts);
if(account == null) extraText.setText(text);
if(p.isPresent() && extraParts.isEmpty())
extraParts.add(p.get());
if(extraText!=null && !extraParts.isEmpty()) {
String sepp=ctx.getString(R.string.sk_separator);
String text=String.join(" " + sepp + " ", extraParts);
if(account==null) extraText.setText(text);
else HtmlParser.setTextWithCustomEmoji(extraText, text, account.emojis);
extraText.setVisibility(View.VISIBLE);
return true;
@@ -1702,14 +1700,17 @@ public class UiUtils {
Matcher matcher=trimPronouns.matcher(text);
if(!matcher.find()) return null;
String matched=matcher.group(1);
String pronouns=matcher.group(1);
// crude fix to allow for pronouns like "it(/she)"
int missingClosingParens=0;
for(char c : matched.toCharArray()){
for(char c : pronouns.toCharArray()){
if(c=='(') missingClosingParens++;
if(c==')') missingClosingParens--;
}
return matched+")".repeat(Math.max(0, missingClosingParens));
pronouns+=")".repeat(Math.max(0, missingClosingParens));
// if ends with an un-closed custom emoji
if(pronouns.matches("^.*\\s+:[a-zA-Z_]+$")) pronouns+=':';
return pronouns;
}
// https://stackoverflow.com/questions/9475589/how-to-get-string-from-different-locales-in-android

View File

@@ -73,6 +73,6 @@ public abstract class ListItemViewHolder<T extends ListItem<?>> extends Bindable
@Override
public void onClick(){
item.onClick.run();
item.performClick();
}
}

View File

@@ -1,33 +1,40 @@
package org.joinmastodon.android.ui.views;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import me.grishka.appkit.utils.V;
import org.joinmastodon.android.R;
/**
* A LinearLayout for TextViews. First child TextView will get truncated if it doesn't fit, remaining will always wrap content.
*/
public class HeaderSubtitleLinearLayout extends LinearLayout{
private float firstFraction;
public HeaderSubtitleLinearLayout(Context context){
super(context);
this(context, null);
}
public HeaderSubtitleLinearLayout(Context context, AttributeSet attrs){
super(context, attrs);
this(context, attrs, 0);
}
public HeaderSubtitleLinearLayout(Context context, AttributeSet attrs, int defStyleAttr){
super(context, attrs, defStyleAttr);
TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.HeaderSubtitleLinearLayout);
firstFraction=ta.getFraction(R.styleable.HeaderSubtitleLinearLayout_firstFraction, 1, 1, 0.5f);
ta.recycle();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
if(getLayoutChildCount()>1){
int remainingWidth=MeasureSpec.getSize(widthMeasureSpec);
int fullWidth=MeasureSpec.getSize(widthMeasureSpec);
int remainingWidth=fullWidth;
for(int i=1;i<getChildCount();i++){
View v=getChildAt(i);
if(v.getVisibility()==GONE)
@@ -38,8 +45,7 @@ public class HeaderSubtitleLinearLayout extends LinearLayout{
}
View first=getChildAt(0);
if(first instanceof TextView){
// guaranteeing at least 64dp of width for the display name
((TextView) first).setMaxWidth(Math.max(remainingWidth, V.dp(64)));
((TextView) first).setMaxWidth(Math.max(remainingWidth, (int)(firstFraction*fullWidth)));
}
}else{
View first=getChildAt(0);
@@ -58,4 +64,12 @@ public class HeaderSubtitleLinearLayout extends LinearLayout{
}
return count;
}
public void setFirstFraction(float firstFraction){
this.firstFraction=firstFraction;
}
public float getFirstFraction(){
return firstFraction;
}
}

View File

@@ -0,0 +1,3 @@
<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="M17.5 12c3.038 0 5.5 2.463 5.5 5.5 0 3.038-2.462 5.5-5.5 5.5-3.037 0-5.5-2.462-5.5-5.5 0-3.037 2.463-5.5 5.5-5.5zm-2.646 5.147c-0.195-0.196-0.512-0.196-0.707 0-0.196 0.195-0.196 0.512 0 0.707l2 2c0.195 0.195 0.512 0.195 0.707 0l4-4c0.195-0.195 0.195-0.512 0-0.707-0.195-0.196-0.512-0.196-0.707 0L16.5 18.793l-1.646-1.646zM12.023 14c-0.297 0.463-0.537 0.966-0.709 1.5H4.253c-0.414 0-0.75 0.335-0.75 0.75v0.577c0 0.535 0.192 1.053 0.54 1.46 1.253 1.469 3.22 2.214 5.957 2.214 0.597 0 1.157-0.035 1.68-0.106 0.246 0.495 0.553 0.954 0.912 1.367-0.795 0.16-1.66 0.24-2.592 0.24-3.146 0-5.532-0.906-7.098-2.74-0.58-0.679-0.898-1.543-0.898-2.435v-0.578C2.004 15.007 3.01 14 4.253 14h7.77zM10 2.005c2.762 0 5 2.239 5 5s-2.238 5-5 5c-2.761 0-5-2.239-5-5s2.239-5 5-5zm0 1.5c-1.933 0-3.5 1.567-3.5 3.5s1.567 3.5 3.5 3.5 3.5-1.567 3.5-3.5-1.567-3.5-3.5-3.5z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

View File

@@ -22,7 +22,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="15dp">
<!-- avatar width (46sp) / 2 - button width (24dp) / 2 -->
<FrameLayout
android:layout_weight="1"

View File

@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp">
@@ -10,7 +11,7 @@
android:id="@+id/buttons"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginTop="5dp"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true">
@@ -107,6 +108,7 @@
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
android:id="@+id/name_wrap"
app:firstFraction="60%"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="@id/avatar"
@@ -125,20 +127,6 @@
android:gravity="start|center_vertical"
tools:text="Eugen" />
<TextView
android:id="@+id/pronouns"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8sp"
android:maxWidth="161sp"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/m3_title_medium"
android:fontFamily="sans-serif"
android:textAlignment="viewStart"
android:textColor="?colorM3OnSurface"
tools:text="they/them" />
<TextView
android:id="@+id/extra_text"
android:layout_width="wrap_content"
@@ -146,8 +134,7 @@
android:layout_marginStart="8sp"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/m3_title_medium"
android:fontFamily="sans-serif"
android:textAppearance="@style/m3_body_medium"
android:textAlignment="viewStart"
android:textColor="?colorM3OnSurface"
tools:text="boosted your cat picture" />

View File

@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:firstFraction="30%"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -45,6 +47,6 @@
android:drawableTint="?colorM3OnSurface"
android:drawablePadding="6dp"
android:singleLine="true"
android:ellipsize="end"/>
android:ellipsize="middle"/>
</org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout>

View File

@@ -110,7 +110,7 @@
android:layout_marginStart="8sp"
android:ellipsize="end"
android:singleLine="true"
android:textAppearance="@style/m3_title_medium"
android:textAppearance="@style/m3_body_medium"
android:textAlignment="viewStart"
android:textColor="?colorM3OnSurface"
tools:text="@string/sk_inline_local_only" />

View File

@@ -1,13 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/menu_group1">
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:visible="false" android:icon="@drawable/ic_fluent_person_swap_24_regular">
<menu android:id="@+id/accounts" />
</item>
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
<item android:id="@+id/open_in_browser" android:title="@string/open_in_browser" android:icon="@drawable/ic_fluent_globe_24_regular"/>
</group>
<group android:id="@+id/menu_group2">
<item android:id="@+id/manage_user_lists" android:title="@string/sk_lists_with_user" android:icon="@drawable/ic_fluent_people_24_regular"/>
<item android:id="@+id/mute" android:title="@string/mute_user" android:icon="@drawable/ic_fluent_speaker_off_24_regular"/>
<item android:id="@+id/hide_boosts" android:title="@string/hide_boosts_from_user" android:icon="@drawable/ic_fluent_arrow_repeat_all_off_24_regular"/>
@@ -16,4 +9,11 @@
<item android:id="@+id/report" android:title="@string/report_user" android:icon="@drawable/ic_fluent_warning_24_regular"/>
<item android:id="@+id/block_domain" android:title="@string/block_domain" android:icon="@drawable/ic_fluent_shield_prohibited_24_regular"/>
</group>
<group android:id="@+id/menu_group2">
<item android:id="@+id/open_in_browser" android:title="@string/open_in_browser" android:icon="@drawable/ic_fluent_globe_24_regular"/>
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:visible="false" android:icon="@drawable/ic_fluent_person_swap_24_regular">
<menu android:id="@+id/accounts" />
</item>
</group>
</menu>

View File

@@ -1,14 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/followed_hashtags" android:title="@string/sk_hashtags_you_follow" android:icon="@drawable/ic_fluent_number_symbol_24_regular" android:showAsAction="always"/>
<item android:id="@+id/bookmarks" android:title="@string/bookmarks" android:icon="@drawable/ic_fluent_bookmark_multiple_24_regular" android:showAsAction="always"/>
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:icon="@drawable/ic_fluent_person_swap_24_regular">
<menu android:id="@+id/accounts" />
</item>
<item android:id="@+id/manage_user_lists" android:title="@string/sk_your_lists" android:icon="@drawable/ic_fluent_people_24_regular"/>
<item android:id="@+id/favorites" android:title="@string/your_favorites" android:icon="@drawable/ic_fluent_star_24_regular"/>
<item android:id="@+id/muted_accounts" android:title="@string/sk_muted_accounts" android:icon="@drawable/ic_fluent_speaker_off_24_regular"/>
<item android:id="@+id/blocked_accounts" android:title="@string/sk_blocked_accounts" android:icon="@drawable/ic_fluent_shield_24_regular"/>
<item android:id="@+id/scheduled" android:title="@string/sk_unsent_posts" android:icon="@drawable/ic_fluent_folder_open_24_regular"/>
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
<group android:id="@+id/menu_group1">
<item android:id="@+id/followed_hashtags" android:title="@string/sk_hashtags_you_follow" android:icon="@drawable/ic_fluent_number_symbol_24_regular" android:showAsAction="always"/>
<item android:id="@+id/bookmarks" android:title="@string/bookmarks" android:icon="@drawable/ic_fluent_bookmark_multiple_24_regular" android:showAsAction="always"/>
<item android:id="@+id/manage_user_lists" android:title="@string/sk_your_lists" android:icon="@drawable/ic_fluent_people_24_regular"/>
<item android:id="@+id/favorites" android:title="@string/your_favorites" android:icon="@drawable/ic_fluent_star_24_regular"/>
<item android:id="@+id/muted_accounts" android:title="@string/sk_muted_accounts" android:icon="@drawable/ic_fluent_speaker_off_24_regular"/>
<item android:id="@+id/blocked_accounts" android:title="@string/sk_blocked_accounts" android:icon="@drawable/ic_fluent_shield_24_regular"/>
<item android:id="@+id/scheduled" android:title="@string/sk_unsent_posts" android:icon="@drawable/ic_fluent_folder_open_24_regular"/>
</group>
<group android:id="@+id/menu_group2">
<item android:id="@+id/open_in_browser" android:title="@string/open_in_browser" android:icon="@drawable/ic_fluent_globe_24_regular"/>
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:visible="false" android:icon="@drawable/ic_fluent_person_swap_24_regular">
<menu android:id="@+id/accounts" />
</item>
</group>
</menu>

View File

@@ -314,7 +314,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">هذه هي جميع المشاركات من جميع المستخدمين في الخادم الخاص بك (%s).</string>
<string name="recommended_accounts_info_banner">قد تعجبك هذه الحسابات استنادا إلى حسابات أخرى تتابعها.</string>
<string name="see_new_posts">استعرض المنشورات الجديدة</string>
<string name="load_missing_posts">حمّل المَنشورات المَفقودَة</string>
<string name="follow_back">رُدّ المتابعة</string>
<string name="button_follow_pending">معلق</string>

View File

@@ -324,4 +324,5 @@
<string name="sk_settings_continues_playback">تراكُب صوتي</string>
<string name="sk_settings_enable_marquee">تمكين تمرير النص في عناوين الأشرطة</string>
<string name="sk_settings_tabs_disable_swipe">تعطيل التمرير بين الألسِنة</string>
<string name="sk_settings_color_palette_default">افتراضي (%s)</string>
</resources>

View File

@@ -273,7 +273,6 @@
<string name="downloading">Спампоўванне…</string>
<string name="local_timeline">Лакальнае</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Паказаць новыя допісы</string>
<string name="load_missing_posts">Загрузіць адсутныя допісы</string>
<string name="follow_back">Падпісацца ў адказ</string>
<string name="button_follow_pending">Чакаюць</string>

View File

@@ -208,7 +208,6 @@
<string name="file_saved">Fitxer desat</string>
<string name="downloading">S\'està baixant…</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Publicacions noves</string>
<string name="load_missing_posts">Carrega les publicacions faltants</string>
<string name="follow_back">Segueix</string>
<string name="button_follow_pending">Pendent</string>

View File

@@ -288,7 +288,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Toto jsou všechny příspěvky od všech uživatelů na vašem serveru (%s).</string>
<string name="recommended_accounts_info_banner">Podle toho, koho sledujete, by se vám mohly líbit tyto účty.</string>
<string name="see_new_posts">Zobrazit nové příspěvky</string>
<string name="load_missing_posts">Načíst chybějící příspěvky</string>
<string name="follow_back">Sledovat nazpět</string>
<string name="button_follow_pending">Čekající</string>

View File

@@ -262,7 +262,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Disse er alle indlæg fra alle brugere på din server (%s).</string>
<string name="recommended_accounts_info_banner">Baseret på andre, du følger, vil du måske synes om disse konti.</string>
<string name="see_new_posts">Se nye indlæg</string>
<string name="load_missing_posts">Indlæs manglende indlæg</string>
<string name="follow_back">Følg Tilbage</string>
<string name="button_follow_pending">Afventer</string>

View File

@@ -262,7 +262,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Dies sind alle Beiträge von allen Benutzern auf deinem Server (%s).</string>
<string name="recommended_accounts_info_banner">Dir könnten diese Konten gefallen, basierend auf Leuten, denen du folgst.</string>
<string name="see_new_posts">Neue Beiträge anzeigen</string>
<string name="load_missing_posts">Weitere Beiträge laden</string>
<string name="follow_back">Zurückfolgen</string>
<string name="button_follow_pending">Ausstehend</string>

View File

@@ -255,7 +255,7 @@
<string name="sk_expand">Erweitern</string>
<string name="sk_collapse">Einklappen</string>
<string name="sk_settings_collapse_long_posts">Sehr lange Beiträge einklappen</string>
<string name="sk_unfinished_attachments">Anhänge richtig stellen\?</string>
<string name="sk_unfinished_attachments">Anhänge laden hoch</string>
<string name="sk_settings_hide_interaction">Interaktions-Buttons verstecken</string>
<string name="sk_unfinished_attachments_message">Einige Anhänge sind nicht fertig hochgeladen.</string>
<string name="sk_followed_as">Mit %s gefolgt</string>
@@ -295,7 +295,7 @@
<string name="sk_settings_allow_remote_loading">Infos von Remote-Instanzen laden</string>
<string name="sk_no_remote_info_hint">keine Remote-Infos abrufbar</string>
<string name="sk_error_loading_profile">Konnte das Profil via %s nicht laden</string>
<string name="sk_settings_allow_remote_loading_explanation">Für vollständigere Auflistung von Follower*innen, Likes und Boosts können die Informationen von der Ursprungs-Instanz geladen werden.</string>
<string name="sk_settings_allow_remote_loading_explanation">Für vollständigere Auflistung von Follower_innen, Likes und Boosts können die Informationen von der Ursprungs-Instanz geladen werden.</string>
<string name="sk_settings_auto_reveal_equal_spoilers">Automatisches Aufdecken von gleichen CWs in Antworten von</string>
<string name="sk_settings_auto_reveal_nobody">Nie</string>
<string name="sk_settings_auto_reveal_author">Antworten, die von der gleichen Person verfasst wurden</string>
@@ -410,4 +410,9 @@
<string name="sk_settings_color_palette_default">Standardwert (%s)</string>
<string name="sk_settings_underlined_links">Unterstrichene Links</string>
<string name="sk_recently_used">Zuletzt verwendet</string>
<string name="sk_settings_clear_timeline_cache">Start-Timeline leeren</string>
<string name="sk_edit_alt_text">Bildbeschreibung bearbeiten</string>
<string name="sk_settings_default_visibility">Standard-Sichtbarkeit für Posts</string>
<string name="sk_settings_lock_account">Neue Follower_innen manuell genehmigen</string>
<string name="sk_timeline_cache_cleared">Start-Timeline geleert</string>
</resources>

View File

@@ -262,7 +262,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Αυτές είναι όλες οι αναρτήσεις από όλους τους χρήστες στο διακομιστή σου (%s).</string>
<string name="recommended_accounts_info_banner">Μπορεί να σου αρέσουν αυτοί οι λογαριασμοί με βάση άλλους που ακολουθείς.</string>
<string name="see_new_posts">Δες νέες αναρτήσεις</string>
<string name="load_missing_posts">Φόρτωση αναρτήσεων που λείπουν</string>
<string name="follow_back">Ακολούθησε και εσύ</string>
<string name="button_follow_pending">Εκκρεμεί</string>

View File

@@ -262,7 +262,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Estos son todos los mensajes de todos los usuarios de tu servidor (%s).</string>
<string name="recommended_accounts_info_banner">Es posible que te gusten estas cuentas basadas en otras que sigues.</string>
<string name="see_new_posts">Ver nuevas publicaciones</string>
<string name="see_new_posts">Nuevas publicaciones</string>
<string name="load_missing_posts">Cargar publicaciones faltantes</string>
<string name="follow_back">Seguir de vuelta</string>
<string name="button_follow_pending">Pendiente</string>
@@ -387,6 +387,7 @@
<string name="welcome_to_mastodon">Bienvenido/da a Mastodon</string>
<string name="welcome_paragraph1">Mastodon es una red social descentralizada, lo que significa que no la controla una sola compañía. Está formada por muchos servidores independientes, todos juntos conectados.</string>
<string name="what_are_servers">¿Qué son los servidores?</string>
<string name="welcome_paragraph2">Cada cuenta de Mastodon está alojada en un servidor — cada uno con sus propios valores, reglas y administradores. Sin importar cuál elijas, puedes seguir e interactuar con personas en cualquier servidor.</string>
<string name="opening_link">Abriendo enlace…</string>
<string name="link_not_supported">Este enlace no es compatible con la aplicación</string>
<string name="log_out_all_accounts">Cerrar sesión en todas las cuentas</string>
@@ -414,6 +415,7 @@
<string name="alt_text">Texto alternativo</string>
<string name="help">Ayuda</string>
<string name="what_is_alt_text">¿Qué es el texto alternativo?</string>
<string name="alt_text_help">El texto alternativo entrega descripciones de una imagen a las personas con discapacidad visual, conexiones de internet de bajo ancho de banda o a quienes buscan más contexto.\n\nPuedes mejorar la accesibilidad y la comprensión de todos al escribir texto alternativo que sea claro, conciso y objetivo.\n\n&lt;ul&gt;&lt;il&gt; Captura elementos importantes&lt;/li&gt;\n&lt;li&gt;Resume el texto en las imágenes&lt;/li&gt;\n&lt;li&gt;Construye las frases de manera normal&lt;/li&gt;\n&lt;li&gt;Evita la información redundante&lt;/li&gt;\n&lt;li&gt;Enfócate en tendencias y en hallazgos claves en imágenes complejas (como diagramas o mapas)&lt;/li&gt;&lt;/ul&gt;</string>
<string name="edit_post">Editar publicación</string>
<string name="no_verified_link">Enlace no verificado</string>
<string name="compose_autocomplete_emoji_empty">Explorar emojis</string>
@@ -433,6 +435,7 @@
<string name="forward_report_to_server">Reenviar a %s</string>
<!-- Shown on the "stamp" on the screen that appears after you report a post/user. Please keep the translation short, preferably a single word -->
<string name="reported">Reportado</string>
<string name="report_unfollow_explanation">Para no ver más sus publicaciones en tu feed de inicio, deja de seguirle.</string>
<string name="muted_user">Silenciado %s</string>
<string name="report_sent_already_blocked">Ya has bloqueado a este usuario, así que no tienes nada más que hacer mientras revisamos tu informe.</string>
<string name="report_personal_already_blocked">Ya has bloqueado a este usuario, así que no tienes nada más que hacer.\n\n¡Gracias por ayudar a mantener Mastodon un lugar seguro para todos!</string>
@@ -475,9 +478,13 @@
<string name="about_server">Acerca de</string>
<string name="server_rules">Reglas</string>
<string name="server_administrator">Administrador</string>
<string name="send_email_to_server_admin">Contacta a un administrador</string>
<string name="notifications_disabled_in_system">Active las notificaciones desde la configuración de su dispositivo para ver actualizaciones desde cualquier lugar.</string>
<string name="settings_even_more">Aún más ajustes</string>
<string name="settings_show_cws">Mostrar advertencias de contenido</string>
<string name="settings_hide_sensitive_media">Esconder contenidos marcados como explícitos</string>
<string name="settings_show_interaction_counts">Contador de interacciones con una publicación</string>
<string name="settings_show_emoji_in_names">Emoji personalizado en los nombres de las pantallas</string>
<plurals name="in_x_seconds">
<item quantity="one">en %d segundo</item>
<item quantity="other">en %d segundos</item>
@@ -532,6 +539,7 @@
<string name="selection_4_or_more">%1$s, %2$s, y %3$d más</string>
<string name="filter_context_home_lists">Inicio y listas</string>
<string name="filter_context_notifications">Notificaciones</string>
<string name="filter_context_public_timelines">Líneas de tiempo públicas</string>
<string name="filter_context_threads_replies">Hilos y respuestas</string>
<string name="filter_context_profiles">Profiles</string>
<string name="settings_filter_title">Título</string>
@@ -541,6 +549,7 @@
<string name="edit_muted_word">Editar palabra silenciada</string>
<string name="add">Añadir</string>
<string name="filter_word_or_phrase">Palabra o frase</string>
<string name="filter_add_word_help">Las palabras no distinguen letras mayúsculas y solo reconocen palabras completas.\n\nSi filtras la palabra \"Agua\", se ocultarán posteos que incluyan \"agua\" o \"aGua\", pero no los que contengan \"paraguas\".</string>
<string name="settings_delete_filter_word">¿Eliminar palabra “%s”?</string>
<string name="enter_selection_mode">Seleccionar</string>
<string name="select_all">Seleccionar todo</string>
@@ -574,8 +583,46 @@
<string name="time_hours_ago_short">hace %dh</string>
<string name="time_days_ago_short">hace %dd</string>
<!-- %s is the name of the post language -->
<string name="translate_post">Traducir desde %s</string>
<!-- %1$s is the language, %2$s is the name of the translation service -->
<string name="post_translated">Traducido desde %1$s usando %2$s</string>
<string name="translation_show_original">Ver original</string>
<string name="translation_failed">Error al traducir. Tal vez el administrador no ha habilitado las traducciones en este servidor o este servidor está ejecutando una versión antigua de Mastodon donde las traducciones aún no están soportadas.</string>
<string name="settings_privacy">Privacidad y alcance</string>
<string name="settings_discoverable">Mostrar perfil y publicaciones en algoritmos de descubrimiento</string>
<string name="settings_indexable">Incluir publicaciones públicas en los resultados de búsqueda</string>
<string name="error_playing_video">Error al reproducir el video</string>
<string name="timeline_following">Siguiendo</string>
<string name="lists">Listas</string>
<string name="followed_hashtags">Etiquetas seguidas</string>
<string name="no_lists">Aún no tienes ninguna lista.</string>
<string name="no_followed_hashtags">Aún no sigues ninguna etiqueta.</string>
<string name="manage_lists">Administrar listas</string>
<string name="manage_hashtags">Administrar etiquetas</string>
<!-- Screen reader description for the menu on the home timeline screen -->
<string name="dropdown_menu">Menú desplegable</string>
<string name="edit_list">Editar lista</string>
<string name="list_members">Miembros de la lista</string>
<string name="delete_list">Borrar lista</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">¿Eliminar “%s”?</string>
<string name="list_exclusive">Ocultar miembros en la lista de Seguidos</string>
<string name="list_exclusive_subtitle">Si alguien está en esta lista, ocúltalos en tu línea de tiempo para evitar ver sus publicaciones dos veces.</string>
<string name="list_name">Nombre de la lista</string>
<string name="list_show_replies_to">Mostrar respuestas a</string>
<string name="list_replies_no_one">Nadie</string>
<string name="list_replies_members">Miembros de la lista</string>
<string name="list_replies_anyone">Cualquiera que yo siga</string>
<string name="confirm_remove_list_members">¿Eliminar miembros?</string>
<string name="remove">Eliminar</string>
<string name="add_list_member">Añadir miembro</string>
<string name="search_among_people_you_follow">Buscar entre las personas a las que sigues</string>
<string name="add_user_to_list">Añadir a lista…</string>
<string name="add_user_to_list_title">Añadir a lista</string>
<!-- %s is a username -->
<string name="manage_user_lists">Administrar las listas en las que %s aparece</string>
<string name="remove_from_list">Quitar de lista</string>
<string name="confirm_remove_list_member">¿Eliminar miembro?</string>
<string name="no_followed_hashtags_title">Manténgase al día con los intereses siguiendo las etiquetas</string>
<string name="no_followed_hashtags_subtitle">Los seguidores aparecerán aquí</string>
</resources>

View File

@@ -254,7 +254,7 @@
<string name="sk_expand">Ampliar</string>
<string name="sk_collapse">Minimizar</string>
<string name="sk_settings_collapse_long_posts">Minimizar publicaciones largas</string>
<string name="sk_unfinished_attachments">¿Corregir adjuntos\?</string>
<string name="sk_unfinished_attachments">Cargando los archivos adjuntos</string>
<string name="sk_unfinished_attachments_message">Algunos adjuntos no han terminado de subirse.</string>
<string name="sk_settings_prefix_reply_cw_with_re">Añadir \"re\" a Avisos de Contenido</string>
<string name="sk_spectator_mode">Modo espectador</string>
@@ -407,4 +407,5 @@
<string name="sk_set_as_default">Establecer por defecto</string>
<string name="sk_settings_color_palette_default">Por defecto (%s)</string>
<string name="sk_settings_underlined_links">Enlaces subrayados</string>
<string name="sk_edit_alt_text">Editar el texto alternativo</string>
</resources>

View File

@@ -246,7 +246,6 @@
<string name="local_timeline">Lokala</string>
<string name="trending_posts_info_banner">Hauek dira zure Mastodon txokoan beraien lekua hartzen ari diren argitalpenak.</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Ikusi bidalketa berriak</string>
<string name="load_missing_posts">Falta diren bidalketak kargatu</string>
<string name="follow_back">Jarraitu</string>
<string name="button_follow_pending">Zain</string>

View File

@@ -262,7 +262,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">این‌ها همه فرسته‌های همه کاربران در سرور شما (%s) هستند.</string>
<string name="recommended_accounts_info_banner">ممکن است این حساب‌ها را بر اساس حساب‌های دیگری که پی می‌گیرید بپسندید.</string>
<string name="see_new_posts">فرسته‌های جدید را ببینید</string>
<string name="see_new_posts">فرسته‌های جدید</string>
<string name="load_missing_posts">بارگذاری فرسته‌های گم شده</string>
<string name="follow_back">پی‌گیری متقابل</string>
<string name="button_follow_pending">منتظر</string>
@@ -599,7 +599,37 @@
<item quantity="one">%,d فرسته امروز</item>
<item quantity="other">%,d فرسته امروز</item>
</plurals>
<string name="error_playing_video">خطا در پخش ویدئو</string>
<string name="timeline_following">پی‌گرفته</string>
<string name="lists">سیاهه‌ها</string>
<string name="followed_hashtags">برچسب‌های پی‌گرفته</string>
<string name="no_lists">شما هنوز هیچ سیاهه‌ای ندارید.</string>
<string name="no_followed_hashtags">شما هیچ برچسبی را پی نمی‌گیرید.</string>
<string name="manage_lists">مدیریت سیاهه‌ها</string>
<string name="manage_hashtags">مدیریت برچسب‌ها</string>
<!-- Screen reader description for the menu on the home timeline screen -->
<string name="dropdown_menu">منوی کشویی</string>
<string name="edit_list">ویرایش سیاهه</string>
<string name="list_members">اعضای سیاهه</string>
<string name="delete_list">حذف سیاهه</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">حذف \"%s\"؟</string>
<string name="list_exclusive">نهفتن اعضای پی‌گرفته</string>
<string name="list_name">اسم سیاهه</string>
<string name="list_show_replies_to">نمایش پاسخ‌ها به</string>
<string name="list_replies_no_one">هیچ‌کس</string>
<string name="list_replies_members">اعضای سیاهه</string>
<string name="confirm_remove_list_members">حذف اعضا؟</string>
<string name="remove">برداشتن</string>
<string name="add_list_member">افزودن عضو</string>
<string name="add_user_to_list">افزودن به سیاهه…</string>
<string name="add_user_to_list_title">افزودن به سیاهه</string>
<!-- %s is a username -->
<string name="remove_from_list">برداشتن از سیاهه</string>
<string name="confirm_remove_list_member">حذف عضو؟</string>
<string name="manage_accounts">افزودن یا جابجا شدن بین حساب‌ها</string>
<plurals name="x_posts_recently">
<item quantity="one">%,d فرسته اخیرا ارسال کرده</item>
<item quantity="other">%,d فرسته اخیرا ارسال کرده</item>
</plurals>
</resources>

View File

@@ -310,7 +310,7 @@
<string name="sk_reacted">%s واکنش نشان داد</string>
<string name="sk_external_share_title">هم‌رسانی با حساب</string>
<string name="sk_settings_prefix_reply_cw_with_re">وارد کردن پیشوند CW با “re:” هنگام پاسخ دادن</string>
<string name="sk_unfinished_attachments">رفع مشکل پیوست‌ها؟</string>
<string name="sk_unfinished_attachments">درحال بارگذاری پیوست‌ها</string>
<string name="sk_settings_allow_remote_loading">بارگیری اطلاعات از نمونه های راه دور</string>
<string name="sk_error_loading_profile">بارگیری نمایه از طریق %s شکست خورد</string>
<string name="sk_settings_reply_visibility_following">پاسخ به پی‌گیر های من</string>
@@ -363,7 +363,7 @@
<string name="sk_button_react">واکنش با ایموجی</string>
<string name="sk_again_for_system_keyboard">دوباره برای کیبورد سامانه ضربه بزنید</string>
<string name="sk_enter_emoji_toast">لطفا یک ایموجی تایپ کنید</string>
<string name="sk_enter_emoji_hint">برای واکنش با ایموجی تایپ کنید</string>
<string name="sk_enter_emoji_hint">یک ایموجی بنویسید یا جستجو کنید</string>
<plurals name="sk_users_reacted_with">
<item quantity="one">یک کاربر با %2$s واکنش نشان داد</item>
<item quantity="other">%1$,d کاربر با %2$s واکنش نشان دادند</item>
@@ -388,11 +388,19 @@
<string name="sk_search_suicide_hotlines">یک راه کمکی بیابید</string>
<string name="sk_do_not_show_again">دوباره نمایش نده</string>
<string name="sk_suicide_helplines_url">https://findahelpline.com</string>
<string name="sk_trending_posts_info_banner">اینها فرسته‌هایی هستند که در کارساز شما مورد توجه قرار می گیرند.</string>
<string name="sk_trending_posts_info_banner">این فرسته‌ها در حال حاضر در فدیورس مورد توجه قرار گرفته اند.</string>
<string name="sk_load_missing_posts_below">بارگذاری فرسته‌های قدیمی‌تر</string>
<string name="sk_search_suicide_title">اگر نیازمند کمک هستید…</string>
<string name="sk_time_minutes">%d دقیقه</string>
<string name="sk_search_suicide_message">اگر به دنبال نشانه ای برای خودکشی نیستید، همین است. لطفاً اگر نیازمند کمک هستید با شماره تلفن محلی خودکشی تماس بگیرید.</string>
<string name="sk_trending_links_info_banner">اینها اخباری است که در کارساز شما در مورد آنها صحبت می شود.</string>
<string name="sk_trending_links_info_banner">این اخبار در سراسر فدیورس درباره آنها صحبت می شود.</string>
<string name="sk_post_contains_media">فرسته حاوی رسانه‌ست</string>
<string name="sk_set_as_default">تنظیم به‌عنوان پیش‌گزیده</string>
<string name="sk_settings_like_icon">استفاده از قلب به عنوان نماد برگزیدن</string>
<string name="sk_settings_color_palette_default">پیش‌گزیده (%s)</string>
<string name="sk_blocked_accounts">حساب‌های مسدود شده</string>
<string name="sk_settings_underlined_links">پیوندهای خط دار</string>
<string name="sk_muted_accounts">حساب‌های خموش شده</string>
<string name="sk_recently_used">اخیرا مورد استفاده قرار گرفته</string>
<string name="sk_edit_alt_text">ویرایش متن جایگزین</string>
</resources>

View File

@@ -262,7 +262,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Nämä ovat viestit kaikilta palvelimesi (%s) käyttäjiltä.</string>
<string name="recommended_accounts_info_banner">Muiden seuraamiesi perusteella saattaisit pitää näistä tileistä.</string>
<string name="see_new_posts">Uusia julkaisuja</string>
<string name="load_missing_posts">Lataa puuttuvat julkaisut</string>
<string name="follow_back">Seuraa takaisin</string>
<string name="button_follow_pending">Pyydetty</string>

View File

@@ -199,7 +199,6 @@
<string name="file_saved">Nai-save ang File</string>
<string name="downloading">Nagda-download…</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Tingnan ang mga bagong post</string>
<string name="load_missing_posts">Mag-Load ng nawawalang mga post</string>
<string name="follow_back">Sundan Pabalik</string>
<string name="button_follow_pending">Nakabinbin</string>

View File

@@ -262,7 +262,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Voici tous les messages de tous les comptes de votre serveur (%s).</string>
<string name="recommended_accounts_info_banner">Vous pourriez aimer ces comptes en fonction des autres que vous suivez.</string>
<string name="see_new_posts">Voir les nouveaux messages</string>
<string name="load_missing_posts">Charger les messages manquants</string>
<string name="follow_back">Suivre en retour</string>
<string name="button_follow_pending">En attente</string>

View File

@@ -256,7 +256,7 @@
<string name="sk_settings_collapse_long_posts">Réduire les messages très longs</string>
<string name="sk_settings_prefix_reply_cw_with_re">Préfixer les CW avec \"re :\" en répondant à</string>
<string name="sk_filtered">Filtré : %s</string>
<string name="sk_unfinished_attachments">Corriger les pièces jointes \?</string>
<string name="sk_unfinished_attachments">Téléchargement de pièces jointes</string>
<string name="sk_unfinished_attachments_message">Certaines pièces jointes n\'ont pas fini de se télécharger.</string>
<string name="sk_spectator_mode">Mode spectateur</string>
<string name="sk_settings_hide_interaction">Masquer les boutons d\'interaction</string>
@@ -408,4 +408,7 @@
<string name="sk_set_as_default">Définir par défaut</string>
<string name="sk_settings_color_palette_default">Par défaut (%s)</string>
<string name="sk_settings_underlined_links">Liens soulignés</string>
<string name="sk_edit_alt_text">Modifier le texte alternatif</string>
<string name="sk_message_cache_cleared">Cache des messages vidé</string>
<string name="sk_settings_clear_timeline_cache">Effacer le cache du fil d\'accueil</string>
</resources>

View File

@@ -288,7 +288,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Seo gach post o gach cleachdaiche an fhrithealaiche agad (%s).</string>
<string name="recommended_accounts_info_banner">Dhfhaoidte gun còrd na cunntasan seo riut stèidhichte air feadhainn eile a tha thu a leantainn.</string>
<string name="see_new_posts">Seall na postaichean ùra</string>
<string name="load_missing_posts">Luchdaich postaichean a dhìth</string>
<string name="follow_back">Lean air ais</string>
<string name="button_follow_pending">Ri dhèiligeadh</string>

View File

@@ -262,7 +262,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Estas son as publicacións das usuarias do teu servidor (%s).</string>
<string name="recommended_accounts_info_banner">Poderían interesarche estas contas en función doutras que segues.</string>
<string name="see_new_posts">Ver novas publicacións</string>
<string name="see_new_posts">Novas publicacións</string>
<string name="load_missing_posts">Cargar publicacións que faltan</string>
<string name="follow_back">Seguir tamén</string>
<string name="button_follow_pending">Pendente</string>
@@ -599,7 +599,45 @@
<item quantity="one">%,d publicación hoxe</item>
<item quantity="other">%,d publicacións hoxe</item>
</plurals>
<string name="error_playing_video">Erro ao reproducir o vídeo</string>
<string name="timeline_following">A Seguir</string>
<string name="lists">Listas</string>
<string name="followed_hashtags">Cancelos seguidos</string>
<string name="no_lists">Aínda non tes ningunha lista.</string>
<string name="no_followed_hashtags">Non segues ningún cancelo.</string>
<string name="manage_lists">Xestionar listas</string>
<string name="manage_hashtags">Xestionar cancelos</string>
<!-- Screen reader description for the menu on the home timeline screen -->
<string name="dropdown_menu">Menú despregable</string>
<string name="edit_list">Editar lista</string>
<string name="list_members">Membros da lista</string>
<string name="delete_list">Eliminar lista</string>
<!-- %s is the name of the list -->
<string name="delete_list_confirm">Eliminar \"%s\"?</string>
<string name="list_exclusive">Agochar aos membros no Inicio</string>
<string name="list_exclusive_subtitle">Se alguén está nesta lista, oculta as súas publicacións na Cronoloxía de inicio para non velas dúas veces.</string>
<string name="list_name">Nome da lista</string>
<string name="list_show_replies_to">Mostrar respostas a</string>
<string name="list_replies_no_one">Ninguén</string>
<string name="list_replies_members">Usuarias na lista</string>
<string name="list_replies_anyone">Alguén a quen sigo</string>
<string name="confirm_remove_list_members">Eliminar membros?</string>
<string name="remove">Eliminar</string>
<string name="add_list_member">Engadir usuaria</string>
<string name="search_among_people_you_follow">Procurar entre as persoas que segues</string>
<string name="add_user_to_list">Engadir á lista…</string>
<string name="add_user_to_list_title">Engadir á lista</string>
<!-- %s is a username -->
<string name="manage_user_lists">Xestionar as listas nas que aparece %s</string>
<string name="remove_from_list">Eliminar da lista</string>
<string name="confirm_remove_list_member">Eliminar membro?</string>
<string name="no_followed_hashtags_title">Infórmate dos teus intereses seguindo cancelos</string>
<string name="no_followed_hashtags_subtitle">Aquí verás os seguimentos</string>
<string name="no_lists_title">Organiza a cronoloxía de inicio con Listas</string>
<string name="no_lists_subtitle">Aquí verás as túas</string>
<string name="manage_accounts">Engade ou cambia de conta</string>
<plurals name="x_posts_recently">
<item quantity="one">%,d publicación recente</item>
<item quantity="other">%,d publicacións recentes</item>
</plurals>
</resources>

View File

@@ -258,7 +258,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Itt található az összes bejegyzés az összes felhasznólótól a példányodon (%s).</string>
<string name="recommended_accounts_info_banner">Ezek a fiókok tetszhetnek neked azok alapján, akiket követsz.</string>
<string name="see_new_posts">Új bejegyzések megtekintése</string>
<string name="load_missing_posts">Hiányzó bejegyzések betöltése</string>
<string name="follow_back">Visszakövetés</string>
<string name="button_follow_pending">Függőben</string>

View File

@@ -209,7 +209,6 @@
<string name="trending_posts_info_banner">Այս գրառումները տարածված են Մաստոդոնում։</string>
<string name="trending_links_info_banner">Այս նորությունների մասին խոսում են Մաստոդոնում։</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Նոր գրառումներ</string>
<string name="load_missing_posts">Բեռնել բաց թողնված գրառումները</string>
<string name="follows_you">Հետեւում է ձեզ</string>
<!-- translators: %,d is a valid placeholder, it formats the number with locale-dependent grouping separators -->

View File

@@ -249,7 +249,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Ini adalah kiriman dari semua pengguna di server Anda (%s).</string>
<string name="recommended_accounts_info_banner">Anda mungkin suka akun berikut berdasarkan orang-orang yang Anda ikuti.</string>
<string name="see_new_posts">Lihat kiriman baru</string>
<string name="load_missing_posts">Muat kiriman yang hilang</string>
<string name="follow_back">Ikuti Balik</string>
<string name="button_follow_pending">Ditunda</string>

View File

@@ -260,7 +260,7 @@
<string name="sk_followed_as">Diikuti dari %s</string>
<string name="sk_settings_prefix_reply_cw_with_re">Awali peringatan konten dengan “re:” saat membalas</string>
<string name="sk_settings_collapse_long_posts">Tutup kiriman yang sangat panjang</string>
<string name="sk_unfinished_attachments">Perbaiki lampiran\?</string>
<string name="sk_unfinished_attachments">Mengunggah lampiran</string>
<string name="sk_unfinished_attachments_message">Beberapa lampiran belum selesai diunggah.</string>
<string name="sk_settings_hide_fab">Sembunyikan tombol Komposer</string>
<string name="sk_in_reply">Dalam balasan</string>
@@ -401,4 +401,5 @@
<string name="sk_set_as_default">Tetapkan sebagai bawaan</string>
<string name="sk_settings_color_palette_default">Bawaan (%s)</string>
<string name="sk_settings_underlined_links">Tautan yang digarisbawahi</string>
<string name="sk_edit_alt_text">Sunting teks alternatif</string>
</resources>

View File

@@ -262,7 +262,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Þetta eru allar færslur frá öllum notendum á netþjóninum þínum (%s).</string>
<string name="recommended_accounts_info_banner">Þú gætir einnig haft áhuga á þessum aðgöngum, miðað við hverjum þú ert að fylgjast með.</string>
<string name="see_new_posts">Skoða nýjar færslur</string>
<string name="see_new_posts">Nýjar færslur</string>
<string name="load_missing_posts">Hlaða inn færslum sem vantar</string>
<string name="follow_back">Fylgjast með til baka</string>
<string name="button_follow_pending">Í bið</string>
@@ -631,6 +631,10 @@
<string name="manage_user_lists">Sýsla með lista sem %s birtist á</string>
<string name="remove_from_list">Fjarlægja af lista</string>
<string name="confirm_remove_list_member">Fjarlægja meðlim?</string>
<string name="no_followed_hashtags_title">Haltu í við áhugasviðin þín með því að fylgjast með myllumerkjum</string>
<string name="no_followed_hashtags_subtitle">Þeir sem fylgst er með birtast hér</string>
<string name="no_lists_title">Skipulegðu heimastreymið þitt með listum</string>
<string name="no_lists_subtitle">Þú munt birtast hér</string>
<plurals name="x_posts_recently">
<item quantity="one">%,d nýleg færsla</item>
<item quantity="other">%,d nýlegar færslur</item>

View File

@@ -262,7 +262,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Questi sono tutti i post di tutti gli utenti nel tuo server (%s).</string>
<string name="recommended_accounts_info_banner">Questi account potrebbero piacerti in base agli altri che segui.</string>
<string name="see_new_posts">Visualizza nuovi post</string>
<string name="load_missing_posts">Carica i post mancanti</string>
<string name="follow_back">Segui anche tu</string>
<string name="button_follow_pending">In attesa</string>

View File

@@ -249,7 +249,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">あなたのサーバー (%s) の全ユーザーの全投稿です。</string>
<string name="recommended_accounts_info_banner">こちらは、あなたがフォローしている人に基づいた、おすすめのアカウントです。</string>
<string name="see_new_posts">新しい投稿を見る</string>
<string name="load_missing_posts">不足している投稿を読み込む</string>
<string name="follow_back">フォローバック</string>
<string name="button_follow_pending">保留</string>

View File

@@ -203,7 +203,6 @@
<string name="file_saved">Afaylu yettwasekles</string>
<string name="downloading">Asader…</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Ẓer tissufaɣ timaynutin</string>
<string name="load_missing_posts">Sali tisuffaɣ i iruḥen</string>
<string name="follow_back">Ḍfeṛ</string>
<string name="button_follow_pending">Yettraǧu</string>

View File

@@ -199,7 +199,6 @@
<string name="file_saved">파일 저장됨</string>
<string name="downloading">다운로드 중…</string>
<!-- %s is the server domain -->
<string name="see_new_posts">새 게시물 보기</string>
<string name="load_missing_posts">놓친 게시물 불러오기</string>
<string name="follow_back">맞팔로우</string>
<string name="button_follow_pending">대기 중</string>

View File

@@ -262,7 +262,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Dit zijn alle berichten van alle gebruikers op uw server (%s).</string>
<string name="recommended_accounts_info_banner">Mogelijk vind je deze accounts leuk op basis van andere accounts die je volgt.</string>
<string name="see_new_posts">Nieuwe berichten</string>
<string name="load_missing_posts">Resterende berichten laden</string>
<string name="follow_back">Terugvolgen</string>
<string name="button_follow_pending">In afwachting</string>

View File

@@ -262,7 +262,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Dette er alle innlegg fra alle brukere på din server (%s).</string>
<string name="recommended_accounts_info_banner">Du liker kanskje disse kontoene basert på de andre du følger.</string>
<string name="see_new_posts">Se nye innlegg</string>
<string name="load_missing_posts">Last inn manglende innlegg</string>
<string name="follow_back">Følg tilbake</string>
<string name="button_follow_pending">Ventende</string>

View File

@@ -288,7 +288,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">To są wszystkie posty od wszystkich użytkowników na Twoim serwerze (%s).</string>
<string name="recommended_accounts_info_banner">Może spodobają się Tobie te konta, bazując na tych, których już obserwujesz?</string>
<string name="see_new_posts">Zobacz nowe wpisy</string>
<string name="load_missing_posts">Załaduj brakujące wpisy</string>
<string name="follow_back">Obserwuj wzajemnie</string>
<string name="button_follow_pending">Oczekujące</string>

View File

@@ -259,7 +259,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Estas são as publicações de todos os usuários em seu servidor (%s).</string>
<string name="recommended_accounts_info_banner">Você pode gostar dessas contas com base em outras que segue.</string>
<string name="see_new_posts">Ver novas publicações</string>
<string name="load_missing_posts">Carregar publicações perdidas</string>
<string name="follow_back">Seguir de volta</string>
<string name="button_follow_pending">Pendente</string>

View File

@@ -180,7 +180,6 @@
<string name="file_saved">Ficheiro guardado</string>
<string name="downloading">A transferir…</string>
<!-- %s is the server domain -->
<string name="see_new_posts">Ver novas publicações</string>
<string name="load_missing_posts">Carregar publicações em falta</string>
<string name="follow_back">Seguir de volta</string>
<string name="button_follow_pending">Pendente</string>

View File

@@ -125,7 +125,7 @@
<string name="sk_reported">raportat</string>
<string name="sk_sign_ups">Utilizatori înregistrați</string>
<string name="sk_new_reports">Rapoarte noi</string>
<string name="sk_unfinished_attachments">Reparați atașamentele\?</string>
<string name="sk_unfinished_attachments">Încărcare atașamente</string>
<string name="sk_unfinished_attachments_message">Unele atașamente nu au terminat încărcarea.</string>
<string name="sk_content_type">Tipul de conținut</string>
<string name="sk_content_type_unspecified">Nespecificat</string>
@@ -404,4 +404,5 @@
<string name="sk_set_as_default">Setați ca implicit</string>
<string name="sk_settings_color_palette_default">Implicit (%s)</string>
<string name="sk_settings_underlined_links">Link-uri subliniate</string>
<string name="sk_edit_alt_text">Editați text alternativ</string>
</resources>

View File

@@ -288,7 +288,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Это все посты от всех пользователей на вашем сервере (%s).</string>
<string name="recommended_accounts_info_banner">Вам могут понравиться эти учетные записи, основаные на ваших подписках.</string>
<string name="see_new_posts">Показать новые</string>
<string name="load_missing_posts">Загрузить недостающие посты</string>
<string name="follow_back">Подписаться в ответ</string>
<string name="button_follow_pending">В ожидании</string>

View File

@@ -15,7 +15,7 @@
<string name="sk_visibility_unlisted">Скрытый</string>
<string name="sk_mark_media_as_sensitive">Отметить медиафайл как деликатный</string>
<string name="sk_settings_app_version">Megalodon v%1$s (%2$d)</string>
<string name="sk_notification_type_status">Публикации</string>
<string name="sk_notification_type_status">Посты</string>
<string name="sk_notification_type_posts">Уведомдения о</string>
<string name="sk_settings_color_palette">Цветовая схема</string>
<string name="sk_color_palette_pink">Розовый</string>
@@ -38,7 +38,7 @@
<string name="sk_lists_with_user">Списки с %s</string>
<string name="sk_confirm_unpin_post">Вы уверены, что хотите открепить этот пост\?</string>
<string name="sk_unpinning">Открепляем пост…</string>
<string name="sk_federated_timeline_info_banner">Это самые последние публикации людей из вашей федерации.</string>
<string name="sk_federated_timeline_info_banner">Это самые последние посты людей из вашей федерации.</string>
<string name="sk_no_update_available">Обновление отсутствует</string>
<string name="sk_list_timelines">Списки</string>
<string name="sk_accept_follow_request">Принять запрос на подписку</string>
@@ -54,16 +54,16 @@
<string name="sk_confirm_clear_recent_languages">Вы точно хотите очистить недавно использованные языки\?</string>
<string name="sk_welcome_text">Акула приветствует вас! Чтобы начать, пожалуйста, введите домен своего домашнего сервера (инстанса) ниже.</string>
<string name="sk_poll_allow_multiple">Разрешить несколько вариантов ответа</string>
<string name="sk_user_post_notifications_on">Уведомления о постах %s включены</string>
<string name="sk_user_post_notifications_off">Уведомления о новых постах %s отключены</string>
<string name="sk_user_post_notifications_on">Включены уведомления о постах для %s</string>
<string name="sk_user_post_notifications_off">Выключены уведомления о постах для %s</string>
<string name="sk_color_palette_material3">Система</string>
<string name="sk_settings_show_boosts">Показать репосты</string>
<string name="sk_settings_show_boosts">Показывать продвижения</string>
<string name="sk_settings_show_interaction_counts">Показывать количество взаимодействий</string>
<string name="sk_settings_enable_marquee">Отключить прокручиваемый текст в заголовках</string>
<string name="sk_color_palette_red">Красный</string>
<string name="sk_settings_tabs_disable_swipe">Отключить жесты переключения между вкладками</string>
<string name="sk_settings_profile">Настроить профиль</string>
<string name="sk_settings_posting">Настройки публикации</string>
<string name="sk_settings_posting">Настройки отправки</string>
<string name="sk_settings_filters">Настройки фильтров</string>
<string name="sk_settings_auth">Настройки безопасности</string>
<string name="sk_settings_rules">Правила инстанса</string>
@@ -83,14 +83,14 @@
<string name="sk_clear_all_notifications_confirm">Вы точно хотите удалить все уведомления\?</string>
<string name="sk_undo_reblog">Отменить продвижение</string>
<string name="sk_reblog_with_visibility">Продвижение с видимостью</string>
<string name="sk_quote_post">Создать публикацию об этом</string>
<string name="sk_copy_link_to_post">Скопировать ссылку на публикацию</string>
<string name="sk_quote_post">Создать пост об этом</string>
<string name="sk_copy_link_to_post">Скопировать ссылку на пост</string>
<string name="sk_open_with_account">Открыть с другого аккаунта</string>
<string name="sk_resource_not_found">Ресурс не был найден</string>
<string name="sk_already_bookmarked">Уже в закладках</string>
<string name="sk_favorite_as">Добавить в избранное с другого аккаунта</string>
<string name="sk_already_favorited">Уже в избранном</string>
<string name="sk_reblog_as">Продвигать на другом аккаунте</string>
<string name="sk_reblog_as">Продвинуть на другом аккаунте</string>
<string name="sk_reblogged_as">Продвинуть на %s</string>
<string name="sk_reply_as">Ответить с другого аккаунта</string>
<string name="sk_settings_uniform_icon_for_notifications">Единая иконка для всех уведомлений</string>
@@ -101,25 +101,25 @@
<string name="sk_already_reblogged">Уже продвинуто</string>
<string name="sk_hashtags_you_follow">Хештеги, на которые вы подписаны</string>
<string name="sk_loading_resource_on_instance_title">Просматриваем на %s</string>
<string name="sk_unsent_posts">Неотправленные сообщения</string>
<string name="sk_unsent_posts">Неотправленные посты</string>
<string name="sk_draft">Черновик</string>
<string name="sk_schedule">Назначить</string>
<string name="sk_confirm_delete_draft">Вы точно хотите удалить публикацию из черновика\?</string>
<string name="sk_confirm_delete_scheduled_post">Вы точно хотите удалить запланированную публикацию\?</string>
<string name="sk_schedule">Запланировать</string>
<string name="sk_confirm_delete_draft">Вы точно хотите удалить пост из черновика\?</string>
<string name="sk_confirm_delete_scheduled_post">Вы точно хотите удалить запланированный пост\?</string>
<string name="sk_draft_or_schedule">В черновики или запланировать</string>
<string name="sk_compose_scheduled">Запланировано на</string>
<string name="sk_draft_saved">Черновик сохранён</string>
<string name="sk_post_scheduled">Публикация запланирована</string>
<string name="sk_post_scheduled">Пост запланирован</string>
<string name="sk_scheduled_too_soon_title">Запланированное время слишком ранее</string>
<string name="sk_confirm_save_draft">Сохранить черновик\?</string>
<string name="sk_confirm_save_changes">Сохранить изменения\?</string>
<string name="sk_mark_as_draft">Пометить как черновик</string>
<string name="sk_schedule_post">Запланировать публикацию</string>
<string name="sk_forward_report_to">Переслать пользователю %s</string>
<string name="sk_schedule_post">Запланировать пост</string>
<string name="sk_forward_report_to">Переслать к %s</string>
<string name="sk_confirm_delete_draft_title">Удалить черновик</string>
<string name="sk_confirm_delete_scheduled_post_title">Удалить запланированную публикацию</string>
<string name="sk_compose_draft">Публикация будет сохранена в черновики.</string>
<string name="sk_scheduled_too_soon">Публикация должна быть запланирована как минимум на 10 минут в будущем.</string>
<string name="sk_confirm_delete_scheduled_post_title">Удалить запланированный пост</string>
<string name="sk_compose_draft">Пост будет сохранен в черновики.</string>
<string name="sk_scheduled_too_soon">Пост должн быть запланирован как минимум на 10 минут в будущем.</string>
<string name="sk_timeline_home">Главная</string>
<string name="sk_timeline_local">Локальная</string>
<string name="sk_timeline_federated">Федерация</string>
@@ -134,9 +134,9 @@
<string name="sk_create_list_title">Создать список</string>
<string name="sk_list_name_hint">Название списка</string>
<string name="sk_list_replies_policy">Показать ответы для</string>
<string name="sk_list_replies_policy_list">Участников списка</string>
<string name="sk_list_replies_policy_followed">Отслеживаемых пользователей</string>
<string name="sk_list_replies_policy_none">Некого</string>
<string name="sk_list_replies_policy_list">участников списка</string>
<string name="sk_list_replies_policy_followed">отслеживаемых пользователей</string>
<string name="sk_list_replies_policy_none">никого</string>
<string name="sk_delete_list">Удалить список</string>
<string name="sk_edit_list_title">Изменить список</string>
<string name="sk_your_lists">Ваши списки</string>
@@ -237,7 +237,7 @@
<string name="sk_separator">·</string>
<string name="sk_local_only">Только локальный инстанс</string>
<string name="sk_instance_features">Функции инстанса</string>
<string name="sk_settings_support_local_only">Сервер поддерживает только локальные публикации</string>
<string name="sk_settings_support_local_only">Сервер поддерживает только локальные посты</string>
<string name="sk_settings_glitch_instance">Локальный режим Glitch</string>
<string name="sk_settings_glitch_mode_explanation">Включите это если ваш инстанс работает на Glitch. Не требуется для Hometown или Akkoma.</string>
<string name="sk_signed_up">зарегистирован</string>
@@ -249,13 +249,13 @@
<string name="sk_settings_see_new_posts_button">Кнопка «Показать новые записи»</string>
<string name="sk_settings_server_version">Версия сервера: %s</string>
<string name="sk_notify_poll_results">Итоги голосования</string>
<string name="sk_settings_local_only_explanation">Для работы этой функции ваш инстанс должен поддерживать локальные публикации. Большинство модифицированных версий Mastodon это поддерживают, но сам Mastodon нет.</string>
<string name="sk_settings_local_only_explanation">Для работы этой функции ваш инстанс должен поддерживать локальные посты. Большинство модифицированных версий Mastodon это поддерживают, но сам Mastodon нет.</string>
<string name="sk_settings_prefix_reply_cw_with_re">Префикс CW с \"re:\" при ответе</string>
<string name="sk_filtered">Отфильтровано: %s</string>
<string name="sk_expand">Развернуть</string>
<string name="sk_collapse">Свернуть</string>
<string name="sk_settings_collapse_long_posts">Сворачивать очень длинные посты</string>
<string name="sk_unfinished_attachments">Исправить вложения\?</string>
<string name="sk_unfinished_attachments">Выгрузка вложений</string>
<string name="sk_unfinished_attachments_message">Некоторые вложения еще не загрузились.</string>
<string name="sk_quoting_user">Цитирование %s</string>
<string name="sk_settings_reply_visibility">Видимость ответа</string>
@@ -321,7 +321,7 @@
<string name="sk_switch_timeline">Переключить ленту</string>
<string name="sk_content_type">Тип содержимого</string>
<string name="sk_content_type_unspecified">Не указано</string>
<string name="sk_bubble_timeline_info_banner">Это недавние посты из сети, управляемой администраторами этого сервера.</string>
<string name="sk_bubble_timeline_info_banner">Это самые последние посты из сети, курируемые администраторами вашего экземпляра.</string>
<string name="sk_search_fediverse">Искать в Федивёрсе</string>
<string name="sk_settings_unifiedpush">Использовать UnifiedPush</string>
<string name="sk_settings_unifiedpush_choose">Выберите распределитель</string>
@@ -332,7 +332,7 @@
<string name="sk_settings_unifiedpush_no_distributor">Распределители не найдены</string>
<string name="sk_settings_content_types_explanation">Позволяет устанавливать тип содержимого вроде Markdown при создании поста. Имейте в виду, что это поддерживается не на всех серверах.</string>
<string name="sk_settings_allow_remote_loading_explanation">Пробовать получить более точные данные о подписчиках, избранных и продвижениях, загрузив информацию из экземпляра происхождения.</string>
<string name="sk_settings_default_content_type_explanation">Это позволяет предварительно выбирать тип содержимого при создании новых публикаций, переопределяя значение, установленное в “Параметры публикации”.</string>
<string name="sk_settings_default_content_type_explanation">Это позволяет предварительно выбирать тип содержимого при создании новых постов, переопределяя значение, установленное в “Настройки отправки”.</string>
<string name="sk_trending_posts_info_banner">Эти посты сейчас набирают обороты в Fediverse.</string>
<string name="sk_settings_continues_playback_summary">Позволять продолжить воспроизведение уже проигрываемого медиа, накладывая его на новое воспроизведение</string>
<string name="sk_settings_continues_playback">Наложение аудио</string>
@@ -418,4 +418,8 @@
<string name="sk_list_exclusive_switch">Сделать список исключительным</string>
<string name="sk_recently_used">Недавно использованные</string>
<string name="sk_exclusive_list">Исключительный список</string>
<string name="sk_set_as_default">Сделать по умолчанию</string>
<string name="sk_settings_color_palette_default">По умолчанию (%s)</string>
<string name="sk_settings_underlined_links">Подчеркнутые ссылки</string>
<string name="sk_edit_alt_text">Изменить альтернативный текст</string>
</resources>

View File

@@ -276,7 +276,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">To so vse objave vseh uporabnikov na vašem strežniku (%s).</string>
<string name="recommended_accounts_info_banner">Glede na to, komu sledite, vam bodo ti računi všeč.</string>
<string name="see_new_posts">Pokaži nove objave</string>
<string name="load_missing_posts">Naloži manjkajoče objave</string>
<string name="follow_back">Sledijo nazaj</string>
<string name="button_follow_pending">Na čakanju</string>

View File

@@ -258,7 +258,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Detta är alla inlägg från alla användare på din server (%s).</string>
<string name="recommended_accounts_info_banner">Du kanske gillar dessa konton baserat på andra konton du följer.</string>
<string name="see_new_posts">Se nya inlägg</string>
<string name="load_missing_posts">Ladda saknade inlägg</string>
<string name="follow_back">Följ tillbaka</string>
<string name="button_follow_pending">Väntande</string>

View File

@@ -249,7 +249,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">นี่คือโพสต์ทั้งหมดจากผู้ใช้ทั้งหมดในเซิร์ฟเวอร์ของคุณ (%s)</string>
<string name="recommended_accounts_info_banner">คุณอาจชอบบัญชีเหล่านี้โดยอิงตามผู้อื่นที่คุณติดตาม</string>
<string name="see_new_posts">ดูโพสต์ใหม่</string>
<string name="see_new_posts">โพสต์ใหม่</string>
<string name="load_missing_posts">โหลดโพสต์ที่ขาดหายไป</string>
<string name="follow_back">ติดตามกลับ</string>
<string name="button_follow_pending">รอดำเนินการ</string>
@@ -600,6 +600,11 @@
<string name="manage_user_lists">จัดการรายการที่ %s ปรากฏอยู่ใน</string>
<string name="remove_from_list">เอาออกจากรายการ</string>
<string name="confirm_remove_list_member">เอาสมาชิกออก?</string>
<string name="no_followed_hashtags_title">ตามให้ทันความสนใจโดยการติดตามแฮชแท็ก</string>
<string name="no_followed_hashtags_subtitle">การติดตามจะปรากฏที่นี่</string>
<string name="no_lists_title">จัดระเบียบฟีดหน้าแรกของคุณด้วยรายการ</string>
<string name="no_lists_subtitle">ของคุณจะปรากฏที่นี่</string>
<string name="manage_accounts">เพิ่มหรือสลับบัญชี</string>
<plurals name="x_posts_recently">
<item quantity="other">%,d โพสต์ล่าสุด</item>
</plurals>

View File

@@ -262,7 +262,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Bunlar, sunucunuzdaki (%s) tüm kullanıcıların gönderileridir.</string>
<string name="recommended_accounts_info_banner">Takip ettiğiniz hesaplara göre bu hesapları beğenebilirsiniz.</string>
<string name="see_new_posts">Yeni gönderileri gör</string>
<string name="load_missing_posts">Daha fazlası</string>
<string name="follow_back">Geri takip et</string>
<string name="button_follow_pending">Bekliyor</string>

View File

@@ -288,7 +288,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Всі ці дописи створені користувачами вашого серверу (%s).</string>
<string name="recommended_accounts_info_banner">Вам можуть сподобатися ці профілі, озираючись на ваші підписки.</string>
<string name="see_new_posts">Переглянути нові дописи</string>
<string name="load_missing_posts">Завантажити пропущені дописи</string>
<string name="follow_back">Підписатися взаємно</string>
<string name="button_follow_pending">Очікується</string>

View File

@@ -134,7 +134,7 @@
<string name="sk_list_replies_policy_none">ніхто</string>
<string name="sk_delete_list">Видалити список</string>
<string name="sk_delete_list_confirm">Ви впевнені, що хочете видалити список «%s»\?</string>
<string name="sk_edit_list_title">Редагувати список</string>
<string name="sk_edit_list_title">Змінити список</string>
<string name="sk_your_lists">Ваші списки</string>
<string name="sk_announcements">Оголошення</string>
<string name="sk_settings_single_notification">Показувати лише одне сповіщення</string>
@@ -169,8 +169,8 @@
<string name="sk_unpin_timeline">Відкріпити стрічку</string>
<string name="sk_pinned_timeline">Прикріплено на головну</string>
<string name="sk_unpinned_timeline">Відкріплено з головної</string>
<string name="sk_edit_timeline">Редагувати стрічку</string>
<string name="sk_edit_timelines">Редагувати стрічки</string>
<string name="sk_edit_timeline">Змінити стрічку</string>
<string name="sk_edit_timelines">Змінити стрічки</string>
<string name="sk_notification_type_update">Змінені дописи</string>
<string name="sk_notify_update">Зміни й поширені дописи</string>
<string name="sk_icon_city">Місто</string>
@@ -253,10 +253,10 @@
<string name="sk_filtered">Відфільтровано: %s</string>
<string name="sk_expand">Розгорнути</string>
<string name="sk_collapse">Згорнути</string>
<string name="sk_unfinished_attachments">Виправити вкладення\?</string>
<string name="sk_unfinished_attachments">Вивантаження вкладень</string>
<string name="sk_settings_prefix_reply_cw_with_re">Префікс CW з «re:» під час відповіді</string>
<string name="sk_settings_collapse_long_posts">Згортати надто довгі дописи</string>
<string name="sk_unfinished_attachments_message">Деякі вкладення не повністю завантажилися.</string>
<string name="sk_unfinished_attachments_message">Деякі вкладення вивантажилися не повністю.</string>
<string name="sk_spectator_mode">Режим глядача</string>
<string name="sk_settings_hide_interaction">Сховати кнопки взаємодії</string>
<string name="sk_follow_as">Підписатися з іншого облікового запису</string>
@@ -409,4 +409,7 @@
<string name="sk_settings_underlined_links">Підкреслені посилання</string>
<string name="sk_set_as_default">Установити типово</string>
<string name="sk_settings_color_palette_default">Усталена (%s)</string>
<string name="sk_edit_alt_text">Змінити альтернативний текст</string>
<string name="sk_message_cache_cleared">Кеш повідомлень очищено</string>
<string name="sk_settings_clear_timeline_cache">Очистити кеш домашньої стрічки</string>
</resources>

View File

@@ -249,7 +249,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">Đây là những tút từ người trên máy chủ của bạn (%s)</string>
<string name="recommended_accounts_info_banner">Có thể bạn quen những người này chăng?!</string>
<string name="see_new_posts">Đọc những tút mới</string>
<string name="load_missing_posts">Tải tút chưa đọc</string>
<string name="follow_back">Theo dõi lại</string>
<string name="button_follow_pending">Đang chờ</string>

View File

@@ -249,7 +249,6 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">以下是来自你所在实例(%s的所有嘟文。</string>
<string name="recommended_accounts_info_banner">根据你所关注的,你或许也会喜欢这些用户。</string>
<string name="see_new_posts">查看新嘟文</string>
<string name="load_missing_posts">加载嘟文</string>
<string name="follow_back">关注</string>
<string name="button_follow_pending">已发送关注请求</string>

View File

@@ -253,7 +253,7 @@
<string name="sk_notify_poll_results">投票结果</string>
<string name="sk_expand">展开</string>
<string name="sk_collapse">折叠</string>
<string name="sk_unfinished_attachments">修复附件</string>
<string name="sk_unfinished_attachments">正在上传附件</string>
<string name="sk_unfinished_attachments_message">部分附件尚未上传完毕。</string>
<string name="sk_filtered">已过滤:%s</string>
<string name="sk_settings_collapse_long_posts">折叠很长的嘟文</string>
@@ -400,4 +400,5 @@
<string name="sk_set_as_default">设为默认</string>
<string name="sk_settings_color_palette_default">默认(%s</string>
<string name="sk_settings_underlined_links">链接加下划线</string>
<string name="sk_edit_alt_text">编辑 ALT 文本</string>
</resources>

View File

@@ -249,7 +249,7 @@
<!-- %s is the server domain -->
<string name="local_timeline_info_banner">這些是來自您伺服器 (%s) 所有使用者之嘟文。</string>
<string name="recommended_accounts_info_banner">基於您所跟隨的其他人,您可能會喜歡這些帳號。</string>
<string name="see_new_posts">檢視最新嘟文</string>
<string name="see_new_posts">新嘟文</string>
<string name="load_missing_posts">讀取錯過的嘟文</string>
<string name="follow_back">跟隨回去</string>
<string name="button_follow_pending">等待中</string>
@@ -600,6 +600,11 @@
<string name="manage_user_lists">管理包含 %s 之列表</string>
<string name="remove_from_list">從列表中移除</string>
<string name="confirm_remove_list_member">移除此成員?</string>
<string name="no_followed_hashtags_title">跟隨主題標籤以跟上興趣主題</string>
<string name="no_followed_hashtags_subtitle">已跟隨的主題標籤將顯示於此</string>
<string name="no_lists_title">藉由列表以整理您的首頁河道</string>
<string name="no_lists_subtitle">您的將出現於此</string>
<string name="manage_accounts">新增或切換帳號</string>
<plurals name="x_posts_recently">
<item quantity="other">%,d 最近發嘟</item>
</plurals>

View File

@@ -114,4 +114,8 @@
<declare-styleable name="NestedRecyclerScrollView">
<attr name="takePriorityOverChildViews" format="boolean"/>
</declare-styleable>
<declare-styleable name="HeaderSubtitleLinearLayout">
<attr name="firstFraction" format="fraction"/>
</declare-styleable>
</resources>

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