Compare commits

..

53 Commits

Author SHA1 Message Date
sk
6b226cdcad bump version 2022-11-08 00:21:33 +01:00
sk
1776709b38 update readme 2022-11-08 00:21:17 +01:00
sk
75a35cd680 Merge branch 'feature/filter-home-timeline' into fork 2022-11-08 00:18:19 +01:00
sk
18d4f2fa36 add timeline filters for replies/boosts
fixes #32, mastodon#210
2022-11-08 00:13:06 +01:00
sk
bca936f6a2 move contribute to the spicy zone
i've been planning to do this for a while :D
2022-11-07 23:37:10 +01:00
sk
0b59379c4e update readme 2022-11-07 23:35:31 +01:00
sk
58abdad62a bump version 2022-11-07 21:18:41 +01:00
sk
c693414cc3 update readme 2022-11-07 21:18:37 +01:00
sk
ee158e1aba Merge branch 'feature/mark-media-as-sensitive' into fork 2022-11-07 21:04:44 +01:00
sk
40d478aaec tweak styles 2022-11-07 21:04:28 +01:00
sk
e7fb96b3ff Merge branch 'feature/mark-media-as-sensitive' into fork 2022-11-07 20:47:15 +01:00
sk
ef75427b45 fix option not being there when editing 2022-11-07 20:46:49 +01:00
sk
2ff4f00774 Merge branch 'feature/mark-media-as-sensitive' into fork 2022-11-07 20:17:39 +01:00
sk
534fd8c119 implement "mark media as sensitive" button
fixes #21
2022-11-07 20:15:16 +01:00
sk
2d2cd89454 Merge branch 'spoiler-height-independent' into fork 2022-11-07 17:32:55 +01:00
sk
9f3f5ca7c1 make spoiler height independent of content
fixes #12, fixes mastodon/mastodon-android#166
2022-11-07 17:32:37 +01:00
Samuel Kaiser
c0e6f17c83 Merge pull request #28 from br4yd/patch-1
Add German translation for the federated timeline
2022-11-07 16:57:21 +01:00
sk
677f1cb42d Merge remote-tracking branch 'origin/upstream' into fork 2022-11-07 16:56:27 +01:00
Gregory K
1ac6a04a46 Merge pull request #309 from julroy67/perapp-language
Add Android 13 per-app language preferences
2022-11-07 06:49:58 +03:00
Julien Humbert
21927d2e25 Add missing line in Android Manifest 2022-11-07 12:32:20 +09:00
Julien Humbert
c35441f5f7 Add per-app language preferences 2022-11-07 12:27:26 +09:00
br4yd
3718fe6601 Add German translation for the federated timeline
I added the translation strings for the federation timeline tab to the German translation file and also translated the values.
2022-11-06 22:21:53 +01:00
sk
095f234bd5 bump version 2022-11-06 11:16:31 +01:00
sk
f10c0e06db Merge branch 'fork' of github.com:sk22/mastodon-android-fork into fork 2022-11-06 11:13:42 +01:00
sk
ebbd5d1fa3 Merge branch 'upstream' into fork 2022-11-06 11:13:26 +01:00
Grishka
c8abf26040 Fix #301 2022-11-06 05:43:17 +03:00
Grishka
bc733af147 Actually no, this makes more sense 2022-11-06 05:39:22 +03:00
Grishka
77a2fd2a60 Fix #298 2022-11-06 05:36:43 +03:00
Samuel Kaiser
5cfc5eb08a Update README.md 2022-11-05 11:27:02 +01:00
Samuel Kaiser
b832d2df26 Update README.md 2022-11-04 18:02:33 +01:00
Samuel Kaiser
db34dc40ba Merge branch 'mastodon:master' into fork 2022-11-04 14:32:13 +01:00
Gregory K
bfa48c2d3e Merge pull request #289 from sk22/fix-editing-cw
Fix spoiler not being published when editing
2022-11-04 07:02:40 +03:00
Gregory K
b5e229a84d Merge pull request #288 from sk22/fix-editing-visibility
Fix wrong visibility displayed when editing
2022-11-04 07:02:19 +03:00
sk
ef207f885b increase update check interval 2022-11-04 03:37:32 +01:00
sk
c4eee28335 Merge branch 'feature/check-for-update-button' into fork 2022-11-04 03:34:06 +01:00
sk
6fe466779e add toash message 2022-11-04 03:33:41 +01:00
sk
e71db1b883 custom app name in strings 2022-11-04 03:11:10 +01:00
sk
b6efafe99d Merge branch 'feature/check-for-update-button' into fork 2022-11-04 03:09:39 +01:00
sk
688d466f8e implement manual update check settings item 2022-11-04 03:09:19 +01:00
Samuel Kaiser
3c5797932e add download badge 2022-11-03 17:42:31 +01:00
sk
48a5e262ce bump version 2022-11-03 17:18:57 +01:00
sk
63b0365208 remove reverted default visibility 2022-11-03 17:18:42 +01:00
sk
972c05d60b Revert "set unlisted as default visibility"
This reverts commit d34653750e.
2022-11-03 17:13:10 +01:00
sk
acb5778e0b bump version, again 2022-11-03 16:36:31 +01:00
sk
7694c50358 Merge branch 'fix-editing-cw' into fork 2022-11-03 16:35:31 +01:00
sk
7ffa368d10 fix spoiler not being published when editing 2022-11-03 16:33:12 +01:00
Y32Gcnte8z
53f8f41d88 remain visibility when editing 2022-11-03 16:15:17 +01:00
sk
93d57d847e fix newly published posts appearing twice
see https://github.com/mastodon/mastodon-android/issues/283
2022-11-03 16:14:12 +01:00
sk
83a4f5eec2 re-add missing onStatusUpdate event listener 2022-11-03 16:11:44 +01:00
Samuel Kaiser
836c2dba8d Merge branch 'mastodon:master' into fork 2022-11-02 22:32:57 +01:00
Samuel Kaiser
13ae8d2ebe Update README.md 2022-11-02 22:30:16 +01:00
Gregory K
98dafb4e49 Merge pull request #280 from sk22/fix-notifications-crash
Check whether title status item is null to fix null pointer exception
2022-11-03 00:27:07 +03:00
sk
85b8bae42e bump version 2022-11-02 22:15:26 +01:00
32 changed files with 360 additions and 69 deletions

