Compare commits

...

53 Commits

Author SHA1 Message Date
sk
e2799fcdff fix metadata markdown 2022-12-23 23:58:59 +01:00
sk
8e4f402e21 update changelogs 2022-12-23 23:48:21 +01:00
sk
10d2949647 remove unused method 2022-12-23 23:43:19 +01:00
sk
30ef23308b bump version 2022-12-23 23:41:46 +01:00
sk
564132ee82 update changelog 2022-12-23 23:40:50 +01:00
sk
1e527e87df fix default reblog visibility 2022-12-23 23:39:51 +01:00
sk
9692a04275 Merge remote-tracking branch 'weblate/main' 2022-12-23 23:36:48 +01:00
Linerly
6ece8eb0c1 Translated using Weblate (Indonesian)
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/id/
2022-12-23 22:18:14 +00:00
Choukajohn
1f33237e8a Translated using Weblate (French)
Currently translated at 100.0% (11 of 11 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/fr/
2022-12-23 22:18:14 +00:00
Linerly
9209508aac Translated using Weblate (Indonesian)
Currently translated at 100.0% (89 of 89 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-23 22:18:14 +00:00
Choukajohn
f750e6ff7e Translated using Weblate (French)
Currently translated at 100.0% (89 of 89 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-23 22:18:14 +00:00
sk
f2eecf774b disable block domain from post 2022-12-23 22:59:06 +01:00
sk
98de4e75e0 implement open with other account as submenu 2022-12-23 22:56:18 +01:00
sk
459e32caf8 fix instance info v2 never getting saved 2022-12-23 21:49:21 +01:00
sk
c4ad325e5c improve settings items 2022-12-23 21:35:16 +01:00
sk
f55bd6d6cd truncate publish button 2022-12-23 21:16:36 +01:00
sk
f1ce700c93 add option to open post with other account
closes #182
2022-12-23 21:11:22 +01:00
nitrogenez
c18e1e8456 Translated using Weblate (Ukrainian)
Currently translated at 90.0% (9 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/uk/
2022-12-23 19:22:28 +00:00
ling0412
1fcd1924c3 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (10 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/zh_Hans/
2022-12-23 19:22:28 +00:00
Choukajohn
a1767f0425 Translated using Weblate (French)
Currently translated at 100.0% (10 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/fr/
2022-12-23 19:22:28 +00:00
nitrogenez
44d95ca25f Translated using Weblate (Ukrainian)
Currently translated at 100.0% (86 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/uk/
2022-12-23 19:22:28 +00:00
Linerly
7432540c29 Translated using Weblate (Indonesian)
Currently translated at 100.0% (86 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-23 19:22:28 +00:00
Choukajohn
c289f58351 Translated using Weblate (French)
Currently translated at 100.0% (86 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-23 19:22:28 +00:00
gallegonovato
711e041ff5 Translated using Weblate (Spanish)
Currently translated at 100.0% (86 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-23 19:22:28 +00:00
ling0412
0ac3534585 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (86 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/zh_Hans/
2022-12-23 19:22:27 +00:00
benjaminwolkchen
57821e0860 Translated using Weblate (German)
Currently translated at 98.8% (85 of 86 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-23 19:22:27 +00:00
sk
0dae798c9a add option to open post with other account
closes #182
2022-12-23 20:17:54 +01:00
sk
732e780fd9 Merge remote-tracking branch 'weblate/main' 2022-12-23 18:54:20 +01:00
sk
5577124b7a use popup background color for dialogs 2022-12-23 18:38:16 +01:00
sk
81b82c75a2 add copy link item and change copyText
use haptic feedback instead of vibrator
2022-12-23 18:10:08 +01:00
sk
b32e322749 implement long-click to copy links
closes sk22#84
2022-12-23 17:51:06 +01:00
sk
3031cc4561 remove selectable background for username
closes sk22#187
2022-12-23 17:22:17 +01:00
sk
d60abc648c only show boost visibility for own posts 2022-12-23 17:11:29 +01:00
sk
a9a0233bb3 Merge branch 'clickable-boost-reply-line' 2022-12-23 16:52:04 +01:00
sk
f6fa9e5122 remove selectable background 2022-12-23 16:51:13 +01:00
sk
29b4f7c91a update changelog 2022-12-22 16:51:50 +01:00
sk
0a9ee57233 implement followed hashtags list
closes sk22/megalodon#162
2022-12-22 16:51:43 +01:00
AiOO
94b69a9c1c Translated using Weblate (Korean)
Currently translated at 100.0% (10 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/ko/
2022-12-22 14:59:36 +00:00
gallegonovato
f0209dd1cc Translated using Weblate (Spanish)
Currently translated at 100.0% (10 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/es/
2022-12-22 14:59:36 +00:00
Linerly
366e432c18 Translated using Weblate (Indonesian)
Currently translated at 100.0% (10 of 10 strings)

Translation: Megalodon/metadata
Translate-URL: https://translate.codeberg.org/projects/megalodon/metadata/id/
2022-12-22 14:59:36 +00:00
Christian Elbrianno
0075c0e779 Translated using Weblate (Indonesian)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-22 14:59:36 +00:00
Linerly
d99dfd4185 Translated using Weblate (Indonesian)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/id/
2022-12-22 14:59:36 +00:00
Choukajohn
0309b3ad25 Translated using Weblate (French)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/fr/
2022-12-22 14:59:36 +00:00
gallegonovato
7a85532b73 Translated using Weblate (Spanish)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/es/
2022-12-22 14:59:36 +00:00
AiOO
7299d947f7 Translated using Weblate (Korean)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/ko/
2022-12-22 14:59:35 +00:00
braydofficial
adec7b28f1 Translated using Weblate (German)
Currently translated at 100.0% (83 of 83 strings)

Translation: Megalodon/values
Translate-URL: https://translate.codeberg.org/projects/megalodon/values/de/
2022-12-22 14:59:35 +00:00
sk
c2563da056 Merge branch 'feature/open-urls-in-app' 2022-12-22 15:35:53 +01:00
sk
64b9e53916 add missing fedi url format 2022-12-22 15:35:26 +01:00
sk
86ab6f7b3d implement setting boost visibility 2022-12-22 15:03:42 +01:00
sk
ed02733524 disable boost button if disabled
closes #180
2022-12-22 11:27:24 +01:00
sk
a99af63f34 Merge branch 'feature/open-urls-in-app' 2022-12-22 11:14:03 +01:00
sk
1d900a66fe try to open link previews in app 2022-12-22 11:13:50 +01:00
sk
f29acc217d update changelog 2022-12-22 01:37:52 +01:00
68 changed files with 820 additions and 163 deletions

View File

@@ -19,7 +19,7 @@
**Allows you to post publicly without having your post show up in trends, hashtags or public timelines (i.e., in the tabs “Community”, “Federated” and “Posts”).**
When posting with Unlisted visibility, your posts will still be publicly accessible in your profile. They will also be shown in peoples Home timelines, but only if they follow you or someone they follow reposted/replied to your post.
When posting with Unlisted visibility, your posts will still be publicly accessible in your profile. They will also be shown in peoples Home timelines, but only if they follow you or someone they follow reblogged/replied to your post.
The Mastodon documentation has some more information about [Unlisted posting](https://docs.joinmastodon.org/user/posting/#unlisted) and [Public timelines](https://docs.joinmastodon.org/user/network/#timelines).
@@ -117,7 +117,7 @@ There's also a handful of custom strings exclusive to this projects that would n
* [Implement a bookmark button and list](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon: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/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/check-for-update-button)
* [Add “Mark media as sensitive” option](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/mark-media-as-sensitive)
* [Add settings to hide replies and reposts from the timeline](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/filter-home-timeline) ([Pull request](https://github.com/mastodon/mastodon-android/pull/317))
* [Add settings to hide replies and reblogs from the timeline](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/filter-home-timeline) ([Pull request](https://github.com/mastodon/mastodon-android/pull/317))
* [Follow and unfollow hashtags](https://github.com/sk22/megalodon/commit/7d38f031f197aa6cefaf53e39d929538689c1e4e) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/233))
* [Notification bell for posts](https://github.com/sk22/megalodon/commit/b166ca705eb9169025ef32bbe6315b42491b57ea) ([Closes issue](https://github.com/mastodon/mastodon-android/issues/81))
* [Viewing lists and adding/removing users from lists](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:list-timeline-views) based on [@obstsalatschuessel](https://github.com/obstsalatschuessel)'s [Pull request](https://github.com/mastodon/mastodon-android/pull/286)
@@ -133,6 +133,7 @@ There's also a handful of custom strings exclusive to this projects that would n
* [Add translate function](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/translate-button)
* [Add language selector](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/language-selector)
* [Implement deleting notifications](https://github.com/sk22/megalodon/commit/b0f9ce081f69f29ad59658fc00ca41372cd2677d) (disabled by default)
* [Long-click boost button to "quote" a post](https://github.com/sk22/megalodon/commit/b25a237c20c6a924ed4d9b357999867c3a32b32b)
### Behavior
@@ -153,8 +154,8 @@ There's also a handful of custom strings exclusive to this projects that would n
* [Copy post URL when long-pressing share button](https://github.com/sk22/megalodon/commit/ba36347f03278763ecec617b1ce57ba89db7be72)
* [Add option to disable swiping between tabs](https://github.com/sk22/megalodon/commit/1f20b21fc84bf006c1ec14bd2229cbfad5215ec8)
* [Resolve Fediverse links in the app](https://github.com/mastodon/mastodon-android/compare/master...sk22:megalodon:feature/open-urls-in-app)
* [Long-click boost button to "quote" a post](https://github.com/sk22/megalodon/commit/b25a237c20c6a924ed4d9b357999867c3a32b32b)
* [Preserve whitespaces in HTML](https://github.com/sk22/megalodon/commit/7d876bddc7a07d98f0fecbf62b13bdb9fcce3412)
* [Long-click to copy links](https://github.com/sk22/megalodon/commit/b32e32274923a94742a9926ef38785f746d41405)
### Visual

3
fix-metadata-markdown-lists.sh Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/bash
find metadata -name '*.txt' -exec sed -Ei 's/^[–—─•·*]\s+/- /' {} \;

View File

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

View File

@@ -9,6 +9,7 @@ import org.joinmastodon.android.api.requests.statuses.SetStatusFavorited;
import org.joinmastodon.android.api.requests.statuses.SetStatusReblogged;
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.StatusPrivacy;
import java.util.HashMap;
import java.util.function.Consumer;
@@ -59,7 +60,7 @@ public class StatusInteractionController{
E.post(new StatusCountersUpdatedEvent(status));
}
public void setReblogged(Status status, boolean reblogged, Consumer<Status> cb){
public void setReblogged(Status status, boolean reblogged, StatusPrivacy visibility, Consumer<Status> cb){
if(!Looper.getMainLooper().isCurrentThread())
throw new IllegalStateException("Can only be called from main thread");
@@ -67,7 +68,7 @@ public class StatusInteractionController{
if(current!=null){
current.cancel();
}
SetStatusReblogged req=(SetStatusReblogged) new SetStatusReblogged(status.id, reblogged)
SetStatusReblogged req=(SetStatusReblogged) new SetStatusReblogged(status.id, reblogged, visibility)
.setCallback(new Callback<>(){
@Override
public void onSuccess(Status reblog){

View File

@@ -2,10 +2,17 @@ package org.joinmastodon.android.api.requests.statuses;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.StatusPrivacy;
public class SetStatusReblogged extends MastodonAPIRequest<Status>{
public SetStatusReblogged(String id, boolean reblogged){
public SetStatusReblogged(String id, boolean reblogged, StatusPrivacy visibility){
super(HttpMethod.POST, "/statuses/"+id+"/"+(reblogged ? "reblog" : "unreblog"), Status.class);
setRequestBody(new Object());
Request req = new Request();
req.visibility = visibility;
setRequestBody(req);
}
public static class Request {
public StatusPrivacy visibility;
}
}

View File

@@ -0,0 +1,24 @@
package org.joinmastodon.android.api.requests.tags;
import com.google.gson.reflect.TypeToken;
import org.joinmastodon.android.api.MastodonAPIRequest;
import org.joinmastodon.android.api.requests.HeaderPaginationRequest;
import org.joinmastodon.android.model.Hashtag;
import java.util.List;
public class GetFollowedHashtags extends HeaderPaginationRequest<Hashtag> {
public GetFollowedHashtags(String maxID, String minID, int limit, String sinceID){
super(HttpMethod.GET, "/followed_tags", new TypeToken<>(){});
if(maxID!=null)
addQueryParameter("max_id", maxID);
if(minID!=null)
addQueryParameter("min_id", minID);
if(sinceID!=null)
addQueryParameter("since_id", sinceID);
if(limit>0)
addQueryParameter("limit", ""+limit);
}
}

View File

@@ -13,8 +13,6 @@ import android.net.Uri;
import android.os.Build;
import android.util.Log;
import com.google.gson.JsonParseException;
import org.joinmastodon.android.BuildConfig;
import org.joinmastodon.android.E;
import org.joinmastodon.android.MainActivity;
@@ -104,12 +102,11 @@ public class AccountSessionManager{
public void addAccount(Instance instance, Token token, Account self, Application app, AccountActivationInfo activationInfo){
instances.put(instance.uri, instance);
updateInstanceInfoV2(instance);
AccountSession session=new AccountSession(token, self, app, instance.uri, activationInfo==null, activationInfo);
sessions.put(session.getID(), session);
lastActiveAccountID=session.getID();
writeAccountsFile();
updateInstanceEmojis(instance, instance.uri);
updateMoreInstanceInfo(instance, instance.uri);
if(PushSubscriptionManager.arePushNotificationsAvailable()){
session.getPushSubscriptionManager().registerAccountForPush(null);
}
@@ -328,10 +325,7 @@ public class AccountSessionManager{
@Override
public void onSuccess(Instance instance){
instances.put(domain, instance);
updateInstanceEmojis(instance, domain);
try {
updateInstanceInfoV2(instance);
} catch (Exception ignored) {}
updateMoreInstanceInfo(instance, domain);
}
@Override
@@ -342,16 +336,18 @@ public class AccountSessionManager{
.execNoAuth(domain);
}
public void updateInstanceInfoV2(Instance instance) {
public void updateMoreInstanceInfo(Instance instance, String domain) {
new GetInstance.V2().setCallback(new Callback<>() {
@Override
public void onSuccess(Instance.V2 v2) {
if (instance != null) instance.v2 = v2;
writeAccountsFile();
updateInstanceEmojis(instance, domain);
}
@Override
public void onError(ErrorResponse errorResponse) {}
public void onError(ErrorResponse errorResponse) {
updateInstanceEmojis(instance, domain);
}
}).execNoAuth(instance.uri);
}

View File

@@ -638,6 +638,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
} else {
publishButton.setText(publishText);
}
publishButton.setSingleLine();
publishButton.setEllipsize(TextUtils.TruncateAt.END);
publishButton.setOnClickListener(this::onPublishClick);
LinearLayout wrap=new LinearLayout(getActivity());
wrap.setOrientation(LinearLayout.HORIZONTAL);

View File

@@ -0,0 +1,107 @@
package org.joinmastodon.android.fragments;
import android.os.Bundle;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.tags.GetFollowedHashtags;
import org.joinmastodon.android.model.Hashtag;
import org.joinmastodon.android.model.HeaderPaginationList;
import org.joinmastodon.android.ui.utils.UiUtils;
import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.views.UsableRecyclerView;
public class FollowedHashtagsFragment extends BaseRecyclerFragment<Hashtag> implements ScrollableToTop {
private String nextMaxID;
private String accountId;
public FollowedHashtagsFragment() {
super(20);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args=getArguments();
accountId=args.getString("account");
setTitle(R.string.sk_hashtags_you_follow);
}
@Override
protected void onShown(){
super.onShown();
if(!getArguments().getBoolean("noAutoLoad") && !loaded && !dataLoading)
loadData();
}
@Override
protected void doLoadData(int offset, int count){
currentRequest=new GetFollowedHashtags(offset==0 ? null : nextMaxID, null, count, null)
.setCallback(new SimpleCallback<>(this){
@Override
public void onSuccess(HeaderPaginationList<Hashtag> result){
if(result.nextPageUri!=null)
nextMaxID=result.nextPageUri.getQueryParameter("max_id");
else
nextMaxID=null;
onDataLoaded(result, nextMaxID!=null);
}
})
.exec(accountId);
}
@Override
protected RecyclerView.Adapter getAdapter() {
return new HashtagsAdapter();
}
@Override
public void scrollToTop() {
smoothScrollRecyclerViewToTop(list);
}
private class HashtagsAdapter extends RecyclerView.Adapter<HashtagViewHolder>{
@NonNull
@Override
public HashtagViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
return new HashtagViewHolder();
}
@Override
public void onBindViewHolder(@NonNull HashtagViewHolder holder, int position) {
holder.bind(data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
}
private class HashtagViewHolder extends BindableViewHolder<Hashtag> implements UsableRecyclerView.Clickable{
private final TextView title;
public HashtagViewHolder(){
super(getActivity(), R.layout.item_text, list);
title=findViewById(R.id.title);
}
@Override
public void onBind(Hashtag item) {
title.setText(item.name);
title.setCompoundDrawablesRelativeWithIntrinsicBounds(itemView.getContext().getDrawable(R.drawable.ic_fluent_number_symbol_24_regular), null, null, null);
}
@Override
public void onClick() {
UiUtils.openHashtagTimeline(getActivity(), accountId, item.name, item.following);
}
}
}

View File

@@ -1,14 +1,9 @@
package org.joinmastodon.android.fragments;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -23,17 +18,13 @@ import org.joinmastodon.android.model.ListTimeline;
import org.joinmastodon.android.ui.utils.UiUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import me.grishka.appkit.api.ErrorResponse;
import me.grishka.appkit.api.SimpleCallback;
import me.grishka.appkit.fragments.BaseRecyclerFragment;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.UsableRecyclerView;
public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> implements ScrollableToTop {
@@ -159,7 +150,7 @@ public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> im
private final CheckBox listToggle;
public ListViewHolder(){
super(getActivity(), R.layout.item_list_timeline, list);
super(getActivity(), R.layout.item_text, list);
title=findViewById(R.id.title);
listToggle=findViewById(R.id.list_toggle);
}
@@ -167,8 +158,10 @@ public class ListTimelinesFragment extends BaseRecyclerFragment<ListTimeline> im
@Override
public void onBind(ListTimeline item) {
title.setText(item.title);
title.setCompoundDrawablesRelativeWithIntrinsicBounds(itemView.getContext().getDrawable(R.drawable.ic_fluent_people_community_24_regular), null, null, null);
if (profileAccountId != null) {
Boolean checked = userInList.get(item.id);
listToggle.setVisibility(View.VISIBLE);
listToggle.setChecked(userInList.containsKey(item.id) && checked != null && checked);
listToggle.setOnClickListener(this::onClickToggle);
} else {

View File

@@ -288,11 +288,11 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
followingBtn.setOnClickListener(this::onFollowersOrFollowingClick);
username.setOnLongClickListener(v->{
String username=account.acct;
if(!username.contains("@")){
username+="@"+AccountSessionManager.getInstance().getAccount(accountID).domain;
String usernameString=account.acct;
if(!usernameString.contains("@")){
usernameString+="@"+AccountSessionManager.getInstance().getAccount(accountID).domain;
}
UiUtils.copyText(getActivity(), '@'+username);
UiUtils.copyText(username, '@'+usernameString);
return true;
});
@@ -624,6 +624,10 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
args.putString("profileAccount", profileAccountID);
args.putString("profileDisplayUsername", account.getDisplayUsername());
Nav.go(getActivity(), ListTimelinesFragment.class, args);
}else if(id==R.id.followed_hashtags){
Bundle args=new Bundle();
args.putString("account", accountID);
Nav.go(getActivity(), FollowedHashtagsFragment.class, args);
}
return true;
}

View File

@@ -220,7 +220,7 @@ public class SettingsFragment extends MastodonToolbarFragment{
items.add(new TextItem(R.string.sk_settings_filters, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/filters"), R.drawable.ic_fluent_open_24_regular));
items.add(new TextItem(R.string.sk_settings_auth, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/auth/edit"), R.drawable.ic_fluent_open_24_regular));
String instanceName = instance != null && !instance.title.isBlank() ? instance.title : session.domain;
String instanceName = UiUtils.getInstanceName(accountID);
items.add(new HeaderItem(instanceName));
items.add(new TextItem(R.string.sk_settings_rules, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/about"), R.drawable.ic_fluent_open_24_regular));
items.add(new TextItem(R.string.settings_tos, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/terms"), R.drawable.ic_fluent_open_24_regular));

View File

@@ -139,7 +139,7 @@ public class StatusEditHistoryFragment extends StatusListFragment{
action=getString(R.string.edit_multiple_changed);
}
}
items.add(0, new ReblogOrReplyLineStatusDisplayItem(s.id, this, action+" · "+date, Collections.emptyList(), 0, null));
items.add(0, new ReblogOrReplyLineStatusDisplayItem(s.id, this, action+" · "+date, Collections.emptyList(), 0, null, null));
}
return items;
}

View File

@@ -32,7 +32,7 @@ public class M3AlertDialogBuilder extends AlertDialog.Builder{
View title=alert.findViewById(titleID);
if(title!=null){
int pad=V.dp(24);
title.setPadding(pad, pad, pad, pad);
title.setPadding(pad, pad, pad, V.dp(18));
}
}
int titleDividerID=getContext().getResources().getIdentifier("titleDividerNoCustom", "id", "android");

View File

@@ -1,9 +1,13 @@
package org.joinmastodon.android.ui.displayitems;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
@@ -12,19 +16,24 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.fragments.ComposeFragment;
import org.joinmastodon.android.model.Status;
import org.joinmastodon.android.model.StatusPrivacy;
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
import org.joinmastodon.android.ui.utils.UiUtils;
import org.parceler.Parcels;
import java.util.function.Consumer;
import me.grishka.appkit.Nav;
import me.grishka.appkit.utils.CubicBezierInterpolator;
import me.grishka.appkit.utils.V;
@@ -132,21 +141,25 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
}
private boolean onButtonTouch(View v, MotionEvent event){
boolean disabled = !v.isEnabled() || (v instanceof FrameLayout parentFrame &&
parentFrame.getChildCount() > 0 && !parentFrame.getChildAt(0).isEnabled());
int action = event.getAction();
long eventDuration = event.getEventTime() - event.getDownTime();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
touchingView = null;
v.removeCallbacks(longClickRunnable);
v.animate().scaleX(1).scaleY(1).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(150).start();
if (action == MotionEvent.ACTION_UP && eventDuration < ViewConfiguration.getLongPressTimeout()) v.performClick();
if (disabled) return true;
if (action == MotionEvent.ACTION_UP && eventDuration <= ViewConfiguration.getLongPressTimeout()) v.performClick();
else v.startAnimation(opacityIn);
} else if (action == MotionEvent.ACTION_DOWN) {
touchingView = v;
// 20dp to center in middle of icon, because: (icon width = 24dp) / 2 + (paddingStart = 8dp)
v.setPivotX(V.dp(20));
v.animate().scaleX(0.85f).scaleY(0.85f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(75).start();
if (disabled) return true;
v.postDelayed(longClickRunnable, ViewConfiguration.getLongPressTimeout());
v.startAnimation(opacityOut);
v.animate().scaleX(0.85f).scaleY(0.85f).setInterpolator(CubicBezierInterpolator.DEFAULT).setDuration(75).start();
}
return true;
}
@@ -161,21 +174,78 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
private void onBoostClick(View v){
boost.setSelected(!item.status.reblogged);
AccountSessionManager.getInstance().getAccount(item.accountID).getStatusInteractionController().setReblogged(item.status, !item.status.reblogged, r->{
v.startAnimation(opacityIn);
bindButton(boost, r.reblogsCount);
});
AccountSessionManager.getInstance().getAccount(item.accountID).getStatusInteractionController().setReblogged(item.status, !item.status.reblogged, null, r->boostConsumer(v, r));
}
private void boostConsumer(View v, Status r) {
v.startAnimation(opacityIn);
bindButton(boost, r.reblogsCount);
}
private boolean onBoostLongClick(View v){
v.setAlpha(1);
v.setScaleX(1);
v.setScaleY(1);
Bundle args=new Bundle();
args.putString("account", item.accountID);
args.putString("prefilledText", "\n\n" + item.status.url);
args.putInt("selectionStart", 0);
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
Context ctx = itemView.getContext();
View menu = LayoutInflater.from(ctx).inflate(R.layout.item_boost_menu, null);
Dialog dialog = new M3AlertDialogBuilder(ctx).setView(menu).create();
AccountSession session = AccountSessionManager.getInstance().getAccount(item.accountID);
Consumer<StatusPrivacy> doReblog = (visibility) -> {
v.startAnimation(opacityOut);
session.getStatusInteractionController()
.setReblogged(item.status, !item.status.reblogged, visibility, r->boostConsumer(v, r));
dialog.dismiss();
};
View separator = menu.findViewById(R.id.separator);
TextView reblogHeader = menu.findViewById(R.id.reblog_header);
TextView undoReblog = menu.findViewById(R.id.delete_reblog);
TextView itemPublic = menu.findViewById(R.id.vis_public);
TextView itemUnlisted = menu.findViewById(R.id.vis_unlisted);
TextView itemFollowers = menu.findViewById(R.id.vis_followers);
undoReblog.setVisibility(item.status.reblogged ? View.VISIBLE : View.GONE);
separator.setVisibility(item.status.reblogged ? View.GONE : View.VISIBLE);
reblogHeader.setVisibility(item.status.reblogged ? View.GONE : View.VISIBLE);
itemPublic.setVisibility(item.status.reblogged || item.status.visibility.isLessVisibleThan(StatusPrivacy.PUBLIC) ? View.GONE : View.VISIBLE);
itemUnlisted.setVisibility(item.status.reblogged || item.status.visibility.isLessVisibleThan(StatusPrivacy.UNLISTED) ? View.GONE : View.VISIBLE);
itemFollowers.setVisibility(item.status.reblogged || item.status.visibility.isLessVisibleThan(StatusPrivacy.PRIVATE) ? View.GONE : View.VISIBLE);
Drawable checkMark = ctx.getDrawable(R.drawable.ic_fluent_checkmark_circle_20_regular);
Drawable publicDrawable = ctx.getDrawable(R.drawable.ic_fluent_earth_24_regular);
Drawable unlistedDrawable = ctx.getDrawable(R.drawable.ic_fluent_people_community_24_regular);
Drawable followersDrawable = ctx.getDrawable(R.drawable.ic_fluent_people_checkmark_24_regular);
StatusPrivacy defaultVisibility = session.preferences.postingDefaultVisibility;
// e.g. post visibility is unlisted, but default is public
// in this case, we want to display the check mark on the most visible visibility
if (item.status.visibility.isLessVisibleThan(defaultVisibility)) {
for (StatusPrivacy vis : StatusPrivacy.values()) {
if (vis.equals(item.status.visibility)) {
defaultVisibility = vis;
break;
}
}
}
itemPublic.setCompoundDrawablesWithIntrinsicBounds(publicDrawable, null, StatusPrivacy.PUBLIC.equals(defaultVisibility) ? checkMark : null, null);
itemUnlisted.setCompoundDrawablesWithIntrinsicBounds(unlistedDrawable, null, StatusPrivacy.UNLISTED.equals(defaultVisibility) ? checkMark : null, null);
itemFollowers.setCompoundDrawablesWithIntrinsicBounds(followersDrawable, null, StatusPrivacy.PRIVATE.equals(defaultVisibility) ? checkMark : null, null);
undoReblog.setOnClickListener(c->doReblog.accept(null));
itemPublic.setOnClickListener(c->doReblog.accept(StatusPrivacy.PUBLIC));
itemUnlisted.setOnClickListener(c->doReblog.accept(StatusPrivacy.UNLISTED));
itemFollowers.setOnClickListener(c->doReblog.accept(StatusPrivacy.PRIVATE));
menu.findViewById(R.id.quote).setOnClickListener(c->{
dialog.dismiss();
v.startAnimation(opacityIn);
Bundle args=new Bundle();
args.putString("account", item.accountID);
args.putString("prefilledText", "\n\n" + item.status.url);
args.putInt("selectionStart", 0);
Nav.go(item.parentFragment.getActivity(), ComposeFragment.class, args);
});
dialog.show();
return true;
}
@@ -203,7 +273,7 @@ public class FooterStatusDisplayItem extends StatusDisplayItem{
}
private boolean onShareLongClick(View v){
UiUtils.copyText(v.getContext(), item.status.url);
UiUtils.copyText(v, item.status.url);
return true;
}

View File

@@ -11,6 +11,7 @@ import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
@@ -19,12 +20,11 @@ import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
import androidx.recyclerview.widget.RecyclerView;
import org.joinmastodon.android.GlobalUserPreferences;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
import org.joinmastodon.android.api.requests.statuses.GetStatusSourceText;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.fragments.ComposeFragment;
@@ -45,6 +45,7 @@ import org.parceler.Parcels;
import java.time.Instant;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import me.grishka.appkit.Nav;
import me.grishka.appkit.api.APIRequest;
@@ -139,6 +140,12 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
avatar.setOutlineProvider(roundCornersOutline);
avatar.setClipToOutline(true);
more.setOnClickListener(this::onMoreClick);
more.setOnLongClickListener((v) -> {
PopupMenu popup = new PopupMenu(itemView.getContext(), v);
populateAccountsMenu(popup.getMenu());
popup.show();
return true;
});
visibility.setOnClickListener(v->item.parentFragment.onVisibilityIconClick(this));
deleteNotification.setOnClickListener(v->UiUtils.confirmDeleteNotification(activity, item.parentFragment.getAccountID(), item.notification, ()->{
if (item.parentFragment instanceof NotificationsListFragment fragment) {
@@ -151,6 +158,13 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
optionsMenu.setOnMenuItemClickListener(menuItem->{
Account account=item.user;
int id=menuItem.getItemId();
SubMenu accountsMenu=id==R.id.open_with_account ? menuItem.getSubMenu() : null;
if (accountsMenu != null) {
accountsMenu.clear();
populateAccountsMenu(accountsMenu);
}
if(id==R.id.edit || id==R.id.delete_and_redraft) {
final Bundle args=new Bundle();
args.putString("account", item.parentFragment.getAccountID());
@@ -191,20 +205,19 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
}
}else if(id==R.id.delete){
UiUtils.confirmDeletePost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, s->{});
}else if(id==R.id.pin || id==R.id.unpin){
UiUtils.confirmPinPost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, !item.status.pinned, s->{});
}else if(id==R.id.mute){
UiUtils.confirmToggleMuteUser(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), account, relationship!=null && relationship.muting, r->{});
}else if(id==R.id.block){
UiUtils.confirmToggleBlockUser(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), account, relationship!=null && relationship.blocking, r->{});
}else if(id==R.id.pin || id==R.id.unpin) {
UiUtils.confirmPinPost(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.status, !item.status.pinned, s -> {
});
}else if(id==R.id.report){
Bundle args=new Bundle();
args.putString("account", item.parentFragment.getAccountID());
args.putParcelable("status", Parcels.wrap(item.status));
args.putParcelable("reportAccount", Parcels.wrap(item.status.account));
Nav.go(item.parentFragment.getActivity(), ReportReasonChoiceFragment.class, args);
}else if(id==R.id.open_in_browser){
}else if(id==R.id.open_in_browser) {
UiUtils.launchWebBrowser(activity, item.status.url);
}else if(id==R.id.copy_link){
UiUtils.copyText(parent, item.status.url);
}else if(id==R.id.follow){
if(relationship==null)
return true;
@@ -229,6 +242,17 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
});
}
private void populateAccountsMenu(Menu menu) {
List<AccountSession> sessions=AccountSessionManager.getInstance().getLoggedInAccounts();
sessions.stream().filter(s -> !s.getID().equals(item.accountID)).forEach(s -> {
String username = "@"+s.self.username+"@"+s.domain;
menu.add(username).setOnMenuItemClickListener(c->{
UiUtils.openURL(item.parentFragment.getActivity(), s.getID(), item.status.url, false);
return true;
});
});
}
@Override
public void onBind(HeaderStatusDisplayItem item){
name.setText(item.parsedName);
@@ -320,6 +344,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
menu.findItem(R.id.pin).setVisible(item.status!=null && isOwnPost && !item.status.pinned);
menu.findItem(R.id.unpin).setVisible(item.status!=null && isOwnPost && item.status.pinned);
menu.findItem(R.id.open_in_browser).setVisible(item.status!=null);
menu.findItem(R.id.copy_link).setVisible(item.status!=null);
MenuItem blockDomain=menu.findItem(R.id.block_domain);
MenuItem mute=menu.findItem(R.id.mute);
MenuItem block=menu.findItem(R.id.block);
@@ -349,12 +374,13 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
mute.setTitle(item.parentFragment.getString(relationship!=null && relationship.muting ? R.string.unmute_user : R.string.mute_user, account.getDisplayUsername()));
block.setTitle(item.parentFragment.getString(relationship!=null && relationship.blocking ? R.string.unblock_user : R.string.block_user, account.getDisplayUsername()));
report.setTitle(item.parentFragment.getString(R.string.report_user, account.getDisplayUsername()));
if(!account.isLocal()){
blockDomain.setVisible(true);
blockDomain.setTitle(item.parentFragment.getString(relationship!=null && relationship.domainBlocking ? R.string.unblock_domain : R.string.block_domain, account.getDomain()));
}else{
// disabled in megalodon. domain blocks from a post clutters the context menu and looks out of place
// if(!account.isLocal()){
// blockDomain.setVisible(true);
// blockDomain.setTitle(item.parentFragment.getString(relationship!=null && relationship.domainBlocking ? R.string.unblock_domain : R.string.block_domain, account.getDomain()));
// }else{
blockDomain.setVisible(false);
}
// }
follow.setTitle(item.parentFragment.getString(relationship!=null && relationship.following ? R.string.unfollow_user : R.string.follow_user, account.getDisplayUsername()));
}
}

View File

@@ -95,7 +95,7 @@ public class LinkCardStatusDisplayItem extends StatusDisplayItem{
}
private void onClick(View v){
UiUtils.launchWebBrowser(itemView.getContext(), item.status.card.url);
UiUtils.openURL(itemView.getContext(), item.parentFragment.getAccountID(), item.status.card.url);
}
}
}

View File

@@ -3,6 +3,7 @@ package org.joinmastodon.android.ui.displayitems;
import static org.joinmastodon.android.MastodonApp.context;
import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.SpannableStringBuilder;
@@ -14,6 +15,7 @@ import android.widget.TextView;
import org.joinmastodon.android.R;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.model.Emoji;
import org.joinmastodon.android.model.StatusPrivacy;
import org.joinmastodon.android.ui.text.HtmlParser;
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
import org.joinmastodon.android.ui.utils.UiUtils;
@@ -30,10 +32,13 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
private CharSequence text;
@DrawableRes
private int icon;
private StatusPrivacy visibility;
@DrawableRes
private int iconEnd;
private CustomEmojiHelper emojiHelper=new CustomEmojiHelper();
private View.OnClickListener handleClick;
public ReblogOrReplyLineStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, CharSequence text, List<Emoji> emojis, @DrawableRes int icon, @Nullable View.OnClickListener handleClick){
public ReblogOrReplyLineStatusDisplayItem(String parentID, BaseStatusListFragment parentFragment, CharSequence text, List<Emoji> emojis, @DrawableRes int icon, StatusPrivacy visibility, @Nullable View.OnClickListener handleClick){
super(parentID, parentFragment);
SpannableStringBuilder ssb=new SpannableStringBuilder(text);
HtmlParser.parseCustomEmoji(ssb, emojis);
@@ -43,6 +48,17 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
this.handleClick=handleClick;
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, outValue, true);
updateVisibility(visibility);
}
public void updateVisibility(StatusPrivacy visibility) {
this.visibility = visibility;
this.iconEnd = visibility != null ? switch (visibility) {
case PUBLIC -> R.drawable.ic_fluent_earth_20_regular;
case UNLISTED -> R.drawable.ic_fluent_people_community_20_regular;
case PRIVATE -> R.drawable.ic_fluent_people_checkmark_20_regular;
default -> 0;
} : 0;
}
@Override
@@ -70,10 +86,18 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
@Override
public void onBind(ReblogOrReplyLineStatusDisplayItem item){
text.setText(item.text);
text.setCompoundDrawablesRelativeWithIntrinsicBounds(item.icon, 0, 0, 0);
text.setCompoundDrawablesRelativeWithIntrinsicBounds(item.icon, 0, item.iconEnd, 0);
if(item.handleClick!=null) text.setOnClickListener(item.handleClick);
text.setEnabled(!item.inset);
text.setClickable(!item.inset);
Context ctx = itemView.getContext();
int visibilityText = item.visibility != null ? switch (item.visibility) {
case PUBLIC -> R.string.visibility_public;
case UNLISTED -> R.string.sk_visibility_unlisted;
case PRIVATE -> R.string.visibility_followers_only;
default -> 0;
} : 0;
if (visibilityText != 0) text.setContentDescription(item.text + " (" + ctx.getString(visibilityText) + ")");
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.N)
UiUtils.fixCompoundDrawableTintOnAndroid6(text);
}

View File

@@ -8,6 +8,7 @@ import android.view.View;
import android.view.ViewGroup;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.BaseStatusListFragment;
import org.joinmastodon.android.fragments.ProfileFragment;
import org.joinmastodon.android.fragments.ThreadFragment;
@@ -81,13 +82,14 @@ public abstract class StatusDisplayItem{
Bundle args=new Bundle();
args.putString("account", accountID);
if(status.reblog!=null){
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.user_boosted, status.account.displayName), status.account.emojis, R.drawable.ic_fluent_arrow_repeat_all_20_filled, i->{
boolean isOwnPost = AccountSessionManager.getInstance().isSelf(fragment.getAccountID(), status.account);
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.user_boosted, status.account.displayName), status.account.emojis, R.drawable.ic_fluent_arrow_repeat_all_20_filled, isOwnPost ? status.visibility : null, i->{
args.putParcelable("profileAccount", Parcels.wrap(status.account));
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
}));
}else if(status.inReplyToAccountId!=null && knownAccounts.containsKey(status.inReplyToAccountId)){
Account account=Objects.requireNonNull(knownAccounts.get(status.inReplyToAccountId));
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.in_reply_to, account.displayName), account.emojis, R.drawable.ic_fluent_arrow_reply_20_filled, i->{
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, fragment.getString(R.string.in_reply_to, account.displayName), account.emojis, R.drawable.ic_fluent_arrow_reply_20_filled, null, i->{
args.putParcelable("profileAccount", Parcels.wrap(account));
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
}));

View File

@@ -10,6 +10,8 @@ import android.text.Layout;
import android.text.Spanned;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.TextView;
import me.grishka.appkit.utils.V;
@@ -20,7 +22,11 @@ public class ClickableLinksDelegate {
private Path hlPath;
private LinkSpan selectedSpan;
private TextView view;
private final Runnable longClickRunnable = () -> {
if (selectedSpan != null) selectedSpan.onLongClick(view);
};
public ClickableLinksDelegate(TextView view) {
this.view=view;
hlPaint=new Paint();
@@ -30,6 +36,7 @@ public class ClickableLinksDelegate {
}
public boolean onTouch(MotionEvent event) {
long eventDuration = event.getEventTime() - event.getDownTime();
if(event.getAction()==MotionEvent.ACTION_DOWN){
int line=-1;
Rect rect=new Rect();
@@ -63,6 +70,7 @@ public class ClickableLinksDelegate {
}
hlPath=new Path();
selectedSpan=span;
view.postDelayed(longClickRunnable, ViewConfiguration.getLongPressTimeout());
hlPaint.setColor((span.getColor() & 0x00FFFFFF) | 0x33000000);
//l.getSelectionPath(start, end, hlPath);
for(int j=lstart;j<=lend;j++){
@@ -90,8 +98,11 @@ public class ClickableLinksDelegate {
}
}
if(event.getAction()==MotionEvent.ACTION_UP && selectedSpan!=null){
view.playSoundEffect(SoundEffectConstants.CLICK);
selectedSpan.onClick(view.getContext());
if (eventDuration <= ViewConfiguration.getLongPressTimeout()) {
view.playSoundEffect(SoundEffectConstants.CLICK);
selectedSpan.onClick(view.getContext());
}
view.removeCallbacks(longClickRunnable);
hlPath=null;
selectedSpan=null;
view.invalidate();
@@ -100,6 +111,7 @@ public class ClickableLinksDelegate {
if(event.getAction()==MotionEvent.ACTION_CANCEL){
hlPath=null;
selectedSpan=null;
view.removeCallbacks(longClickRunnable);
view.invalidate();
return false;
}

View File

@@ -117,8 +117,8 @@ public class HtmlParser{
case "a" -> {
String href=el.attr("href");
LinkSpan.Type linkType;
String text=el.text();
if(el.hasClass("hashtag")){
String text=el.text();
if(text.startsWith("#")){
linkType=LinkSpan.Type.HASHTAG;
href=text.substring(1);
@@ -136,7 +136,7 @@ public class HtmlParser{
}else{
linkType=LinkSpan.Type.URL;
}
openSpans.add(new SpanInfo(new LinkSpan(href, null, linkType, accountID), ssb.length(), el));
openSpans.add(new SpanInfo(new LinkSpan(href, null, linkType, accountID, text), ssb.length(), el));
}
case "br" -> ssb.append('\n');
case "span" -> {
@@ -260,7 +260,7 @@ public class HtmlParser{
String url=matcher.group(3);
if(TextUtils.isEmpty(matcher.group(4)))
url="http://"+url;
ssb.setSpan(new LinkSpan(url, null, LinkSpan.Type.URL, null), matcher.start(3), matcher.end(3), 0);
ssb.setSpan(new LinkSpan(url, null, LinkSpan.Type.URL, null, url), matcher.start(3), matcher.end(3), 0);
}while(matcher.find()); // Find more URLs
return ssb;
}

View File

@@ -3,6 +3,7 @@ package org.joinmastodon.android.ui.text;
import android.content.Context;
import android.text.TextPaint;
import android.text.style.CharacterStyle;
import android.view.View;
import org.joinmastodon.android.ui.utils.UiUtils;
@@ -13,12 +14,14 @@ public class LinkSpan extends CharacterStyle {
private String link;
private Type type;
private String accountID;
private String text;
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID){
public LinkSpan(String link, OnLinkClickListener listener, Type type, String accountID, String text){
this.listener=listener;
this.link=link;
this.type=type;
this.accountID=accountID;
this.text=text;
}
public int getColor(){
@@ -38,6 +41,10 @@ public class LinkSpan extends CharacterStyle {
}
}
public void onLongClick(View view) {
UiUtils.copyText(view, getType() == Type.URL ? link : text);
}
public String getLink(){
return link;
}

View File

@@ -32,6 +32,7 @@ import android.provider.OpenableColumns;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.view.HapticFeedbackConstants;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -56,6 +57,7 @@ import org.joinmastodon.android.api.requests.search.GetSearchResults;
import org.joinmastodon.android.api.requests.statuses.DeleteStatus;
import org.joinmastodon.android.api.requests.statuses.GetStatusByID;
import org.joinmastodon.android.api.requests.statuses.SetStatusPinned;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
import org.joinmastodon.android.events.FollowRequestHandledEvent;
@@ -69,6 +71,7 @@ import org.joinmastodon.android.fragments.ProfileFragment;
import org.joinmastodon.android.fragments.ThreadFragment;
import org.joinmastodon.android.model.Account;
import org.joinmastodon.android.model.Emoji;
import org.joinmastodon.android.model.Instance;
import org.joinmastodon.android.model.ListTimeline;
import org.joinmastodon.android.model.Notification;
import org.joinmastodon.android.model.Relationship;
@@ -96,6 +99,7 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import androidx.annotation.AttrRes;
import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.browser.customtabs.CustomTabsIntent;
@@ -731,22 +735,37 @@ public class UiUtils{
String it = uri.getPath();
return it.matches("^/@[^/]+$") ||
it.matches("^/@[^/]+/\\d+$") ||
it.matches("^/users/\\w+$") ||
it.matches("^/notice/[a-zA-Z0-9]+$") ||
it.matches("^/objects/[-a-f0-9]+$") ||
it.matches("^/notes/[a-z0-9]+$") ||
it.matches("^/display/[-a-f0-9]+$") ||
it.matches("^/profile/\\w+$") ||
it.matches("^/p/\\w+/\\d+$") ||
it.matches("^/\\w+$") ||
it.matches("^/@[^/]+/statuses/[a-zA-Z0-9]+$") ||
it.matches("^/o/[a-f0-9]+$");
it.matches("^/@[^/]+/\\d+$") ||
it.matches("^/users/\\w+$") ||
it.matches("^/notice/[a-zA-Z0-9]+$") ||
it.matches("^/objects/[-a-f0-9]+$") ||
it.matches("^/notes/[a-z0-9]+$") ||
it.matches("^/display/[-a-f0-9]+$") ||
it.matches("^/profile/\\w+$") ||
it.matches("^/p/\\w+/\\d+$") ||
it.matches("^/\\w+$") ||
it.matches("^/@[^/]+/statuses/[a-zA-Z0-9]+$") ||
it.matches("^/users/[^/]+/statuses/[a-zA-Z0-9]+$") ||
it.matches("^/o/[a-f0-9]+$");
}
public static void openURL(Context context, String accountID, String url){
public static String getInstanceName(String accountID) {
AccountSession session = AccountSessionManager.getInstance().getAccount(accountID);
Instance instance = AccountSessionManager.getInstance().getInstanceInfo(session.domain);
return instance != null && !instance.title.isBlank() ? instance.title : session.domain;
}
public static void openURL(Context context, String accountID, String url) {
openURL(context, accountID, url, true);
}
public static void openURL(Context context, String accountID, String url, boolean launchBrowser){
Consumer<ProgressDialog> transformDialogForLookup = dialog -> {
dialog.setTitle(R.string.sk_loading_fediverse_resource_title);
if (accountID != null) {
dialog.setTitle(context.getString(R.string.sk_loading_resource_on_instance_title, getInstanceName(accountID)));
} else {
dialog.setTitle(R.string.sk_loading_fediverse_resource_title);
}
dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel), (d, which) -> d.cancel());
dialog.setButton(DialogInterface.BUTTON_POSITIVE, context.getString(R.string.open_in_browser), (d, which) -> {
d.cancel();
@@ -771,7 +790,7 @@ public class UiUtils{
@Override
public void onError(ErrorResponse error){
error.showToast(context);
launchWebBrowser(context, url);
if (launchBrowser) launchWebBrowser(context, url);
}
})
.wrapProgress((Activity)context, R.string.loading, true, transformDialogForLookup)
@@ -791,14 +810,15 @@ public class UiUtils{
args.putParcelable("profileAccount", Parcels.wrap(results.accounts.get(0)));
Nav.go((Activity) context, ProfileFragment.class, args);
} else {
launchWebBrowser(context, url);
if (launchBrowser) launchWebBrowser(context, url);
else Toast.makeText(context, R.string.sk_resource_not_found, Toast.LENGTH_SHORT).show();
}
}
@Override
public void onError(ErrorResponse error) {
error.showToast(context);
launchWebBrowser(context, url);
if (launchBrowser) launchWebBrowser(context, url);
}
})
.wrapProgress((Activity)context, R.string.loading, true, transformDialogForLookup)
@@ -809,14 +829,13 @@ public class UiUtils{
launchWebBrowser(context, url);
}
public static void copyText(Context context, String text) {
public static void copyText(View v, String text) {
Context context = v.getContext();
context.getSystemService(ClipboardManager.class).setPrimaryClip(ClipData.newPlainText(null, text));
if(Build.VERSION.SDK_INT<Build.VERSION_CODES.TIRAMISU || UiUtils.isMIUI()){ // Android 13+ SystemUI shows its own thing when you put things into the clipboard
Toast.makeText(context, R.string.text_copied, Toast.LENGTH_SHORT).show();
}
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) vibrator.vibrate(VibrationEffect.createOneShot(50, VibrationEffect.DEFAULT_AMPLITUDE));
else vibrator.vibrate(50);
v.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
}
private static String getSystemProperty(String key){

View File

@@ -0,0 +1,3 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20">
<path android:pathData="M10 2c4.418 0 8 3.582 8 8s-3.582 8-8 8-8-3.582-8-8 3.582-8 8-8zm0 1c-3.866 0-7 3.134-7 7s3.134 7 7 7 7-3.134 7-7-3.134-7-7-7zm3.358 4.646c0.174 0.174 0.193 0.443 0.058 0.638l-0.058 0.07-4.005 4.004c-0.173 0.174-0.442 0.193-0.637 0.058l-0.07-0.058-2-2c-0.195-0.195-0.195-0.511 0-0.707C6.82 9.478 7.09 9.46 7.284 9.594l0.07 0.057L9 11.298l3.651-3.652c0.196-0.195 0.512-0.195 0.707 0z" 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="M21.78 3.28c0.293-0.293 0.293-0.767 0-1.06-0.293-0.293-0.768-0.293-1.06 0l-10 10-0.47 1.53 1.53-0.47 10-10zM6.25 3C4.455 3 3 4.455 3 6.25v11.5C3 19.545 4.455 21 6.25 21h11.5c1.795 0 3.25-1.455 3.25-3.25v-8C21 9.336 20.664 9 20.25 9S19.5 9.336 19.5 9.75v8c0 0.966-0.784 1.75-1.75 1.75H6.25c-0.966 0-1.75-0.784-1.75-1.75V6.25c0-0.966 0.784-1.75 1.75-1.75h8C14.664 4.5 15 4.164 15 3.75S14.664 3 14.25 3h-8z" 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="M10.987 2.89c0.077-0.408-0.19-0.8-0.598-0.877-0.407-0.077-0.799 0.19-0.876 0.598L8.494 7.998 3.75 8C3.335 8 3 8.336 3 8.75 3 9.166 3.336 9.5 3.75 9.5l4.46-0.002-0.946 5L2.75 14.5C2.335 14.5 2 14.836 2 15.25 2 15.665 2.336 16 2.75 16l4.23-0.002-0.967 5.116c-0.077 0.407 0.19 0.8 0.598 0.876 0.407 0.077 0.799-0.19 0.876-0.598l1.02-5.395 5.474-0.002-0.968 5.119c-0.077 0.407 0.19 0.8 0.598 0.876 0.407 0.077 0.799-0.19 0.876-0.598l1.021-5.398 4.742-0.002c0.415 0 0.75-0.336 0.75-0.75 0-0.415-0.336-0.75-0.75-0.75l-4.458 0.002 0.946-5 4.512-0.002c0.415 0 0.75-0.336 0.75-0.75s-0.336-0.75-0.75-0.75l-4.23 0.002 0.966-5.104c0.077-0.408-0.19-0.8-0.598-0.877-0.407-0.077-0.799 0.19-0.876 0.598l-1.018 5.384-5.474 0.002 0.966-5.107zm-1.25 6.608l5.474-0.003-0.946 5-5.474 0.002 0.946-5z" android:fillColor="@color/fluent_default_icon_tint"/>
</vector>

View File

@@ -6,12 +6,11 @@
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:paddingTop="16dp"
android:paddingBottom="6dp"
android:background="?android:selectableItemBackground"
android:textAppearance="@style/m3_title_small"
android:drawableStart="@drawable/ic_fluent_arrow_repeat_all_20_filled"
android:drawableTint="?android:textColorSecondary"

View File

@@ -241,17 +241,14 @@
android:textAppearance="@style/m3_headline_small"
tools:text="Eugen" />
<TextView
android:id="@+id/username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginStart="16dp"
android:layout_below="@id/name"
android:paddingHorizontal="16dp"
android:paddingTop="2dp"
android:paddingBottom="4dp"
android:background="?android:selectableItemBackground"
android:paddingTop="4dp"
android:paddingBottom="8dp"
android:textAppearance="@style/m3_title_medium"
android:textColor="?android:textColorSecondary"
tools:text="\@Gargron" />
@@ -262,7 +259,6 @@
android:layout_height="wrap_content"
android:layout_below="@id/username"
android:layout_marginLeft="16dp"
android:layout_marginTop="4dp"
android:layout_marginRight="16dp"
android:textAppearance="@style/m3_body_large"
android:textSize="16sp"
@@ -291,7 +287,6 @@
android:layout_height="wrap_content"
android:layout_below="@id/username"
android:layout_marginLeft="16dp"
android:layout_marginTop="8dp"
android:layout_marginRight="16dp"
android:textAppearance="@style/m3_body_large"
android:textSize="16sp"

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingVertical="12dp">
<TextView
android:id="@+id/reblog_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:fontFamily="sans-serif-medium"
android:textColor="?android:colorAccent"
android:accessibilityHeading="true"
android:paddingVertical="12dp"
android:paddingHorizontal="24dp"
android:text="@string/sk_reblog_with_visibility" />
<TextView
android:id="@+id/delete_reblog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:paddingVertical="12dp"
android:paddingHorizontal="24dp"
android:gravity="center_vertical"
android:textSize="16sp"
android:textColor="?android:textColorPrimary"
android:drawablePadding="16dp"
android:background="?android:selectableItemBackground"
android:text="@string/sk_undo_reblog"
android:visibility="gone"
android:drawableStart="@drawable/ic_fluent_arrow_repeat_all_off_24_regular" />
<TextView
android:id="@+id/vis_public"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:paddingVertical="12dp"
android:paddingHorizontal="24dp"
android:gravity="center_vertical"
android:textSize="16sp"
android:textColor="?android:textColorPrimary"
android:drawablePadding="16dp"
android:background="?android:selectableItemBackground"
android:text="@string/visibility_public"
android:drawableStart="@drawable/ic_fluent_earth_24_regular" />
<TextView
android:id="@+id/vis_unlisted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:paddingVertical="12dp"
android:paddingHorizontal="24dp"
android:gravity="center_vertical"
android:textSize="16sp"
android:textColor="?android:textColorPrimary"
android:drawablePadding="16dp"
android:background="?android:selectableItemBackground"
android:text="@string/sk_visibility_unlisted"
android:drawableStart="@drawable/ic_fluent_people_community_24_regular" />
<TextView
android:id="@+id/vis_followers"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:paddingVertical="12dp"
android:paddingHorizontal="24dp"
android:gravity="center_vertical"
android:textSize="16sp"
android:textColor="?android:textColorPrimary"
android:drawablePadding="16dp"
android:background="?android:selectableItemBackground"
android:text="@string/visibility_followers_only"
android:drawableStart="@drawable/ic_fluent_people_checkmark_24_regular" />
<View
android:id="@+id/separator"
android:layout_height="1dp"
android:layout_width="match_parent"
android:layout_marginVertical="8dp"
android:background="?colorPollVoted" />
<TextView
android:id="@+id/quote"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="36dp"
android:paddingVertical="12dp"
android:paddingHorizontal="24dp"
android:gravity="center_vertical"
android:textSize="16sp"
android:textColor="?android:textColorPrimary"
android:drawablePadding="16dp"
android:background="?android:selectableItemBackground"
android:text="@string/sk_quote_post"
android:drawableStart="@drawable/ic_fluent_compose_24_regular" />
</LinearLayout>

View File

@@ -1,11 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="48dp"
android:paddingHorizontal="16dp"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:gravity="center_vertical"
android:layoutDirection="locale">
@@ -13,6 +12,7 @@
android:id="@+id/icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="32dp"
android:importantForAccessibility="no"
android:tint="?android:textColorPrimary"
@@ -21,10 +21,11 @@
<TextView
android:id="@+id/text"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:paddingVertical="8dp"
android:gravity="center_vertical"
android:textColor="?android:textColorPrimary"
android:textSize="16sp" />
@@ -33,6 +34,9 @@
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="32dp"
android:layout_weight="0"
android:layout_marginEnd="16dp"
android:maxWidth="140dp"
android:background="@drawable/bg_inline_button"
android:elevation="0dp"
android:ellipsize="middle"

View File

@@ -3,7 +3,8 @@
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:gravity="center_vertical"
android:layoutDirection="locale">
@@ -22,6 +23,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingVertical="8dp"
android:textSize="16sp"
android:textColor="?android:textColorPrimary"
tools:text="@string/theme_true_black"/>

View File

@@ -5,6 +5,7 @@
android:paddingHorizontal="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:gravity="center_vertical"
android:layoutDirection="locale">
<TextView
@@ -12,7 +13,6 @@
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:paddingVertical="8dp"
android:paddingEnd="16dp"
android:gravity="center_vertical"

View File

@@ -12,7 +12,6 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingHorizontal="16dp"
android:drawableLeft="@drawable/ic_fluent_people_community_24_regular"
android:drawableTint="?android:textColorSecondary"
android:drawablePadding="16dp"
android:textAppearance="@style/m3_title_medium"
@@ -26,6 +25,7 @@
android:clickable="false"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:visibility="gone"
android:paddingRight="16dp"/>
</LinearLayout>

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account">
<menu android:id="@+id/accounts" />
</item>
<item android:id="@+id/edit" android:title="@string/edit"/>
<item android:id="@+id/delete" android:title="@string/delete"/>
<item android:id="@+id/delete_and_redraft" android:title="@string/sk_delete_and_redraft"/>
@@ -11,5 +14,6 @@
<item android:id="@+id/follow" android:title="@string/follow_user"/>
<item android:id="@+id/report" android:title="@string/report_user"/>
<item android:id="@+id/bookmark" android:title="@string/add_bookmark"/>
<item android:id="@+id/copy_link" android:title="@string/sk_copy_link_to_post"/>
<item android:id="@+id/open_in_browser" android:title="@string/open_in_browser"/>
</menu>

View File

@@ -2,5 +2,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<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/favorites" android:title="@string/your_favorites" android:icon="@drawable/ic_fluent_star_24_regular"/>
<item android:id="@+id/followed_hashtags" android:title="@string/sk_hashtags_you_follow" android:icon="@drawable/ic_fluent_number_symbol_24_regular"/>
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
</menu>

View File

@@ -38,7 +38,7 @@
<string name="sk_disable_marquee">Laufschrift in Titelleisten deaktivieren</string>
<string name="sk_settings_contribute">Zu Megalodon beitragen</string>
<string name="sk_settings_show_federated_timeline">Föderierte Timeline anzeigen</string>
<string name="sk_notify_posts">Beitrags-Benachrichtigungen</string>
<string name="sk_notify_posts">Beitrags-Benachrichtigungen</string>
<string name="sk_settings_color_palette">Farbschema</string>
<string name="sk_color_palette_pink">Pink</string>
<string name="sk_color_palette_purple">Violett</string>
@@ -58,13 +58,13 @@
<string name="sk_clear_recent_languages">Zuletzt verwendete Sprachen leeren</string>
<string name="sk_welcome_title">Willkommen!</string>
<string name="sk_example_domain">beispiel.social</string>
<string name="sk_welcome_text">Der Hai sagt Hi! Um anzufangen, bitte gib den Domain-Namen deiner Heim-Instanz unten ein.</string>
<string name="sk_welcome_text">Der Hai sagt Hi! Um anzufangen, bitte gib den Domain-Namen deiner Heim-Instanz unten ein.</string>
<string name="sk_color_palette_material3">System</string>
<string name="sk_color_palette_red">Rot</string>
<string name="sk_settings_profile">Profil einrichten</string>
<string name="sk_settings_posting">Einstellungen für Beiträge</string>
<string name="sk_settings_filters">Filter konfigurieren</string>
<string name="sk_settings_auth">Sicherheitseinstellungen</string>
<string name="sk_settings_auth">Sicherheits-Einstellungen</string>
<string name="sk_settings_rules">Regelwerk</string>
<string name="sk_settings_about">Über die App</string>
<string name="sk_settings_donate">Spenden</string>
@@ -73,12 +73,15 @@
<string name="sk_delete_notification_confirm">Benachrichtigung wirklich löschen\?</string>
<string name="sk_clear_all_notifications_confirm_action">Alle löschen</string>
<string name="sk_enable_delete_notifications">Löschen von Benachrichtigungen aktivieren</string>
<string name="sk_settings_publish_button_text">Veröffentlichen-Button-Text</string>
<string name="sk_settings_hide_translate_in_timeline">Übersetzen-Button in der Timeline ausblenden</string>
<string name="sk_settings_publish_button_text">Veröffentlichen-Button-Text</string>
<string name="sk_settings_hide_translate_in_timeline">Übersetzen-Button in der Timeline ausblenden</string>
<string name="sk_delete_notification">Benachrichtigung löschen</string>
<string name="sk_clear_all_notifications">Alle Benachrichtigungen löschen</string>
<string name="sk_settings_publish_button_text_title">Veröffentlichen-Button-Text anpassen</string>
<string name="sk_settings_publish_button_text_title">Veröffentlichen-Button-Text anpassen</string>
<string name="sk_clear_all_notifications_confirm">Wirklich alle Benachrichtigungen löschen\?</string>
<string name="sk_settings_translation_availability_note_available">%s unterstützt Übersetzung!</string>
<string name="sk_settings_translation_availability_note_unavailable">%s scheint keine Übersetzung zu unterstützen.</string>
<string name="sk_loading_fediverse_resource_title">Suche im Fediverse…</string>
<string name="sk_undo_reblog">Reblog rückgängig machen</string>
<string name="sk_reblog_with_visibility">Rebloggen mit Sichtbarkeit</string>
</resources>

View File

@@ -81,4 +81,8 @@
<string name="sk_clear_all_notifications_confirm">¿Estás seguro de que quieres borrar todas las notificaciones\?</string>
<string name="sk_settings_translation_availability_note_available">¡%s admite traducción!</string>
<string name="sk_settings_translation_availability_note_unavailable">%s no parece soportar la traducción.</string>
<string name="sk_loading_fediverse_resource_title">Buscándolo en Fediverse…</string>
<string name="sk_quote_post">Publicar sobre esto</string>
<string name="sk_undo_reblog">Deshacer reblogueo</string>
<string name="sk_reblog_with_visibility">Rebloguea con visibilidad</string>
</resources>

View File

@@ -81,4 +81,11 @@
<string name="sk_settings_translation_availability_note_available">%s prend en charge la traduction !</string>
<string name="sk_settings_translation_availability_note_unavailable">%s ne semble pas prendre en charge la traduction.</string>
<string name="sk_clear_all_notifications_confirm">Voulez-vous vraiment supprimer toutes les notifications \?</string>
<string name="sk_loading_fediverse_resource_title">Le rechercher sur le Fediverse…</string>
<string name="sk_reblog_with_visibility">Rebloguer avec visibilité</string>
<string name="sk_undo_reblog">Annuler le reblogage</string>
<string name="sk_quote_post">Poster à ce sujet</string>
<string name="sk_hashtags_you_follow">Hashtags que vous suivez</string>
<string name="sk_open_in_account">Ouvrir dans un autre compte</string>
<string name="sk_copy_link_to_post">Copier le lien du post</string>
</resources>

View File

@@ -61,4 +61,31 @@
<string name="sk_color_palette_red">Merah</string>
<string name="sk_translated_using">Diterjemahkan menggunakan %s</string>
<string name="sk_welcome_text">Hiu menyapamu! Untuk memulai, silakan memasukkan nama domain instansi Anda di bawah.</string>
<string name="sk_tabs_disable_swipe">Nonaktifkan mengusap antara tab</string>
<string name="sk_settings_profile">Atur profil</string>
<string name="sk_settings_filters">Atur profil</string>
<string name="sk_enable_delete_notifications">Aktifkan menghapus notifikasi</string>
<string name="sk_settings_publish_button_text">Teks tombol Terbitkan</string>
<string name="sk_settings_publish_button_text_title">Ubah teks tombol Terbitkan</string>
<string name="sk_settings_hide_translate_in_timeline">Sembunyikan tombol terjemahkan di lini masa</string>
<string name="sk_settings_translation_availability_note_available">%s mendukung penerjemahan!</string>
<string name="sk_settings_translation_availability_note_unavailable">%s sepertinya tidak mendukung penerjemahan.</string>
<string name="sk_clear_all_notifications_confirm">Apakah Anda yakin ingin menghapus semua notifikasi\?</string>
<string name="sk_loading_fediverse_resource_title">Mencari di Fedimesta…</string>
<string name="sk_settings_rules">Aturan</string>
<string name="sk_settings_about">Tentang aplikasi</string>
<string name="sk_settings_donate">Donasi</string>
<string name="sk_delete_notification">Hapus notifikasi</string>
<string name="sk_delete_notification_confirm_action">Hapus notifikasi</string>
<string name="sk_delete_notification_confirm">Apakah kamu yakin ingin menghapus notifikasi ini\?</string>
<string name="sk_clear_all_notifications_confirm_action">Hapus semua</string>
<string name="sk_settings_posting">Preferensi kiriman</string>
<string name="sk_settings_auth">Pengaturan keamanan</string>
<string name="sk_clear_all_notifications">Hapus semua notifikasi</string>
<string name="sk_undo_reblog">Urungkan pembagian</string>
<string name="sk_quote_post">Kirim tentang ini</string>
<string name="sk_reblog_with_visibility">Bagikan dengan keterlihatan</string>
<string name="sk_copy_link_to_post">Salin tautan ke kiriman</string>
<string name="sk_open_in_account">Buka di akun lain</string>
<string name="sk_hashtags_you_follow">Tagar yang Anda ikuti</string>
</resources>

View File

@@ -61,4 +61,25 @@
<string name="sk_welcome_text">상어가 당신을 맞이합니다! 시작하기 위해, 아래에 사용하시는 인스턴스의 도메인 이름을 입력해주세요.</string>
<string name="sk_color_palette_material3">시스템</string>
<string name="sk_color_palette_red">빨간색</string>
<string name="sk_settings_profile">프로필 설정</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>
<string name="sk_settings_about">이 앱에 관하여</string>
<string name="sk_settings_donate">기부</string>
<string name="sk_delete_notification_confirm_action">알림 삭제</string>
<string name="sk_delete_notification_confirm">정말로 이 알림을 삭제하시겠습니까\?</string>
<string name="sk_enable_delete_notifications">알림 삭제 활성화</string>
<string name="sk_settings_publish_button_text">게시 버튼 텍스트</string>
<string name="sk_settings_publish_button_text_title">게시 버튼 사용자화</string>
<string name="sk_settings_hide_translate_in_timeline">타임라인에서 번역 버튼 숨김</string>
<string name="sk_delete_notification">알림 삭제</string>
<string name="sk_settings_translation_availability_note_available">%s 서버는 번역을 지원합니다!</string>
<string name="sk_settings_translation_availability_note_unavailable">%s 서버는 번역을 지원하지 않는 것 같습니다.</string>
<string name="sk_clear_all_notifications_confirm">정말로 모든 알림을 삭제하시겠습니까\?</string>
<string name="sk_clear_all_notifications_confirm_action">모두 삭제</string>
<string name="sk_tabs_disable_swipe">스와이프로 탭간 전환 비활성화</string>
<string name="sk_clear_all_notifications">모든 알림 삭제</string>
<string name="sk_loading_fediverse_resource_title">연합우주에서 찾아보는 중…</string>
</resources>

View File

@@ -59,4 +59,30 @@
<string name="sk_example_domain">example.social</string>
<string name="sk_welcome_title">Вітаємо!</string>
<string name="sk_welcome_text">Акулка вас вітає! Щоб розпочати, введіть нижче доменне ім’я вашого інстансу.</string>
<string name="sk_settings_profile">Налаштувати профіль</string>
<string name="sk_settings_posting">Налаштувати постинг</string>
<string name="sk_settings_filters">Налаштувати фільтри</string>
<string name="sk_settings_rules">Правила</string>
<string name="sk_settings_about">Про застосунок</string>
<string name="sk_settings_donate">Донат</string>
<string name="sk_color_palette_material3">Системна</string>
<string name="sk_color_palette_red">Червона</string>
<string name="sk_delete_notification">Видалити сповіщення</string>
<string name="sk_delete_notification_confirm_action">Видалити</string>
<string name="sk_delete_notification_confirm">Ви впевнені, що хочете видалити це сповіщення\?</string>
<string name="sk_enable_delete_notifications">Увімкнути видалення сповіщень</string>
<string name="sk_settings_publish_button_text">Текст кнопки \"опублікувати\"</string>
<string name="sk_settings_publish_button_text_title">Змінити текст кнопки \"опублікувати\"</string>
<string name="sk_settings_hide_translate_in_timeline">Сховати кнопку \"перекласти\" у стрічці</string>
<string name="sk_settings_translation_availability_note_available">%s підтримує переклад!</string>
<string name="sk_settings_translation_availability_note_unavailable">%s не підтримує переклад.</string>
<string name="sk_clear_all_notifications">Очистити всі сповіщення</string>
<string name="sk_clear_all_notifications_confirm">Ви впевнені, що хочете очистити всі сповіщення\?</string>
<string name="sk_loading_fediverse_resource_title">Переглядаємо Федісвіт…</string>
<string name="sk_undo_reblog">Скасувати репост</string>
<string name="sk_reblog_with_visibility">Репост з видимістю</string>
<string name="sk_quote_post">Цитувати пост</string>
<string name="sk_tabs_disable_swipe">Вимкнути перегортання вкладок</string>
<string name="sk_settings_auth">Налаштування безпеці</string>
<string name="sk_clear_all_notifications_confirm_action">Видалити все</string>
</resources>

View File

@@ -47,4 +47,42 @@
<string name="sk_color_palette_yellow"></string>
<string name="sk_notification_type_status">嘟文</string>
<string name="sk_notify_posts">嘟文通知</string>
<string name="sk_translate_post">翻译</string>
<string name="sk_translate_show_original">显示原文</string>
<string name="sk_poll_allow_multiple">允许多选</string>
<string name="sk_welcome_text">鲨鱼向你致敬!要想开始,请在下面输入你的账户所在实例的域名。</string>
<string name="sk_welcome_title">欢迎!</string>
<string name="sk_clear_recent_languages">清除最近使用的语言</string>
<string name="sk_confirm_clear_recent_languages">您确定要清除最近使用的语言吗?</string>
<string name="sk_translated_using">使用 %s 翻译</string>
<string name="sk_post_language">语言: %s</string>
<string name="sk_available_languages">可用语言</string>
<string name="sk_language_name">%s (%s)</string>
<string name="sk_example_domain">example.social</string>
<string name="sk_tabs_disable_swipe">禁用选项卡之间的滑动</string>
<string name="sk_settings_profile">设置个人资料</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>
<string name="sk_settings_about">关于应用程序</string>
<string name="sk_settings_donate">捐赠</string>
<string name="sk_color_palette_material3">系统</string>
<string name="sk_color_palette_red"></string>
<string name="sk_delete_notification_confirm">您确定要删除此通知吗?</string>
<string name="sk_enable_delete_notifications">启用删除通知</string>
<string name="sk_delete_notification">删除通知</string>
<string name="sk_delete_notification_confirm_action">删除通知</string>
<string name="sk_settings_publish_button_text">发布按钮文本</string>
<string name="sk_settings_publish_button_text_title">自定义发布按钮文本</string>
<string name="sk_settings_hide_translate_in_timeline">在时间轴中隐藏翻译按钮</string>
<string name="sk_settings_translation_availability_note_available">%s 支持翻译!</string>
<string name="sk_settings_translation_availability_note_unavailable">%s 似乎不支持翻译。</string>
<string name="sk_clear_all_notifications">清除所有通知</string>
<string name="sk_clear_all_notifications_confirm_action">删除所有</string>
<string name="sk_clear_all_notifications_confirm">您确定要清除所有通知吗?</string>
<string name="sk_loading_fediverse_resource_title">在 Fediverse 上查找它……</string>
<string name="sk_undo_reblog">撤销转发</string>
<string name="sk_reblog_with_visibility">转发可见性</string>
<string name="sk_quote_post">关于这个嘟文</string>
</resources>

View File

@@ -82,5 +82,13 @@
<string name="sk_settings_hide_translate_in_timeline">Hide translate button in timeline</string>
<string name="sk_settings_translation_availability_note_available">%s supports translation!</string>
<string name="sk_settings_translation_availability_note_unavailable">%s does not appear to support translation.</string>
<string name="sk_loading_fediverse_resource_title">Looking it up on the Fediverse</string>
<string name="sk_loading_fediverse_resource_title">Looking it up on the Fediverse</string>
<string name="sk_loading_resource_on_instance_title">Looking it up on %s</string>
<string name="sk_undo_reblog">Undo reblog</string>
<string name="sk_reblog_with_visibility">Reblog with visibility</string>
<string name="sk_quote_post">Post about this</string>
<string name="sk_hashtags_you_follow">Hashtags you follow</string>
<string name="sk_copy_link_to_post">Copy link to post</string>
<string name="sk_open_with_account">Open with other account</string>
<string name="sk_resource_not_found">Resource could not be found</string>
</resources>

View File

@@ -307,7 +307,7 @@
<!-- colors -->
<item name="android:colorAccent">?colorPrimary700</item>
<item name="android:colorPrimary">?colorGray800</item>
<item name="android:colorBackground">?colorGray100</item>
<item name="android:colorBackground">?colorBackgroundPopup</item>
<item name="android:textColorPrimary">?colorGray800</item>
<item name="android:textColorSecondary">?colorGray500</item>
</style>
@@ -321,7 +321,7 @@
<!-- colors -->
<item name="android:colorAccent">?colorPrimary600</item>
<item name="android:colorPrimary">?colorGray50</item>
<item name="android:colorBackground">?colorGray700</item>
<item name="android:colorBackground">?colorBackgroundPopup</item>
<item name="android:textColorPrimary">?colorGray50</item>
<item name="android:textColorSecondary">?colorGray400</item>
</style>

View File

@@ -1,4 +1,4 @@
S'han preparat els fitxers per al llançament a F-Droid
S'ha solucionat l'actualització automàtica
S'han afegit icones monocromàtiques per a les icones del menú d'aplicacions
S'ha canviat la icona de «No llistat» incorrecta al peu de pàgina ampliat
- S'han preparat els fitxers per al llançament a F-Droid
- S'ha solucionat l'actualització automàtica
- S'han afegit icones monocromàtiques per a les icones del menú d'aplicacions
- S'ha canviat la icona de «No llistat» incorrecta al peu de pàgina ampliat

View File

@@ -1,6 +1,6 @@
És possible obrir la publicació original mentre respons (fent clic a la línia «En resposta a…»)
Ha combinat els canvis de la font superior i correccions d'errors
S'ha eliminat el codi «Centre d'aplicacions» no utilitzat
S'ha afegit una versió sense línia de temps federada per a la Play Store
S'ha afegit un URI de redirecció personalitzat per a facilitar l'inici de sessió
S'ha canviat l'enllaç de contribució
- És possible obrir la publicació original mentre respons (fent clic a la línia «En resposta a…»)
- Ha combinat els canvis de la font superior i correccions d'errors
- S'ha eliminat el codi «Centre d'aplicacions» no utilitzat
- S'ha afegit una versió sense línia de temps federada per a la Play Store
- S'ha afegit un URI de redirecció personalitzat per a facilitar l'inici de sessió
- S'ha canviat l'enllaç de contribució

View File

@@ -3,9 +3,9 @@
- Boost-Button gedrückt halten zum Drüber-Kommentieren
- Teilen-Button gedrückt halten, um den Link zu kopieren
- Benachrichtigungen löschen (standardmäßig deaktiviert)
- Extra Symbole für die einzelnen Benachrichtigungs-Typen
- Extra Symbole für Benachrichtigungs-Typen
- Neue Grautöne
- Einstellung, um Wischen zwischen Tabs auszuschalten
- Verschiedene Links zu Kontoeinstellungen hinzugefügt
- Einstellung, um den Übersetzen-Button in der Timeline zu verbergen/anzuzeigen
- Fehlerbehebungen und Anpassungen
- Wischen zwischen Tabs ausschaltbar
- Links zu Kontoeinstellungen hinzugefügt
- Einstellung, um den Übersetzen-Button in der Timeline anzuzeigen
- Fehlerbehebungen

View File

@@ -0,0 +1,6 @@
- Option zum Auswählen der Sichtbarkeit durch Gedrückthalten des Reblog-Buttons
- Sichtbarkeit eigener Reblogs wird nun angezeigt
- Liste der gefolgten Hashtags hinzugefügt
- Links gedrückt halten, um sie zu kopieren
- Option, um Beiträge mit einem anderen Konto zu öffnen
- Fehlerbehebungen und kleinere Tweaks

View File

@@ -0,0 +1,6 @@
- Option to reblog with specific visibility on long-click
- Show visibility of own reblogs
- Add list of followed hashtags
- Long-click to copy links
- Option to open posts with other account
- Bugfixes and minor tweaks

View File

@@ -1,4 +1,4 @@
Se han preparado los archivos para el lanzamiento en F-Droid
Se ha solucionado la actualización automática
Se han añadido iconos monocromáticos para los iconos del menú de aplicaciones
Se ha cambiado el icono de «No listado» incorrecto en el pie de página ampliado
- Se han preparado los archivos para el lanzamiento en F-Droid
- Se ha solucionado la actualización automática
- Se han añadido iconos monocromáticos para los iconos del menú de aplicaciones
- Se ha cambiado el icono de «No listado» incorrecto en el pie de página ampliado

View File

@@ -1,6 +1,6 @@
Es posible abrir la publicación original mientras respondes (haciendo clic en la línea "En respuesta a…")
Ha combinado los cambios de la fuente superior y correcciones de errores
Se ha eliminado el código "Centro de aplicaciones" no utilizado
Se ha añadido una versión sin línea de tiempo federada para Play Store
Se ha añadido un URI de redirección personalizado para facilitar el inicio de sesión
Se ha cambiado el enlace de las contribuciones
- Es posible abrir la publicación original mientras respondes (haciendo clic en la línea "En respuesta a…")
- Ha combinado los cambios de la fuente superior y correcciones de errores
- Se ha eliminado el código "Centro de aplicaciones" no utilizado
- Se ha añadido una versión sin línea de tiempo federada para Play Store
- Se ha añadido un URI de redirección personalizado para facilitar el inicio de sesión
- Se ha cambiado el enlace de las contribuciones

View File

@@ -1,9 +1,11 @@
- Copiar la URL de la entrada al pulsar prolongadamente el botón de compartir
- Añadir la opción de desactivar el deslizamiento entre pestañas
- Nuevos colores grises
- Eliminar notificaciones (desactivado por defecto)
- Añadir varios enlaces a la configuración de la cuenta
- Botón de publicación personalizable
- Abrir enlaces de Fediverse en la aplicación
- Botón boost de pulsación larga para "citar" un post
- Copiar la URL de la publicación al pulsar prolongadamente el botón de compartir
- Implementar la eliminación de notificaciones (desactivada por defecto)
- Iconos específicos para los distintos tipos de notificaciones
- Nuevos colores grises
- Añadir la opción de desactivar el deslizamiento entre pestañas.
- Añadir varios enlaces a la configuración de la cuenta
- Mostrar/ocultar el botón de traducción en la línea de tiempo
- Corrección de errores y ajustes (botón Marcador, animaciones de los botones)
- Corrección de errores y ajustes

View File

@@ -1,9 +1,11 @@
- Copier l'URL du post avec un appuis long sur le bouton de partage
- Ajout d'une option pour désactiver le balayage entre les onglets
- Bouton Publier perso.
- Ouverture des liens Fediverse dans l'application
- Clic long sur le bouton boost pour citer un message
- Copier l'URL du post avec appuis long sur le bouton de partage
- Ajout de la suppr. des notifs.
- Icônes pour différents types de notification
- Nouvelles couleurs grises
- Ajout de la suppression des notifications
- Ajout de divers liens vers les paramètres du compte
- Bouton Publier personnalisable
- Icônes dédiées pour différents types de notification
- Possibilité de désactiver le balayage entre les onglets
- Ajout de liens vers les paramètres du compte
- Option pour afficher/masquer le bouton de traduction dans la timeline
- Corrections de bugs et ajustements (bouton de signet, animations de bouton)
- Correction de bugs

View File

@@ -0,0 +1,3 @@
- Rebloguer avec une visibilité spécifique sur clic long
- Liste des hashtags suivis
- Cliquez longuement sur les liens pour les copier

View File

@@ -0,0 +1,5 @@
- Tema warna baru: Material You dan Merah
- Tanda abu-abu gelap baru untuk semua tema
- Ikon bagikan lebih jelas
- Animasi untuk tombol interaksi
- Perbaikan kutu (Mogok pada beberapa kiriman, "Daftar dengan", bahasa kiriman bawaan)

View File

@@ -0,0 +1,11 @@
- Tombol Terbitkan dapat diubah
- Buka tautan Fedimesta dlm aplikasi
- Klik lama pada tombol boost utk "mengutip" kiriman
- Salin URL kiriman ketika menekan lama pada tombol bagikan
- Terapkan penghapusan notifikasi (dinonaktifkan secara bawaan)
- Ikon tersendiri utk jenis notifikasi berbeda
- Warna abu-abu baru
- Tambah pengaturan utk menonaktifkan pengusapan antara tab
- Tambah tautan ke pengaturan akun
- Saklar menampilkan/menyembunyikan tombol terjemahkan dalam lini masa
- Banyak perbaikan

View File

@@ -0,0 +1,3 @@
- Bagikan dengan keterlihatan khusu pada klik lama
- Daftar tagar yang diikuti
- Klik lama pada tautan untuk menyalinnya

View File

@@ -0,0 +1,5 @@
- 새로운 색상 테마: Material You와 빨간색
- 모든 테마에 새로운 회색 톤 적용
- 부스트 아이콘을 더 뚜렷하게 채움
- 반응 버튼에 애니메이션 적용
- 버그 수정 (일부 게시물로 인한 오류, "...님이 포함된 리스트", 기본 게시물 언어)

View File

@@ -0,0 +1,11 @@
- 게시 버튼을 커스텀 가능함
- 연합우주 링크를 앱으로 열 수 있음
- 부스트 버튼을 길게 눌러 게시물 "인용"
- 공유 버튼을 길게 눌러 게시물 URL 복사
- 알림 삭제 기능 추가 (기본적으로 비활성화)
- 서로 다른 알림 유형에 따라 다르게 표시되는 아이콘
- 새로운 회색 색상 적용
- 스와이프로 탭간 전환할 수 있는 기능 비활성화 설정 추가
- 계정 설정과 관련된 여러 링크 추가
- 번역 버튼을 타임라인에 표시하거나 숨길 수 있는 설정 추가
- 버그 수정 및 개선

View File

@@ -0,0 +1,5 @@
- Нові колірні теми: Material You й Червона
- Нові темно-сірі тони для всіх тем
- Більш виразний заповнений значок репоста
- Анімації для кнопок взаємодій
- Виправлення багів (виліт на деякіх постах, тощо)

View File

@@ -0,0 +1,4 @@
- 准备文件以便在F-Droid上发布
- 修复自动更新程序
- 将单色图标重新添加到启动器图标
- 替换发布页脚中错误的不公开图标

View File

@@ -0,0 +1,6 @@
- 使得在回复时可以打开原帖(通过点击 "回复...... "一行)。
- 合并上游的修改和错误修正
- 删除未使用的 "App Center" 代码
- 为Play Store添加没有联邦时间轴的版本
- 添加自定义重定向URI以方便登录
- 更改贡献链接

View File

@@ -0,0 +1,4 @@
- 修复损坏的 HTML 标签并启用以 Markdown 格式呈现
- 初始化 <a href="https://translate.codeberg.org/projects/megalodon">Weblate 翻译项目</a>
- 为联邦时间线添加切换
- 版本 52-54 是针对 Google Play 版本的小幅调整

View File

@@ -0,0 +1,6 @@
- @LucasGGamerM 自定义颜色主题
- 由@LucasGGamerM 提交的新“megalodon”文字标识
- 创作时更好的表情符号搜索
- 调整投票(显示自己的投票,始终显示投票按钮,不要切断长答案)
- 为嘟文通知添加推送通知设置
- Bug修复

View File

@@ -0,0 +1,6 @@
- 添加语言选择器
- 添加翻译功能
- 改进投票投票的语义(单选按钮和复选框)
- 添加选项以允许对民意调查中的多个选项进行投票
- 新的登录屏幕
- Bug修复

View File

@@ -0,0 +1,5 @@
- 新的颜色主题Material You 和 红
- 所有主题的新深灰色调
- 更明显的填充提升图标
- 交互按钮的动画
- 错误修正(某些嘟文崩溃,“列表为”,默认发布语言)

View File

@@ -0,0 +1,11 @@
- 可定制的发布按钮
- 在应用程序中打开 Fediverse 链接
- 长按转发按钮以“引用”嘟文
- 长按分享按钮时复制帖子网址
- 实施删除通知(默认禁用)
- 不同通知类型的专用图标
- 新的灰色
- 添加设置以禁用选项卡之间的滑动
- 添加各种链接到帐户设置
- 切换显示/隐藏时间轴中的翻译按钮
- 错误修正和调整

View File

@@ -0,0 +1,15 @@
Megalodon 是<a href="https://github.com/mastodon/mastodon-android">官方 Mastodon Android 应用</a>的修改版本,添加了官方应用中缺少的重要功能,例如联合时间轴、不公开的帖子和图像描述查看器。
<b>主要特点</b>
- <b>不公开的帖子</b>:公开发布而不让您的帖子出现在趋势、标签或公共时间轴中。
- <b>联邦时间轴</b>:查看您的实例连接到的所有其他 Fediverse 社区的人们的所有公开帖子。
- <b>图片描述查看器</b>:快速检查图片或视频是否附加了替代文字。
- <b>置顶帖子</b>:将您最重要的帖子置顶到您的个人资料,并使用“置顶”选项卡查看其他人固定的内容。
- <b>关注话题标签</b>:通过关注直接在您的主页时间线中查看来自特定话题标签的新帖子。
- <b>回应关注请求</b>:接受或拒绝来自您的通知或专用关注请求列表的关注请求。
- <b>删除和重新起草</b>:这个备受喜爱的功能使编辑成为可能,而无需实际的编辑功能。
- <b>语言选择器</b>:为您发布的每个帖子轻松选择语言,以便过滤器和翻译正常工作。
- <b>翻译</b>:在 Megalodon 内轻松翻译帖子! 该功能仅在在您的 Mastodon Web 上也可用时才有效。
- <b>帖子可见性指示器</b>:打开或回复帖子时,将显示一个指示帖子可见性的便捷图标。
- <b>颜色主题</b>如果您不喜欢默认的粉红色鲨鱼在默默地评判您Moshidon 的颜色主题可以满足您的需求。