View File

@@ -1,34 +1,48 @@
![Pink version of the Mastodon for Android launcher icon](mastodon/src/main/res/mipmap-xhdpi/ic_launcher_round.png)
# Mastodon for Android Fork
# Mastodos
> A fork of the [official Mastodon Android app](https://github.com/mastodon/mastodon-android) adding important features that are missing in the official app and possibly wont ever be implemented, such as the federated timeline, unlisted posting, bookmarks and an image description viewer.
[![Download latest release](https://img.shields.io/badge/dynamic/json?color=d92aad&label=download%20apk&query=%24.tag_name&url=https%3A%2F%2Fapi.github.com%2Frepos%2Fsk22%2Fmastodon-android-fork%2Freleases%2Flatest&style=for-the-badge)](https://github.com/sk22/mastodon-android-fork/releases/latest/download/mastodos.apk)
## Changes
* [Enable "Unlisted" as a visibility option](https://github.com/sk22/mastodon-android-fork/tree/feature/enable-unlisted)
([Pull request](https://github.com/mastodon/mastodon-android/pull/103)) and
[set as default](https://github.com/sk22/mastodon-android-fork/tree/feature/enable-unlisted-as-default)
* [Add "Federation" tab and change Discover tab order](https://github.com/sk22/mastodon-android-fork/tree/feature/add-federated-timeline) ([Fixes issue](https://github.com/mastodon/mastodon-android/issues/8))
### Features
* [Add “Unlisted” as a post visibility option](https://github.com/sk22/mastodon-android-fork/tree/feature/enable-unlisted)
([Pull request](https://github.com/mastodon/mastodon-android/pull/103))
* [Add “Federation” tab and change Discover tab order](https://github.com/sk22/mastodon-android-fork/tree/feature/add-federated-timeline) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/8))
* [Add image description button and viewer](https://github.com/sk22/mastodon-android-fork/tree/feature/display-alt-text) ([Pull request](https://github.com/mastodon/mastodon-android/pull/129))
* [Implement pinning posts and displaying pinned posts](https://github.com/sk22/mastodon-android-fork/tree/feature/pin-posts) ([Pull request](https://github.com/mastodon/mastodon-android/pull/140))
* [Implement a bookmark button and list](https://github.com/sk22/mastodon-android-fork/tree/feature/bookmarks) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/22))
* [Add “Check for update” button in addition to integrated update checker](https://github.com/sk22/mastodon-android-fork/commits/feature/check-for-update-button)
* [Add “Mark media as sensitive” option](https://github.com/sk22/mastodon-android-fork/tree/feature/mark-media-as-sensitive)
* [Add settings to hide replies and reposts from the timeline](https://github.com/sk22/mastodon-android-fork/tree/feature/filter-home-timeline) ([Pull request](https://github.com/mastodon/mastodon-android/pull/317))
### Behavior
* [Make back button return to the home tab before exiting the app](https://github.com/sk22/mastodon-android-fork/tree/feature/back-returns-home) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/118))
* [Always preserve content warnings when replying](https://github.com/sk22/mastodon-android-fork/tree/feature/always-preserve-cw) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/113))
* [Display full image when adding image description](https://github.com/sk22/mastodon-android-fork/tree/feature/compose-image-description-full-image) ([Pull request](https://github.com/mastodon/mastodon-android/pull/182))
* [Always preserve content warnings when replying](https://github.com/sk22/mastodon-android-fork/tree/feature/always-preserve-cw) ([Fixes issue](https://github.com/mastodon/mastodon-android/issues/113))
* [Make back button return to the home tab before exiting the app](https://github.com/sk22/mastodon-android-fork/tree/feature/back-returns-home) ([Fixes issue](https://github.com/mastodon/mastodon-android/issues/118))
* [Implement a bookmark button and list](https://github.com/sk22/mastodon-android-fork/tree/feature/bookmarks) ([Fixes issue](https://github.com/mastodon/mastodon-android/issues/22))
* [Implement deleting and re-drafting](https://github.com/sk22/mastodon-android-fork/tree/feature/delete-redraft) ([Fixes issue](https://github.com/mastodon/mastodon-android/issues/21))
* [Implement deleting and re-drafting](https://github.com/sk22/mastodon-android-fork/tree/feature/delete-redraft) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/21))
* [Set spoiler height independently to content height](https://github.com/sk22/mastodon-android-fork/commits/spoiler-height-independent) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/166))
## Fork-specific changes
### Installation
* Custom app name
To install this app on your Android device, download the [latest release from GitHub](https://github.com/sk22/mastodon-android-fork/releases/latest/download/mastodos.apk) and open it. You might have to accept installing APK files from your browser when trying to install it. You can also take a look at all releases on the [Releases](https://github.com/sk22/mastodon-android-fork/releases) page.
Mastodos makes use of [Mastodon for Android](https://github.com/mastodon/mastodon-android)s automatic update checker. Mastodos will check for new updates available on GitHub and offer to download and install them. You can also manually press “Check for updates” at the bottom of the settings page!
### Branding
* App name “Mastodos”
* Pink primary color
* Custom icon: Modulate upstream icon using ImageMagick
```bash
mogrify -modulate 90,100,140 mastodon/src/main/res/mipmap-*/ic_launcher*.png
```
* Custom primary color: Hue of all `primary` colors in `colors.xml` is rotated, on basis of upstream Mastodon's [old branding](https://github.com/mastodon/mastodon-android/commit/74f03026cfcfcfd23237c38ff47d2b2a98a6f92a#diff-59134ec2a1cf3761f80b0ecccbbf8b9e433d9780d2f5c5d6ac3ac8cc254e808f)
by `109.8°` (equivalent of `161%`, done by hand using
[PineTools](https://pinetools.com/shift-hue-color))
## Building
As this app is using Java 17 features, you need JDK 17 or newer to build it. Other than that, everything is pretty standard. You can either import the project into Android Studio and build it from there, or run the following command in the project directory:

View File

@@ -9,9 +9,13 @@ android {
applicationId "org.joinmastodon.android.sk"
minSdk 23
targetSdk 33
versionCode 25
versionName "1.1.4+fork.25"
versionCode 31
versionName "1.1.4+fork.31"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
resConfigs "en", "ar-rSA", "bs-rBA", "ca-rES", "cs-rCZ", "de-rDE", "el-rGR", "es-rES",
"eu-rES", "fi-rFI", "fr-rFR", "gl-rES", "hr-rHR", "hy-rAM", "it-rIT", "iw-rIL",
"ja-rJP", "kab", "ko-rKR", "oc-rFR", "pl-rPL", "pt-rBR", "pt-rPT", "ru-rRU",
"sv-rSE", "th-rTH", "tr-rTR", "uk-rUA", "vi-rVN", "zh-rCN", "zh-rTW"
}
buildTypes {

View File

@@ -26,6 +26,8 @@ import org.joinmastodon.android.api.MastodonAPIController;
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
import java.io.File;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -36,7 +38,7 @@ import okhttp3.Response;
@Keep
public class GithubSelfUpdaterImpl extends GithubSelfUpdater{
private static final long CHECK_PERIOD=24*3600*1000L;
private static final long CHECK_PERIOD=6*3600*1000L;
private static final String TAG="GithubSelfUpdater";
private UpdateState state=UpdateState.NO_UPDATE;
@@ -101,6 +103,12 @@ public class GithubSelfUpdaterImpl extends GithubSelfUpdater{
}
}
@Override
public void checkForUpdates() {
setState(UpdateState.CHECKING);
MastodonAPIController.runInBackground(this::actuallyCheckForUpdates);
}
private void actuallyCheckForUpdates(){
Request req=new Request.Builder()
.url("https://api.github.com/repos/sk22/mastodon-android-fork/releases/latest")

View File

@@ -16,6 +16,7 @@
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true"
android:localeConfig="@xml/locales_config"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:theme="@style/Theme.Mastodon.AutoLightDark"

View File

@@ -7,6 +7,8 @@ public class GlobalUserPreferences{
public static boolean playGifs;
public static boolean useCustomTabs;
public static boolean trueBlackTheme;
public static boolean showReplies;
public static boolean showBoosts;
public static ThemePreference theme;
private static SharedPreferences getPrefs(){
@@ -18,6 +20,8 @@ public class GlobalUserPreferences{
playGifs=prefs.getBoolean("playGifs", true);
useCustomTabs=prefs.getBoolean("useCustomTabs", true);
trueBlackTheme=prefs.getBoolean("trueBlackTheme", false);
showReplies=prefs.getBoolean("showReplies", true);
showBoosts=prefs.getBoolean("showBoosts", true);
theme=ThemePreference.values()[prefs.getInt("theme", 0)];
}
@@ -25,6 +29,8 @@ public class GlobalUserPreferences{
getPrefs().edit()
.putBoolean("playGifs", playGifs)
.putBoolean("useCustomTabs", useCustomTabs)
.putBoolean("showReplies", showReplies)
.putBoolean("showBoosts", showBoosts)
.putBoolean("trueBlackTheme", trueBlackTheme)
.putInt("theme", theme.ordinal())
.apply();

View File

@@ -4,7 +4,7 @@ import org.joinmastodon.android.model.Status;
public class StatusCountersUpdatedEvent{
public String id;
public int favorites, reblogs, replies;
public long favorites, reblogs, replies;
public boolean favorited, reblogged, pinned;
public StatusCountersUpdatedEvent(Status s){

View File

@@ -161,11 +161,13 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private Button publishButton;
private ImageButton mediaBtn, pollBtn, emojiBtn, spoilerBtn, visibilityBtn;
private ImageView sensitiveIcon;
private ComposeMediaLayout attachmentsView;
private TextView replyText;
private ReorderableLinearLayout pollOptionsView;
private View pollWrap;
private View addPollOptionBtn;
private View sensitiveItem;
private TextView pollDurationView;
private ArrayList<DraftPollOption> pollOptions=new ArrayList<>();
@@ -181,11 +183,12 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
private String pollDurationStr;
private EditText spoilerEdit;
private boolean hasSpoiler;
private boolean sensitive;
private ProgressBar sendProgress;
private ImageView sendError;
private View sendingOverlay;
private WindowManager wm;
private StatusPrivacy statusVisibility=StatusPrivacy.UNLISTED;
private StatusPrivacy statusVisibility=StatusPrivacy.PUBLIC;
private ComposeAutocompleteSpan currentAutocompleteSpan;
private FrameLayout mainEditTextWrap;
private ComposeAutocompleteViewController autocompleteViewController;
@@ -290,6 +293,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
emojiBtn=view.findViewById(R.id.btn_emoji);
spoilerBtn=view.findViewById(R.id.btn_spoiler);
visibilityBtn=view.findViewById(R.id.btn_visibility);
sensitiveIcon=view.findViewById(R.id.sensitive_icon);
sensitiveItem=view.findViewById(R.id.sensitive_item);
replyText=view.findViewById(R.id.reply_text);
mediaBtn.setOnClickListener(v->openFilePicker());
@@ -297,6 +302,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
emojiBtn.setOnClickListener(v->emojiKeyboard.toggleKeyboardPopup(mainEditText));
spoilerBtn.setOnClickListener(v->toggleSpoiler());
visibilityBtn.setOnClickListener(this::onVisibilityClick);
sensitiveItem.setOnClickListener(v->toggleSensitive());
emojiKeyboard.setOnIconChangedListener(new PopupKeyboard.OnIconChangeListener(){
@Override
public void onIconChanged(int icon){
@@ -362,11 +368,16 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
spoilerEdit.setVisibility(View.VISIBLE);
spoilerBtn.setSelected(true);
}else if(editingStatus!=null && !TextUtils.isEmpty(editingStatus.spoilerText)){
hasSpoiler=true;
spoilerEdit.setVisibility(View.VISIBLE);
spoilerEdit.setText(getArguments().getString("sourceSpoiler", editingStatus.spoilerText));
spoilerBtn.setSelected(true);
}
sensitive = editingStatus != null ? editingStatus.sensitive
: (savedInstanceState != null && savedInstanceState.getBoolean("sensitive", false));
sensitiveIcon.setSelected(sensitive);
ArrayList<Parcelable> serializedAttachments=(savedInstanceState!=null ? savedInstanceState : getArguments())
.getParcelableArrayList("attachments");
if(serializedAttachments!=null){
@@ -386,6 +397,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
if(editingStatus!=null && editingStatus.visibility!=null) {
statusVisibility=editingStatus.visibility;
}
updateVisibilityIcon();
autocompleteViewController=new ComposeAutocompleteViewController(getActivity(), accountID);
@@ -420,6 +432,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
outState.putSerializable("visibility", statusVisibility);
}
outState.putBoolean("sensitive", sensitive);
}
@Override
@@ -567,8 +580,11 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
}
}
updateSensitive();
if(editingStatus!=null){
updateCharCounter();
visibilityBtn.setEnabled(false);
}
}
@@ -676,6 +692,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
CreateStatus.Request req=new CreateStatus.Request();
req.status=text;
req.visibility=statusVisibility;
req.sensitive=sensitive;
if(!attachments.isEmpty()){
req.mediaIds=attachments.stream().map(a->a.serverAttachment.id).collect(Collectors.toList());
}
@@ -882,6 +899,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
uploadNextQueuedAttachment();
}
updatePublishButtonState();
updateSensitive();
if(getMediaAttachmentsCount()==MAX_ATTACHMENTS)
mediaBtn.setEnabled(false);
return true;
@@ -1056,6 +1074,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
updatePublishButtonState();
pollBtn.setEnabled(attachments.isEmpty());
mediaBtn.setEnabled(true);
updateSensitive();
}
private void onRetryOrCancelMediaUploadClick(View v){
@@ -1257,7 +1276,20 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
spoilerBtn.setSelected(false);
mainEditText.requestFocus();
updateCharCounter();
sensitiveIcon.setVisibility(getMediaAttachmentsCount() > 0 ? View.VISIBLE : View.GONE);
}
updateSensitive();
}
private void toggleSensitive() {
sensitive=!sensitive;
sensitiveIcon.setSelected(sensitive);
}
private void updateSensitive() {
sensitiveItem.setVisibility(View.GONE);
if (!attachments.isEmpty() && !hasSpoiler) sensitiveItem.setVisibility(View.VISIBLE);
if (attachments.isEmpty()) sensitive = false;
}
private int getMediaAttachmentsCount(){

View File

@@ -24,6 +24,7 @@ import android.widget.Toolbar;
import com.squareup.otto.Subscribe;
import org.joinmastodon.android.E;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.timelines.GetHomeTimeline;
import org.joinmastodon.android.api.session.AccountSessionManager;
@@ -82,7 +83,12 @@ public class HomeTimelineFragment extends StatusListFragment{
public void onSuccess(CacheablePaginatedResponse<List<Status>> result){
if(getActivity()==null)
return;
onDataLoaded(result.items, !result.items.isEmpty());
List<Status> filteredItems = result.items.stream().filter(i ->
(GlobalUserPreferences.showReplies || i.inReplyToId == null) &&
(GlobalUserPreferences.showBoosts || i.reblog == null)
).collect(Collectors.toList());
onDataLoaded(filteredItems, !result.items.isEmpty());
maxID=result.maxID;
if(result.isFromCache())
loadNewPosts();
@@ -142,7 +148,6 @@ public class HomeTimelineFragment extends StatusListFragment{
}
}
@Subscribe
public void onStatusCreated(StatusCreatedEvent ev){
prependItems(Collections.singletonList(ev.status), true);
}

View File

@@ -414,7 +414,7 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
private void bindHeaderView(){
setTitle(account.displayName);
setSubtitle(getResources().getQuantityString(R.plurals.x_posts, account.statusesCount, account.statusesCount));
setSubtitle(getResources().getQuantityString(R.plurals.x_posts, (int)(account.statusesCount%1000), account.statusesCount));
ViewImageLoader.load(avatar, null, new UrlImageLoaderRequest(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);
@@ -451,9 +451,9 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
followersCount.setText(UiUtils.abbreviateNumber(account.followersCount));
followingCount.setText(UiUtils.abbreviateNumber(account.followingCount));
postsCount.setText(UiUtils.abbreviateNumber(account.statusesCount));
followersLabel.setText(getResources().getQuantityString(R.plurals.followers, Math.min(999, account.followersCount)));
followingLabel.setText(getResources().getQuantityString(R.plurals.following, Math.min(999, account.followingCount)));
postsLabel.setText(getResources().getQuantityString(R.plurals.posts, Math.min(999, account.statusesCount)));
followersLabel.setText(getResources().getQuantityString(R.plurals.followers, (int)Math.min(999, account.followersCount)));
followingLabel.setText(getResources().getQuantityString(R.plurals.following, (int)Math.min(999, account.followingCount)));
postsLabel.setText(getResources().getQuantityString(R.plurals.posts, (int)Math.min(999, account.statusesCount)));
UiUtils.loadCustomEmojiInTextView(name);
UiUtils.loadCustomEmojiInTextView(bio);

View File

@@ -15,6 +15,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.ImageButton;
@@ -71,6 +72,7 @@ public class SettingsFragment extends MastodonToolbarFragment{
private PushSubscription pushSubscription;
private ImageView themeTransitionWindowView;
private TextItem checkForUpdateItem;
@Override
public void onCreate(Bundle savedInstanceState){
@@ -103,6 +105,16 @@ public class SettingsFragment extends MastodonToolbarFragment{
GlobalUserPreferences.save();
}));
items.add(new HeaderItem(R.string.settings_timeline));
items.add(new SwitchItem(R.string.settings_show_replies, R.drawable.ic_fluent_chat_multiple_24_regular, GlobalUserPreferences.showReplies, i->{
GlobalUserPreferences.showReplies=i.checked;
GlobalUserPreferences.save();
}));
items.add(new SwitchItem(R.string.settings_show_boosts, R.drawable.ic_fluent_arrow_repeat_all_24_regular, GlobalUserPreferences.showBoosts, i->{
GlobalUserPreferences.showBoosts=i.checked;
GlobalUserPreferences.save();
}));
items.add(new HeaderItem(R.string.settings_notifications));
items.add(notificationPolicyItem=new NotificationPolicyItem());
PushSubscription pushSubscription=getPushSubscription();
@@ -113,11 +125,15 @@ public class SettingsFragment extends MastodonToolbarFragment{
items.add(new HeaderItem(R.string.settings_boring));
items.add(new TextItem(R.string.settings_account, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/auth/edit")));
items.add(new TextItem(R.string.settings_contribute, ()->UiUtils.launchWebBrowser(getActivity(), "https://github.com/mastodon/mastodon-android")));
items.add(new TextItem(R.string.settings_tos, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/terms")));
items.add(new TextItem(R.string.settings_privacy_policy, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/terms")));
items.add(new RedHeaderItem(R.string.settings_spicy));
if (GithubSelfUpdater.needSelfUpdating()) {
checkForUpdateItem = new TextItem(R.string.check_for_update, GithubSelfUpdater.getInstance()::checkForUpdates);
items.add(checkForUpdateItem);
}
items.add(new TextItem(R.string.settings_contribute, ()->UiUtils.launchWebBrowser(getActivity(), "https://github.com/mastodon/mastodon-android")));
items.add(new TextItem(R.string.settings_clear_cache, this::clearImageCache));
items.add(new TextItem(R.string.log_out, this::confirmLogOut));
@@ -326,11 +342,25 @@ public class SettingsFragment extends MastodonToolbarFragment{
@Subscribe
public void onSelfUpdateStateChanged(SelfUpdateStateChangedEvent ev){
if(items.get(0) instanceof UpdateItem item){
RecyclerView.ViewHolder holder=list.findViewHolderForAdapterPosition(0);
if(holder instanceof UpdateViewHolder uvh){
uvh.bind(item);
}
checkForUpdateItem.loading = ev.state == GithubSelfUpdater.UpdateState.CHECKING;
if (list.findViewHolderForAdapterPosition(items.indexOf(checkForUpdateItem)) instanceof TextViewHolder tvh) tvh.rebind();
UpdateItem updateItem = null;
if(items.get(0) instanceof UpdateItem item0) {
updateItem = item0;
} else if (ev.state != GithubSelfUpdater.UpdateState.CHECKING
&& ev.state != GithubSelfUpdater.UpdateState.NO_UPDATE) {
updateItem = new UpdateItem();
items.add(0, updateItem);
list.setAdapter(new SettingsAdapter());
}
if(updateItem != null && list.findViewHolderForAdapterPosition(0) instanceof UpdateViewHolder uvh){
uvh.bind(updateItem);
}
if (ev.state == GithubSelfUpdater.UpdateState.NO_UPDATE) {
Toast.makeText(getActivity(), R.string.no_update_available, Toast.LENGTH_SHORT).show();
}
}
@@ -398,10 +428,16 @@ public class SettingsFragment extends MastodonToolbarFragment{
private class TextItem extends Item{
private String text;
private Runnable onClick;
private boolean loading;
public TextItem(@StringRes int text, Runnable onClick){
public TextItem(@StringRes int text, Runnable onClick) {
this(text, onClick, false);
}
public TextItem(@StringRes int text, Runnable onClick, boolean loading){
this.text=getString(text);
this.onClick=onClick;
this.loading=loading;
}
@Override
@@ -630,14 +666,18 @@ public class SettingsFragment extends MastodonToolbarFragment{
private class TextViewHolder extends BindableViewHolder<TextItem> implements UsableRecyclerView.Clickable{
private final TextView text;
private final ProgressBar progress;
public TextViewHolder(){
super(getActivity(), R.layout.item_settings_text, list);
text=(TextView) itemView;
text = itemView.findViewById(R.id.text);
progress = itemView.findViewById(R.id.progress);
}
@Override
public void onBind(TextItem item){
text.setText(item.text);
progress.animate().alpha(item.loading ? 1 : 0);
}
@Override
@@ -692,8 +732,9 @@ public class SettingsFragment extends MastodonToolbarFragment{
@Override
public void onBind(UpdateItem item){
GithubSelfUpdater updater=GithubSelfUpdater.getInstance();
GithubSelfUpdater.UpdateInfo info=updater.getUpdateInfo();
GithubSelfUpdater.UpdateState state=updater.getState();
if (state == GithubSelfUpdater.UpdateState.CHECKING) return;
GithubSelfUpdater.UpdateInfo info=updater.getUpdateInfo();
if(state!=GithubSelfUpdater.UpdateState.DOWNLOADED){
text.setText(getString(R.string.update_available, info.version));
button.setText(getString(R.string.download_update, UiUtils.formatFileSize(getActivity(), info.size, false)));

View File

@@ -10,7 +10,6 @@ import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.events.StatusCreatedEvent;
import org.joinmastodon.android.events.StatusDeletedEvent;
import org.joinmastodon.android.events.StatusUpdatedEvent;
import org.joinmastodon.android.events.StatusUnpinnedEvent;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.ui.displayitems.ExtendedFooterStatusDisplayItem;
import org.joinmastodon.android.ui.displayitems.FooterStatusDisplayItem;
@@ -63,6 +62,59 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>{
protected void onStatusCreated(StatusCreatedEvent ev){}
protected void onStatusUpdated(StatusUpdatedEvent ev){
ArrayList<Status> statusesForDisplayItems=new ArrayList<>();
for(int i=0;i<data.size();i++){
Status s=data.get(i);
if(s.reblog!=null && s.reblog.id.equals(ev.status.id)){
s.reblog=ev.status;
statusesForDisplayItems.add(s);
}else if(s.id.equals(ev.status.id)){
data.set(i, ev.status);
statusesForDisplayItems.add(ev.status);
}
}
for(int i=0;i<preloadedData.size();i++){
Status s=preloadedData.get(i);
if(s.reblog!=null && s.reblog.id.equals(ev.status.id)){
s.reblog=ev.status;
}else if(s.id.equals(ev.status.id)){
preloadedData.set(i, ev.status);
}
}
if(statusesForDisplayItems.isEmpty())
return;
for(Status s:statusesForDisplayItems){
int i=0;
for(StatusDisplayItem item:displayItems){
if(item.parentID.equals(s.id)){
int start=i;
for(;i<displayItems.size();i++){
if(!displayItems.get(i).parentID.equals(s.id))
break;
}
List<StatusDisplayItem> postItems=displayItems.subList(start, i);
postItems.clear();
postItems.addAll(buildDisplayItems(s));
int oldSize=i-start, newSize=postItems.size();
if(oldSize==newSize){
adapter.notifyItemRangeChanged(start, newSize);
}else if(oldSize<newSize){
adapter.notifyItemRangeChanged(start, oldSize);
adapter.notifyItemRangeInserted(start+oldSize, newSize-oldSize);
}else{
adapter.notifyItemRangeChanged(start, newSize);
adapter.notifyItemRangeRemoved(start+newSize, oldSize-newSize);
}
break;
}
i++;
}
}
}
protected Status getContentStatusByID(String id){
Status s=getStatusByID(id);
return s==null ? null : s.getContentStatus();
@@ -138,6 +190,11 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>{
StatusListFragment.this.onStatusCreated(ev);
}
@Subscribe
public void onStatusUpdated(StatusUpdatedEvent ev){
StatusListFragment.this.onStatusUpdated(ev);
}
@Subscribe
public void onPollUpdated(PollUpdatedEvent ev){
if(!ev.accountID.equals(accountID))

View File

@@ -12,7 +12,7 @@ public class FollowerListFragment extends AccountRelatedAccountListFragment{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setSubtitle(getResources().getQuantityString(R.plurals.x_followers, account.followersCount, account.followersCount));
setSubtitle(getResources().getQuantityString(R.plurals.x_followers, (int)(account.followersCount%1000), account.followersCount));
}
@Override

View File

@@ -12,7 +12,7 @@ public class FollowingListFragment extends AccountRelatedAccountListFragment{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setSubtitle(getResources().getQuantityString(R.plurals.x_following, account.followingCount, account.followingCount));
setSubtitle(getResources().getQuantityString(R.plurals.x_following, (int)(account.followingCount%1000), account.followingCount));
}
@Override

View File

@@ -11,7 +11,7 @@ public class StatusFavoritesListFragment extends StatusRelatedAccountListFragmen
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setTitle(getResources().getQuantityString(R.plurals.x_favorites, status.favouritesCount, status.favouritesCount));
setTitle(getResources().getQuantityString(R.plurals.x_favorites, (int)(status.favouritesCount%1000), status.favouritesCount));
}
@Override

View File

@@ -11,7 +11,7 @@ public class StatusReblogsListFragment extends StatusRelatedAccountListFragment{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setTitle(getResources().getQuantityString(R.plurals.x_reblogs, status.reblogsCount, status.reblogsCount));
setTitle(getResources().getQuantityString(R.plurals.x_reblogs, (int)(status.reblogsCount%1000), status.reblogsCount));
}
@Override

View File

@@ -220,9 +220,9 @@ public class DiscoverAccountsFragment extends BaseRecyclerFragment<DiscoverAccou
followersCount.setText(UiUtils.abbreviateNumber(item.account.followersCount));
followingCount.setText(UiUtils.abbreviateNumber(item.account.followingCount));
postsCount.setText(UiUtils.abbreviateNumber(item.account.statusesCount));
followersLabel.setText(getResources().getQuantityString(R.plurals.followers, Math.min(999, item.account.followersCount)));
followingLabel.setText(getResources().getQuantityString(R.plurals.following, Math.min(999, item.account.followingCount)));
postsLabel.setText(getResources().getQuantityString(R.plurals.posts, Math.min(999, item.account.statusesCount)));
followersLabel.setText(getResources().getQuantityString(R.plurals.followers, (int)Math.min(999, item.account.followersCount)));
followingLabel.setText(getResources().getQuantityString(R.plurals.following, (int)Math.min(999, item.account.followingCount)));
postsLabel.setText(getResources().getQuantityString(R.plurals.posts, (int)Math.min(999, item.account.statusesCount)));
relationship=relationships.get(item.account.id);
if(relationship==null){
actionWrap.setVisibility(View.GONE);

View File

@@ -96,15 +96,15 @@ public class Account extends BaseModel{
/**
* How many statuses are attached to this account.
*/
public int statusesCount;
public long statusesCount;
/**
* The reported followers of this profile.
*/
public int followersCount;
public long followersCount;
/**
* The reported follows of this profile.
*/
public int followingCount;
public long followingCount;
// Optional attributes

View File

@@ -34,9 +34,9 @@ public class Status extends BaseModel implements DisplayItemsParent{
public List<Hashtag> tags;
@RequiredField
public List<Emoji> emojis;
public int reblogsCount;
public int favouritesCount;
public int repliesCount;
public long reblogsCount;
public long favouritesCount;
public long repliesCount;
public Instant editedAt;
public String url;

View File

@@ -115,9 +115,9 @@ public class AccountCardStatusDisplayItem extends StatusDisplayItem{
followersCount.setText(UiUtils.abbreviateNumber(item.account.followersCount));
followingCount.setText(UiUtils.abbreviateNumber(item.account.followingCount));
postsCount.setText(UiUtils.abbreviateNumber(item.account.statusesCount));
followersLabel.setText(item.parentFragment.getResources().getQuantityString(R.plurals.followers, Math.min(999, item.account.followersCount)));
followingLabel.setText(item.parentFragment.getResources().getQuantityString(R.plurals.following, Math.min(999, item.account.followingCount)));
postsLabel.setText(item.parentFragment.getResources().getQuantityString(R.plurals.posts, Math.min(999, item.account.statusesCount)));
followersLabel.setText(item.parentFragment.getResources().getQuantityString(R.plurals.followers, (int)Math.min(999, item.account.followersCount)));
followingLabel.setText(item.parentFragment.getResources().getQuantityString(R.plurals.following, (int)Math.min(999, item.account.followingCount)));
postsLabel.setText(item.parentFragment.getResources().getQuantityString(R.plurals.posts, (int)Math.min(999, item.account.statusesCount)));
relationship=item.parentFragment.getRelationship(item.account.id);
if(relationship==null){
actionWrap.setVisibility(View.GONE);

View File

@@ -97,7 +97,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
|| (item.status.visibility==StatusPrivacy.PRIVATE && item.status.account.id.equals(AccountSessionManager.getInstance().getAccount(item.accountID).self.id)));
}
private void bindButton(TextView btn, int count){
private void bindButton(TextView btn, long count){
if(count>0 && !item.hideCounts){
btn.setText(DecimalFormat.getIntegerInstance().format(count));
btn.setCompoundDrawablePadding(V.dp(8));

View File

@@ -83,7 +83,7 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
itemView.setClickable(false);
}else{
spoilerOverlay.setVisibility(View.VISIBLE);
text.setVisibility(View.INVISIBLE);
text.setVisibility(View.GONE);
itemView.setClickable(true);
}
}else{

View File

@@ -193,6 +193,15 @@ public class UiUtils{
}
}
@SuppressLint("DefaultLocale")
public static String abbreviateNumber(long n){
if(n<1_000_000_000L)
return abbreviateNumber((int)n);
double a=n/1_000_000_000.0;
return a>99f ? String.format("%,dB", (int)Math.floor(a)) : String.format("%,.1fB", n/1_000_000_000.0);
}
/**
* Android 6.0 has a bug where start and end compound drawables don't get tinted.
* This works around it by setting the tint colors directly to the drawables.

View File

@@ -23,6 +23,8 @@ public abstract class GithubSelfUpdater{
return BuildConfig.BUILD_TYPE.equals("githubRelease") || BuildConfig.BUILD_TYPE.equals("debug");
}
public abstract void checkForUpdates();
public abstract void maybeCheckForUpdates();
public abstract GithubSelfUpdater.UpdateState getState();

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="M3 3.748c0-0.414 0.336-0.75 0.75-0.75h16.504c0.618 0 0.971 0.706 0.6 1.2L16.69 9.75l4.164 5.551c0.371 0.495 0.018 1.2-0.6 1.2H4.5v4.75c0 0.38-0.282 0.693-0.648 0.743L3.75 22c-0.38 0-0.693-0.282-0.743-0.648L3 21.25V3.748z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

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="M3 3.748c0-0.414 0.336-0.75 0.75-0.75h16.504c0.618 0 0.971 0.706 0.6 1.2L16.69 9.75l4.164 5.551c0.371 0.495 0.018 1.2-0.6 1.2H4.5v4.75c0 0.38-0.282 0.693-0.648 0.743L3.75 22c-0.38 0-0.693-0.282-0.743-0.648L3 21.25V3.748zm15.754 0.75H4.5v10.503h14.254l-3.602-4.802c-0.2-0.266-0.2-0.633 0-0.9l3.602-4.8z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--~ Copyright (c) 2022. ~ Microsoft Corporation. All rights reserved.-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_fluent_flag_24_filled" android:state_activated="true"/>
<item android:drawable="@drawable/ic_fluent_flag_24_filled" android:state_checked="true"/>
<item android:drawable="@drawable/ic_fluent_flag_24_filled" android:state_selected="true"/>
<item android:drawable="@drawable/ic_fluent_flag_24_regular"/>
</selector>

View File

@@ -20,6 +20,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:paddingVertical="8dp"
android:orientation="vertical">
<TextView

View File

@@ -154,6 +154,38 @@
android:layout_gravity="center_horizontal"
android:visibility="gone"/>
<LinearLayout
android:id="@+id/sensitive_item"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center_vertical"
android:layoutDirection="locale"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:background="?android:selectableItemBackground"
android:visibility="gone">
<ImageView
android:id="@+id/sensitive_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="32dp"
android:src="@drawable/ic_fluent_flag_24_selector"
android:tint="?android:textColorPrimary"
android:importantForAccessibility="no"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="16sp"
android:singleLine="true"
android:text="@string/mark_media_as_sensitive" />
</LinearLayout>
</LinearLayout>
</ScrollView>

View File

@@ -1,13 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center_vertical"
android:textSize="16sp"
android:textColor="?android:textColorPrimary"
android:singleLine="true"
android:ellipsize="end"
tools:text="daffdsa"/>
android:layoutDirection="locale">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="48dp"
android:paddingRight="16dp"
android:gravity="center_vertical"
android:textSize="16sp"
android:textColor="?android:textColorPrimary"
android:singleLine="true"
android:ellipsize="end"
tools:text="Account settings"/>
<ProgressBar
android:id="@+id/progress"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center"
android:alpha="0"
/>
</LinearLayout>

View File

@@ -252,6 +252,9 @@
<string name="theme_dark">Dunkel</string>
<string name="theme_true_black">AMOLED-Modus</string>
<string name="settings_behavior">App-Verhalten</string>
<string name="settings_timeline">Timeline</string>
<string name="settings_show_replies">Antworten anzeigen</string>
<string name="settings_show_boosts">Geteilte Beiträge anzeigen</string>
<string name="settings_gif">Spiele animierte GIFs, Avatare und Emojis ab</string>
<string name="settings_custom_tabs">In-App-Browser verwenden</string>
<string name="settings_notifications">Benachrichtigungen</string>
@@ -271,7 +274,7 @@
<string name="settings_privacy_policy">Datenschutzbestimmungen</string>
<string name="settings_spicy">Gefährliches</string>
<string name="settings_clear_cache">Medien-Cache leeren</string>
<string name="settings_app_version">Mastodon für Android v%1$s (%2$d)</string>
<string name="settings_app_version">Mastodos v%1$s (%2$d)</string>
<string name="media_cache_cleared">Medien-Cache geleert</string>
<string name="confirm_log_out">Bist du dir sicher, dass du dich abmelden möchtest?</string>
<string name="sensitive_content">Sensibler Inhalt</string>
@@ -288,6 +291,7 @@
<string name="button_share">Teilen</string>
<string name="media_no_description">Medien ohne Beschreibung</string>
<string name="add_media">Medien hinzufügen</string>
<string name="mark_media_as_sensitive">Medien als NSFW markieren</string>
<string name="add_poll">Umfrage hinzufügen</string>
<string name="emoji">Emoji</string>
<string name="post_visibility">Sichtbarkeit des Beitrages</string>
@@ -315,10 +319,12 @@
<string name="downloading">wird heruntergeladen </string>
<string name="no_app_to_handle_action">Es gibt keine App, um diese Aktion auszuführen</string>
<string name="local_timeline">Community</string>
<string name="federated_timeline">Föderation</string>
<string name="trending_posts_info_banner">Dies sind Beiträge, die auf deinem Mastodon-Server gerade angesagt sind.</string>
<string name="trending_hashtags_info_banner">Dies sind Hashtags, die auf deinem Mastodon-Server gerade angesagt sind.</string>
<string name="trending_links_info_banner">Dies sind journalistische Nachrichten, die auf deinem Mastodon-Server gerade am häufigsten geteilt werden.</string>
<string name="local_timeline_info_banner">Dies sind die neuesten Beiträge der Leute, die den gleichen Mastodon-Server verwenden wie du.</string>
<string name="federated_timeline_info_banner">Dies sind die neusten Beiträge der Leute, die in der Föderation deines Servers sind.</string>
<string name="dismiss">Verwerfen</string>
<string name="see_new_posts">Neue Beiträge anzeigen</string>
<string name="load_missing_posts">Weitere Beiträge laden</string>
@@ -387,10 +393,12 @@
<string name="upload_error_connection_lost">Dein Gerät hat gerade keinen Zugang zum Internet</string>
<string name="upload_processing">wird verarbeitet </string>
<!-- %s is version like 1.2.3 -->
<string name="update_available">Mastodon für Android %s kann nun heruntergeladen werden.</string>
<string name="update_available">Mastodos %s kann nun heruntergeladen werden.</string>
<!-- %s is version like 1.2.3 -->
<string name="update_ready">Mastodon für Android %s wurde heruntergeladen und kann nun installiert werden.</string>
<string name="update_ready">Mastodos %s wurde heruntergeladen und kann nun installiert werden.</string>
<!-- %s is file size -->
<string name="download_update">Download (%s)</string>
<string name="install_update">Installieren</string>
<string name="check_for_update">Auf Update prüfen</string>
<string name="no_update_available">Kein Update verfügbar</string>
</resources>

View File

@@ -256,6 +256,9 @@
<string name="theme_dark">Dark</string>
<string name="theme_true_black">True black mode</string>
<string name="settings_behavior">Behavior</string>
<string name="settings_timeline">Timeline</string>
<string name="settings_show_replies">Show replies</string>
<string name="settings_show_boosts">Show boosts</string>
<string name="settings_gif">Play animated avatars and emoji</string>
<string name="settings_custom_tabs">Use in-app browser</string>
<string name="settings_notifications">Notifications</string>
@@ -275,7 +278,7 @@
<string name="settings_privacy_policy">Privacy policy</string>
<string name="settings_spicy">The spicy zone</string>
<string name="settings_clear_cache">Clear media cache</string>
<string name="settings_app_version">Mastodon for Android v%1$s (%2$d)</string>
<string name="settings_app_version">Mastodos v%1$s (%2$d)</string>
<string name="media_cache_cleared">Media cache cleared</string>
<string name="confirm_log_out">Are you sure you want to sign out?</string>
<string name="sensitive_content">Sensitive content</string>
@@ -294,6 +297,7 @@
<string name="bookmarks">Bookmarks</string>
<string name="media_no_description">Media without description</string>
<string name="add_media">Add media</string>
<string name="mark_media_as_sensitive">Mark media as sensitive</string>
<string name="add_poll">Add a poll</string>
<string name="emoji">Emoji</string>
<string name="post_visibility">Post visibility</string>
@@ -396,12 +400,14 @@
<string name="upload_error_connection_lost">Your device lost connection to the internet</string>
<string name="upload_processing">Processing…</string>
<!-- %s is version like 1.2.3 -->
<string name="update_available">Mastodon for Android %s is ready to download.</string>
<string name="update_available">Mastodos %s is ready to download.</string>
<!-- %s is version like 1.2.3 -->
<string name="update_ready">Mastodon for Android %s is downloaded and ready to install.</string>
<string name="update_ready">Mastodos %s is downloaded and ready to install.</string>
<!-- %s is file size -->
<string name="download_update">Download (%s)</string>
<string name="install_update">Install</string>
<string name="check_for_update">Check for update</string>
<string name="no_update_available">No update available</string>
<string name="privacy_policy_title">Mastodon and your privacy</string>
<string name="privacy_policy_subtitle">Although the Mastodon app does not collect any data, the server you sign up through may have a different policy. Take a minute to review and agree to the Mastodon app privacy policy and your server\'s privacy policy.</string>
<string name="i_agree">I Agree</string>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
<locale android:name="en" />
<locale android:name="ar" />
<locale android:name="bs" />
<locale android:name="ca" />
<locale android:name="cs" />
<locale android:name="de" />
<locale android:name="el" />
<locale android:name="es" />
<locale android:name="eu" />
<locale android:name="fi" />
<locale android:name="fr" />
<locale android:name="gl" />
<locale android:name="hr" />
<locale android:name="hy" />
<locale android:name="it" />
<locale android:name="iw" />
<locale android:name="ja" />
<locale android:name="kab" />
<locale android:name="ko" />
<locale android:name="oc" />
<locale android:name="pl" />
<locale android:name="pt-BR" />
<locale android:name="pt-PT" />
<locale android:name="ru" />
<locale android:name="sv" />
<locale android:name="th" />
<locale android:name="tr" />
<locale android:name="uk" />
<locale android:name="vi" />
<locale android:name="zh-Hans" />
<locale android:name="zh-Hant" />
</locale-config>