Compare commits
108 Commits
v2.1.6+for
...
v2.1.6+for
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20039ec97e | ||
|
|
172d25eeb0 | ||
|
|
fa04e00032 | ||
|
|
3ff442894d | ||
|
|
edb0823bf9 | ||
|
|
9de83355e1 | ||
|
|
183fb0e8c0 | ||
|
|
d624a04e18 | ||
|
|
303461d803 | ||
|
|
11c7816bb1 | ||
|
|
b5eae13a16 | ||
|
|
59026286a1 | ||
|
|
ef0fbb26a4 | ||
|
|
387b31193f | ||
|
|
95fa547f15 | ||
|
|
3198c9adb1 | ||
|
|
e1af6f4643 | ||
|
|
cc52e491b0 | ||
|
|
b0db0d9f2e | ||
|
|
d699788a12 | ||
|
|
bdbf441e1a | ||
|
|
0deba2885b | ||
|
|
48b39fd3bc | ||
|
|
875b235e6d | ||
|
|
1711682322 | ||
|
|
70f5ec7500 | ||
|
|
d34c73c210 | ||
|
|
50a0586e8a | ||
|
|
1d2ca1e500 | ||
|
|
34b7123a8d | ||
|
|
ec718ff58e | ||
|
|
20a442e27f | ||
|
|
47cb74abc9 | ||
|
|
a11e53c89a | ||
|
|
d721e8ca46 | ||
|
|
23e5dcd030 | ||
|
|
25dd2cfab8 | ||
|
|
8537c7a7ae | ||
|
|
ebd7f9c36c | ||
|
|
49cda3aeb2 | ||
|
|
67cbc8aff2 | ||
|
|
5db44cbf9d | ||
|
|
95858e3280 | ||
|
|
36846acbe5 | ||
|
|
b95d944003 | ||
|
|
f52886af74 | ||
|
|
6cbe406cef | ||
|
|
3097bc7168 | ||
|
|
5f7faa69e8 | ||
|
|
ed24e89a96 | ||
|
|
8ea05c6ebd | ||
|
|
a30fcbbe34 | ||
|
|
39f76f9988 | ||
|
|
5135653cd3 | ||
|
|
2e4f04cd88 | ||
|
|
a44e0e036a | ||
|
|
5d54c1bae4 | ||
|
|
09577074a9 | ||
|
|
53f0e2a933 | ||
|
|
b8dccbbef1 | ||
|
|
2ef17ba051 | ||
|
|
f63daf3a4e | ||
|
|
52b079be2a | ||
|
|
efeca17106 | ||
|
|
6827166c1d | ||
|
|
04483e61e8 | ||
|
|
22fe174922 | ||
|
|
f143da3913 | ||
|
|
7e9f41c74b | ||
|
|
a1474d0d29 | ||
|
|
0dce936ad3 | ||
|
|
6ebbbb4c6c | ||
|
|
dc6ddbd0ee | ||
|
|
86c81d6b53 | ||
|
|
451a92aa36 | ||
|
|
5c42e67e73 | ||
|
|
d20d36d964 | ||
|
|
1a8d46c71e | ||
|
|
91da10eca3 | ||
|
|
3bb0dcee53 | ||
|
|
d3fd4b200f | ||
|
|
fed96864e1 | ||
|
|
3b351bea27 | ||
|
|
254e01dca1 | ||
|
|
19158e1d48 | ||
|
|
bffb78fccf | ||
|
|
a3800592a2 | ||
|
|
22a498dfc9 | ||
|
|
9ea96e32bd | ||
|
|
68f51a123e | ||
|
|
43b1b63581 | ||
|
|
43b4a2c515 | ||
|
|
5b9cfdb689 | ||
|
|
b43cd7103a | ||
|
|
30e4f6e0f5 | ||
|
|
1d0ebf889b | ||
|
|
7c4f1da485 | ||
|
|
8163921014 | ||
|
|
993393dd96 | ||
|
|
82aed43934 | ||
|
|
fa65134c26 | ||
|
|
af4266c739 | ||
|
|
f72ea2e763 | ||
|
|
c5540270a3 | ||
|
|
5840c94395 | ||
|
|
92d7ae67ef | ||
|
|
fc09514a4d | ||
|
|
300fa97781 |
@@ -15,8 +15,8 @@ android {
|
||||
applicationId "org.joinmastodon.android.sk"
|
||||
minSdk 23
|
||||
targetSdk 33
|
||||
versionCode 105
|
||||
versionName "2.1.6+fork.105"
|
||||
versionCode 107
|
||||
versionName "2.1.6+fork.107"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
resourceConfigurations += ['ar-rSA', 'ar-rDZ', 'be-rBY', 'bn-rBD', 'bs-rBA', 'ca-rES', 'cs-rCZ', 'da-rDK', 'de-rDE', 'el-rGR', 'es-rES', 'eu-rES', 'fa-rIR', 'fi-rFI', 'fil-rPH', 'fr-rFR', 'ga-rIE', 'gd-rGB', 'gl-rES', 'hi-rIN', 'hr-rHR', 'hu-rHU', 'hy-rAM', 'ig-rNG', 'in-rID', 'is-rIS', 'it-rIT', 'iw-rIL', 'ja-rJP', 'kab', 'ko-rKR', 'my-rMM', 'nl-rNL', 'no-rNO', 'oc-rFR', 'pl-rPL', 'pt-rBR', 'pt-rPT', 'ro-rRO', 'ru-rRU', 'si-rLK', 'sl-rSI', 'sv-rSE', 'th-rTH', 'tr-rTR', 'uk-rUA', 'ur-rIN', 'vi-rVN', 'zh-rCN', 'zh-rTW']
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ public class AudioPlayerService extends Service{
|
||||
private void updateNotification(boolean dismissable, boolean removeNotification){
|
||||
Notification.Builder bldr=new Notification.Builder(this)
|
||||
.setSmallIcon(R.drawable.ic_ntf_logo)
|
||||
.setContentTitle(status.account.displayName)
|
||||
.setContentTitle(status.account.getDisplayName())
|
||||
.setContentText(HtmlParser.strip(status.content))
|
||||
.setOngoing(!dismissable)
|
||||
.setShowWhen(false)
|
||||
|
||||
@@ -120,6 +120,8 @@ public class CacheController{
|
||||
values.put("time", s.createdAt.getEpochSecond());
|
||||
db.insertWithOnConflict("home_timeline", null, values, SQLiteDatabase.CONFLICT_REPLACE);
|
||||
}
|
||||
if(!clear)
|
||||
db.delete("home_timeline", "`id` NOT IN (SELECT `id` FROM `home_timeline` ORDER BY `time` DESC LIMIT ?)", new String[]{"100"});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -53,9 +53,7 @@ public class MastodonAPIController{
|
||||
.registerTypeAdapter(Status.class, new Status.StatusDeserializer())
|
||||
.create();
|
||||
private static WorkerThread thread=new WorkerThread("MastodonAPIController");
|
||||
private static OkHttpClient httpClient=new OkHttpClient.Builder()
|
||||
.readTimeout(5, TimeUnit.MINUTES)
|
||||
.build();
|
||||
private static OkHttpClient httpClient=new OkHttpClient.Builder().build();
|
||||
|
||||
private AccountSession session;
|
||||
private static List<String> badDomains = new ArrayList<>();
|
||||
@@ -113,13 +111,13 @@ public class MastodonAPIController{
|
||||
}
|
||||
|
||||
Request hreq=builder.build();
|
||||
Call call=httpClient.newCall(hreq);
|
||||
OkHttpClient client=req.timeout>0
|
||||
? httpClient.newBuilder().readTimeout(req.timeout, TimeUnit.MILLISECONDS).build()
|
||||
: httpClient;
|
||||
Call call=client.newCall(hreq);
|
||||
synchronized(req){
|
||||
req.okhttpCall=call;
|
||||
}
|
||||
if(req.timeout>0){
|
||||
call.timeout().timeout(req.timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
if(BuildConfig.DEBUG)
|
||||
Log.d(TAG, "["+(session==null ? "no-auth" : session.getID())+"] Sending request: "+hreq);
|
||||
|
||||
@@ -153,8 +153,9 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
|
||||
headers.put(key, value);
|
||||
}
|
||||
|
||||
protected void setTimeout(long timeout){
|
||||
public MastodonAPIRequest<T> setTimeout(long timeout){
|
||||
this.timeout=timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected String getPathPrefix(){
|
||||
|
||||
@@ -218,7 +218,7 @@ public class AccountSession{
|
||||
|
||||
public void savePreferencesIfPending(){
|
||||
if(preferencesNeedSaving){
|
||||
new UpdateAccountCredentialsPreferences(preferences, null, self.discoverable, self.source.indexable)
|
||||
new UpdateAccountCredentialsPreferences(preferences, self.locked, self.discoverable, self.source.indexable)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(Account result){
|
||||
|
||||
@@ -9,5 +9,6 @@ public class StatusCreatedEvent{
|
||||
public StatusCreatedEvent(Status status, String accountID){
|
||||
this.status=status;
|
||||
this.accountID=accountID;
|
||||
status.fromStatusCreated=true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
|
||||
public LinearLayout mainLayout;
|
||||
private SizeListenerLinearLayout contentView;
|
||||
private TextView selfName, selfUsername, selfExtraText, extraText, pronouns;
|
||||
private TextView selfName, selfUsername, selfExtraText, extraText;
|
||||
private ImageView selfAvatar;
|
||||
private Account self;
|
||||
private String instanceDomain;
|
||||
@@ -326,7 +326,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
selfUsername=view.findViewById(R.id.self_username);
|
||||
selfAvatar=view.findViewById(R.id.self_avatar);
|
||||
selfExtraText=view.findViewById(R.id.self_extra_text);
|
||||
HtmlParser.setTextWithCustomEmoji(selfName, self.displayName, self.emojis);
|
||||
HtmlParser.setTextWithCustomEmoji(selfName, self.getDisplayName(), self.emojis);
|
||||
selfUsername.setText('@'+self.username+'@'+instanceDomain);
|
||||
if(self.avatar!=null)
|
||||
ViewImageLoader.load(selfAvatar, null, new UrlImageLoaderRequest(self.avatar));
|
||||
@@ -626,7 +626,6 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
});
|
||||
View originalPost=view.findViewById(R.id.original_post);
|
||||
extraText=view.findViewById(R.id.extra_text);
|
||||
pronouns=view.findViewById(R.id.pronouns);
|
||||
originalPost.setVisibility(View.VISIBLE);
|
||||
originalPost.setOnClickListener(v->{
|
||||
Bundle args=new Bundle();
|
||||
@@ -666,7 +665,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
moreBtn.setBackground(null);
|
||||
|
||||
TextView name = view.findViewById(R.id.name);
|
||||
name.setText(HtmlParser.parseCustomEmoji(status.account.displayName, status.account.emojis));
|
||||
name.setText(HtmlParser.parseCustomEmoji(status.account.getDisplayName(), status.account.emojis));
|
||||
UiUtils.loadCustomEmojiInTextView(name);
|
||||
|
||||
String time = status==null || status.editedAt==null
|
||||
@@ -700,7 +699,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(16)));
|
||||
}
|
||||
|
||||
replyText.setText(getString(quote!=null? R.string.sk_quoting_user : R.string.in_reply_to, status.account.displayName));
|
||||
replyText.setText(getString(quote!=null? R.string.sk_quoting_user : R.string.in_reply_to, status.account.getDisplayName()));
|
||||
int visibilityNameRes = switch (status.visibility) {
|
||||
case PUBLIC -> R.string.visibility_public;
|
||||
case UNLISTED -> R.string.sk_visibility_unlisted;
|
||||
@@ -708,7 +707,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
case DIRECT -> R.string.visibility_private;
|
||||
case LOCAL -> R.string.sk_local_only;
|
||||
};
|
||||
replyText.setContentDescription(getString(R.string.in_reply_to, status.account.displayName) + ", " + getString(visibilityNameRes));
|
||||
replyText.setContentDescription(getString(R.string.in_reply_to, status.account.getDisplayName()) + ", " + getString(visibilityNameRes));
|
||||
replyText.setOnClickListener(v->{
|
||||
scrollView.smoothScrollTo(0, 0);
|
||||
});
|
||||
@@ -1455,8 +1454,8 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
}
|
||||
|
||||
private void updateHeaders() {
|
||||
UiUtils.setExtraTextInfo(getContext(), selfExtraText, null, false, false, localOnly || statusVisibility==StatusPrivacy.LOCAL, null);
|
||||
if (replyTo != null) UiUtils.setExtraTextInfo(getContext(), extraText, pronouns, true, false, replyTo.localOnly || replyTo.visibility==StatusPrivacy.LOCAL, replyTo.account);
|
||||
UiUtils.setExtraTextInfo(getContext(), selfExtraText, false, false, localOnly, null);
|
||||
if (replyTo != null) UiUtils.setExtraTextInfo(getContext(), extraText, true, false, replyTo.localOnly || replyTo.visibility==StatusPrivacy.LOCAL, replyTo.account);
|
||||
}
|
||||
|
||||
private void buildVisibilityPopup(View v){
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.joinmastodon.android.api.requests.accounts.GetFollowRequests;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.HeaderPaginationList;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.Relationship;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
@@ -271,7 +270,7 @@ public class FollowRequestsListFragment extends MastodonRecyclerFragment<FollowR
|
||||
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
relationship=relationships.get(item.account.id);
|
||||
UiUtils.setExtraTextInfo(getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
|
||||
UiUtils.setExtraTextInfo(getContext(), null, true, false, false, item.account);
|
||||
|
||||
if(relationship==null || !relationship.followedBy){
|
||||
actionWrap.setVisibility(View.GONE);
|
||||
@@ -366,9 +365,9 @@ public class FollowRequestsListFragment extends MastodonRecyclerFragment<FollowR
|
||||
coverRequest=new UrlImageLoaderRequest(account.header, 1000, 1000);
|
||||
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
||||
if(account.emojis.isEmpty()){
|
||||
parsedName=account.displayName;
|
||||
parsedName= account.getDisplayName();
|
||||
}else{
|
||||
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
|
||||
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
|
||||
emojiHelper.setText(new SpannableStringBuilder(parsedName).append(parsedBio));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import org.joinmastodon.android.events.NotificationsMarkerUpdatedEvent;
|
||||
import org.joinmastodon.android.events.StatusDisplaySettingsChangedEvent;
|
||||
import org.joinmastodon.android.fragments.discover.DiscoverFragment;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.Notification;
|
||||
import org.joinmastodon.android.model.PaginatedResponse;
|
||||
import org.joinmastodon.android.ui.AccountSwitcherSheet;
|
||||
@@ -71,14 +70,12 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
|
||||
private TextView notificationsBadge;
|
||||
|
||||
private String accountID;
|
||||
private boolean isAkkoma;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
accountID=getArguments().getString("account");
|
||||
setTitle(R.string.sk_app_name);
|
||||
isAkkoma = getInstance().map(Instance::isAkkoma).orElse(false);
|
||||
|
||||
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
|
||||
setRetainInstance(true);
|
||||
@@ -89,7 +86,6 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
|
||||
homeTabFragment=new HomeTabFragment();
|
||||
homeTabFragment.setArguments(args);
|
||||
args=new Bundle(args);
|
||||
args.putBoolean("disableDiscover", isAkkoma);
|
||||
args.putBoolean("noAutoLoad", true);
|
||||
discoverFragment=new DiscoverFragment();
|
||||
discoverFragment.setArguments(args);
|
||||
@@ -296,7 +292,7 @@ public class HomeFragment extends AppKitFragment implements OnBackPressedListene
|
||||
if(tab==R.id.tab_profile){
|
||||
ArrayList<String> options=new ArrayList<>();
|
||||
for(AccountSession session:AccountSessionManager.getInstance().getLoggedInAccounts()){
|
||||
options.add(session.self.displayName+"\n("+session.self.username+"@"+session.domain+")");
|
||||
options.add(session.self.getDisplayName()+"\n("+session.self.username+"@"+session.domain+")");
|
||||
}
|
||||
new AccountSwitcherSheet(getActivity(), this).show();
|
||||
return true;
|
||||
|
||||
@@ -233,21 +233,25 @@ public class HomeTabFragment extends MastodonToolbarFragment implements Scrollab
|
||||
|
||||
ViewTreeObserver vto = getToolbar().getViewTreeObserver();
|
||||
if (vto.isAlive()) {
|
||||
vto.addOnGlobalLayoutListener(() -> {
|
||||
Toolbar t = getToolbar();
|
||||
if (t == null) return;
|
||||
int toolbarWidth = t.getWidth();
|
||||
if (toolbarWidth == 0) return;
|
||||
vto.addOnGlobalLayoutListener(()->{
|
||||
Toolbar t=getToolbar();
|
||||
if(t==null) return;
|
||||
int toolbarWidth=t.getWidth();
|
||||
if(toolbarWidth==0) return;
|
||||
|
||||
int toolbarFrameWidth = toolbarFrame.getWidth();
|
||||
int padding = toolbarWidth - toolbarFrameWidth;
|
||||
FrameLayout parent = ((FrameLayout) toolbarShowNewPostsBtn.getParent());
|
||||
if (padding == parent.getPaddingStart()) return;
|
||||
int toolbarFrameWidth=toolbarFrame.getWidth();
|
||||
int actionsWidth=toolbarWidth-toolbarFrameWidth;
|
||||
// margin (4) + padding (12) + icon (24) + margin (8) + chevron (16) + padding (12)
|
||||
int switcherWidth=V.dp(76);
|
||||
FrameLayout parent=((FrameLayout) toolbarShowNewPostsBtn.getParent());
|
||||
if(actionsWidth==parent.getPaddingStart()) return;
|
||||
int paddingMax=Math.max(actionsWidth, switcherWidth);
|
||||
int paddingEnd=(Math.max(0, switcherWidth-actionsWidth));
|
||||
|
||||
// toolbar frame goes from screen edge to beginning of right-aligned option buttons.
|
||||
// centering button by applying the same space on the left
|
||||
parent.setPaddingRelative(padding, 0, 0, 0);
|
||||
toolbarShowNewPostsBtn.setMaxWidth(toolbarWidth - padding * 2);
|
||||
parent.setPaddingRelative(paddingMax, 0, paddingEnd, 0);
|
||||
toolbarShowNewPostsBtn.setMaxWidth(toolbarWidth-paddingMax*2);
|
||||
|
||||
switcher.setPivotX(V.dp(28)); // padding + half of icon
|
||||
switcher.setPivotY(switcher.getHeight() / 2f);
|
||||
|
||||
@@ -61,7 +61,7 @@ public class HomeTimelineFragment extends StatusListFragment {
|
||||
maxID=result.maxID;
|
||||
AccountSessionManager.get(accountID).filterStatuses(result.items, getFilterContext());
|
||||
onDataLoaded(result.items, !empty);
|
||||
if(result.isFromCache())
|
||||
if(result.isFromCache() && GlobalUserPreferences.loadNewPosts)
|
||||
loadNewPosts();
|
||||
}
|
||||
});
|
||||
@@ -74,7 +74,7 @@ public class HomeTimelineFragment extends StatusListFragment {
|
||||
list.addOnScrollListener(new RecyclerView.OnScrollListener(){
|
||||
@Override
|
||||
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy){
|
||||
if(parent != null && parent.isNewPostsBtnShown() && list.getChildAdapterPosition(list.getChildAt(0))<=getMainAdapterOffset()){
|
||||
if(parent!=null && parent.isNewPostsBtnShown() && list.getChildAdapterPosition(list.getChildAt(0))<=getMainAdapterOffset()){
|
||||
parent.hideNewPostsButton();
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ public class HomeTimelineFragment extends StatusListFragment {
|
||||
if(!getArguments().getBoolean("noAutoLoad")){
|
||||
if(!loaded && !dataLoading){
|
||||
loadData();
|
||||
}else if(!dataLoading){
|
||||
}else if(!dataLoading && GlobalUserPreferences.loadNewPosts){
|
||||
loadNewPosts();
|
||||
}
|
||||
}
|
||||
@@ -117,48 +117,54 @@ public class HomeTimelineFragment extends StatusListFragment {
|
||||
}
|
||||
|
||||
public void onStatusCreated(Status status){
|
||||
if(status.reblog!=null) return;
|
||||
prependItems(Collections.singletonList(status), true);
|
||||
}
|
||||
|
||||
private void loadNewPosts(){
|
||||
if (!GlobalUserPreferences.loadNewPosts) return;
|
||||
dataLoading=true;
|
||||
// we only care about the data that was actually retrieved from the timeline api since
|
||||
// user-created statuses are probably in the wrong position
|
||||
List<Status> dataFromTimeline=data.stream().filter(s->!s.fromStatusCreated).collect(Collectors.toList());
|
||||
// The idea here is that we request the timeline such that if there are fewer than `limit` posts,
|
||||
// we'll get the currently topmost post as last in the response. This way we know there's no gap
|
||||
// between the existing and newly loaded parts of the timeline.
|
||||
String sinceID=data.size()>1 ? data.get(1).id : "1";
|
||||
String sinceID=dataFromTimeline.size()>1 ? dataFromTimeline.get(1).id : "1";
|
||||
currentRequest=new GetHomeTimeline(null, null, 20, sinceID, getLocalPrefs().timelineReplyVisibility)
|
||||
.setCallback(new Callback<>(){
|
||||
@Override
|
||||
public void onSuccess(List<Status> result){
|
||||
currentRequest=null;
|
||||
dataLoading=false;
|
||||
refreshDone();
|
||||
if(result.isEmpty() || getActivity()==null)
|
||||
return;
|
||||
Status last=result.get(result.size()-1);
|
||||
List<Status> toAdd;
|
||||
if(!data.isEmpty() && last.id.equals(data.get(0).id)){ // This part intersects with the existing one
|
||||
if(!dataFromTimeline.isEmpty() && last.id.equals(dataFromTimeline.get(0).id)){ // This part intersects with the existing one
|
||||
toAdd=new ArrayList<>(result.subList(0, result.size()-1)); // Remove the already known last post
|
||||
}else{
|
||||
last.hasGapAfter=last.id;
|
||||
toAdd=result;
|
||||
}
|
||||
if(!toAdd.isEmpty())
|
||||
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(new ArrayList<>(toAdd), false);
|
||||
// removing statuses that come up as duplicates (hopefully only posts and boosts that were locally created
|
||||
// and thus were already prepended to the timeline earlier)
|
||||
List<String> existingIds=data.stream().map(Status::getID).collect(Collectors.toList());
|
||||
toAdd.removeIf(s->existingIds.contains(s.getID()));
|
||||
List<Status> toAddUnfiltered=new ArrayList<>(toAdd);
|
||||
AccountSessionManager.get(accountID).filterStatuses(toAdd, getFilterContext());
|
||||
if(!toAdd.isEmpty()){
|
||||
prependItems(toAdd, true);
|
||||
if(parent != null && GlobalUserPreferences.showNewPostsButton) parent.showNewPostsButton();
|
||||
}
|
||||
if(toAddUnfiltered.isEmpty())
|
||||
AccountSessionManager.getInstance().getAccount(accountID).getCacheController().putHomeTimeline(toAddUnfiltered, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
currentRequest=null;
|
||||
dataLoading=false;
|
||||
refreshDone();
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
@@ -325,8 +331,8 @@ public class HomeTimelineFragment extends StatusListFragment {
|
||||
currentRequest=null;
|
||||
dataLoading=false;
|
||||
}
|
||||
if (parent != null) parent.hideNewPostsButton();
|
||||
super.onRefresh();
|
||||
if(parent!=null) parent.hideNewPostsButton();
|
||||
loadNewPosts();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -621,14 +621,14 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
private void bindHeaderView(){
|
||||
setTitle(account.displayName);
|
||||
setTitle(account.getDisplayName());
|
||||
setSubtitle(getResources().getQuantityString(R.plurals.x_posts, (int)(account.statusesCount%1000), account.statusesCount));
|
||||
ViewImageLoader.load(avatar, null, new UrlImageLoaderRequest(
|
||||
TextUtils.isEmpty(account.avatar) ? getSession().getDefaultAvatarUrl() :
|
||||
GlobalUserPreferences.playGifs ? account.avatar : account.avatarStatic,
|
||||
V.dp(100), V.dp(100)));
|
||||
ViewImageLoader.load(cover, null, new UrlImageLoaderRequest(GlobalUserPreferences.playGifs ? account.header : account.headerStatic, 1000, 1000));
|
||||
SpannableStringBuilder ssb=new SpannableStringBuilder(account.displayName);
|
||||
SpannableStringBuilder ssb=new SpannableStringBuilder(account.getDisplayName());
|
||||
if(AccountSessionManager.get(accountID).getLocalPreferences().customEmojiInNames)
|
||||
HtmlParser.parseCustomEmoji(ssb, account.emojis);
|
||||
name.setText(ssb);
|
||||
|
||||
@@ -9,6 +9,7 @@ import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.joinmastodon.android.E;
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.api.CacheController;
|
||||
import org.joinmastodon.android.api.session.AccountLocalPreferences;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.events.EmojiReactionsUpdatedEvent;
|
||||
@@ -31,6 +32,10 @@ import org.parceler.Parcels;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -176,56 +181,71 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>
|
||||
}
|
||||
}
|
||||
|
||||
private void iterateRemoveStatus(List<Status> l, String id){
|
||||
Iterator<Status> it=l.iterator();
|
||||
while(it.hasNext()){
|
||||
if(it.next().getContentStatus().id.equals(id)){
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void removeStatusDisplayItems(Status status, int index, int ancestorFirstIndex, int ancestorLastIndex, boolean deleteContent){
|
||||
private boolean removeStatusDisplayItems(String parentID, int firstIndex, int ancestorFirstIndex, int ancestorLastIndex){
|
||||
// did we find an ancestor that is also the status' neighbor?
|
||||
if(ancestorFirstIndex>=0 && ancestorLastIndex==index-1){
|
||||
for(int i=ancestorFirstIndex; i<=ancestorLastIndex; i++){
|
||||
StatusDisplayItem item=displayItems.get(i);
|
||||
String id=deleteContent ? item.getContentID() : item.parentID;
|
||||
// update ancestor to have no descendant anymore
|
||||
if(id.equals(status.inReplyToId)) item.hasDescendantNeighbor=false;
|
||||
}
|
||||
if(ancestorFirstIndex>=0 && ancestorLastIndex==firstIndex-1){
|
||||
// update ancestor to have no descendant anymore
|
||||
displayItems.subList(ancestorFirstIndex, ancestorLastIndex+1).forEach(i->i.hasDescendantNeighbor=false);
|
||||
adapter.notifyItemRangeChanged(ancestorFirstIndex, ancestorLastIndex-ancestorFirstIndex+1);
|
||||
}
|
||||
|
||||
if(index==-1) return;
|
||||
int lastIndex;
|
||||
for(lastIndex=index;lastIndex<displayItems.size();lastIndex++){
|
||||
StatusDisplayItem item=displayItems.get(lastIndex);
|
||||
String id=deleteContent ? item.getContentID() : item.parentID;
|
||||
if(!id.equals(status.id)) break;
|
||||
if(firstIndex==-1) return false;
|
||||
int lastIndex=firstIndex;
|
||||
while(lastIndex<displayItems.size()){
|
||||
if(!displayItems.get(lastIndex).parentID.equals(parentID)) break;
|
||||
lastIndex++;
|
||||
}
|
||||
displayItems.subList(index, lastIndex).clear();
|
||||
adapter.notifyItemRangeRemoved(index, lastIndex-index);
|
||||
int count=lastIndex-firstIndex;
|
||||
displayItems.subList(firstIndex, lastIndex).clear();
|
||||
adapter.notifyItemRangeRemoved(firstIndex, count);
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void removeStatus(Status status){
|
||||
boolean deleteContent=status==status.getContentStatus();
|
||||
final AccountSessionManager asm=AccountSessionManager.getInstance();
|
||||
final CacheController cache=AccountSessionManager.get(accountID).getCacheController();
|
||||
final boolean unReblogging=status.reblog!=null && asm.isSelf(accountID, status.account);
|
||||
final Predicate<Status> isToBeRemovedReblog=item->item!=null && item.reblog!=null
|
||||
&& item.reblog.id.equals(status.reblog.id)
|
||||
&& asm.isSelf(accountID, item.account);
|
||||
final BiPredicate<String, Supplier<String>> isToBeRemovedContent=(parentId, contentIdSupplier)->
|
||||
parentId.equals(status.id) || contentIdSupplier.get().equals(status.id);
|
||||
|
||||
int ancestorFirstIndex=-1, ancestorLastIndex=-1;
|
||||
for(int i=0;i<displayItems.size();i++){
|
||||
StatusDisplayItem item=displayItems.get(i);
|
||||
String id=deleteContent ? item.getContentID() : item.parentID;
|
||||
if(id.equals(status.id)){
|
||||
removeStatusDisplayItems(status, i, ancestorFirstIndex, ancestorLastIndex, deleteContent);
|
||||
ancestorFirstIndex=ancestorLastIndex=-1;
|
||||
continue;
|
||||
}
|
||||
if(id.equals(status.inReplyToId)){
|
||||
// we found a status that the to-be-removed status replies to!
|
||||
// storing indices to maybe update its display items
|
||||
if(item.parentID.equals(status.inReplyToId)){
|
||||
if(ancestorFirstIndex==-1) ancestorFirstIndex=i;
|
||||
ancestorLastIndex=i;
|
||||
}
|
||||
// if we're un-reblogging, we compare the reblogged status's id with the current status's
|
||||
if(unReblogging
|
||||
? isToBeRemovedReblog.test(getStatusByID(item.parentID))
|
||||
: isToBeRemovedContent.test(item.parentID, item::getContentStatusID)){
|
||||
// if statuses are removed from index i, the next iteration should be on the same index again
|
||||
if(removeStatusDisplayItems(item.parentID, i, ancestorFirstIndex, ancestorLastIndex)) i--;
|
||||
// resetting in case we find another occurrence of the same status that also has ancestors
|
||||
// (we won't - unless the timeline is being especially weird)
|
||||
ancestorFirstIndex=-1; ancestorLastIndex=-1;
|
||||
}
|
||||
}
|
||||
iterateRemoveStatus(data, status.id);
|
||||
iterateRemoveStatus(preloadedData, status.id);
|
||||
|
||||
Consumer<List<Status>> removeStatusFromData=(list)->{
|
||||
Iterator<Status> it=list.iterator();
|
||||
while(it.hasNext()){
|
||||
Status s=it.next();
|
||||
if(unReblogging
|
||||
? isToBeRemovedReblog.test(s)
|
||||
: isToBeRemovedContent.test(s.id, s::getContentStatusID)){
|
||||
it.remove();
|
||||
cache.deleteStatus(s.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
removeStatusFromData.accept(data);
|
||||
removeStatusFromData.accept(preloadedData);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -296,10 +316,14 @@ public abstract class StatusListFragment extends BaseStatusListFragment<Status>
|
||||
|
||||
@Subscribe
|
||||
public void onReblogDeleted(ReblogDeletedEvent ev){
|
||||
AccountSessionManager asm=AccountSessionManager.getInstance();
|
||||
if(!ev.accountID.equals(accountID))
|
||||
return;
|
||||
for(Status item : data){
|
||||
if(item.getContentStatus().id.equals(ev.statusID) && item.reblog!=null){
|
||||
boolean itemIsOwnReblog=item.reblog!=null
|
||||
&& item.getContentStatusID().equals(ev.statusID)
|
||||
&& asm.isSelf(accountID, item.account);
|
||||
if(itemIsOwnReblog){
|
||||
removeStatus(item);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class ThreadFragment extends StatusListFragment implements ProvidesAssist
|
||||
knownAccounts.put(inReplyToAccount.id, inReplyToAccount);
|
||||
data.add(mainStatus);
|
||||
onAppendItems(Collections.singletonList(mainStatus));
|
||||
setTitle(HtmlParser.parseCustomEmoji(getString(R.string.post_from_user, mainStatus.account.displayName), mainStatus.account.emojis));
|
||||
setTitle(HtmlParser.parseCustomEmoji(getString(R.string.post_from_user, mainStatus.account.getDisplayName()), mainStatus.account.emojis));
|
||||
transitionFinished = getArguments().getBoolean("noTransition", false);
|
||||
}
|
||||
|
||||
|
||||
@@ -261,7 +261,7 @@ public class DiscoverAccountsFragment extends MastodonRecyclerFragment<DiscoverA
|
||||
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
relationship=relationships.get(item.account.id);
|
||||
UiUtils.setExtraTextInfo(getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
|
||||
UiUtils.setExtraTextInfo(getContext(), null, true, false, false, item.account);
|
||||
|
||||
if(relationship==null){
|
||||
actionWrap.setVisibility(View.GONE);
|
||||
@@ -330,9 +330,9 @@ public class DiscoverAccountsFragment extends MastodonRecyclerFragment<DiscoverA
|
||||
coverRequest=new UrlImageLoaderRequest(account.header, 1000, 1000);
|
||||
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
||||
if(account.emojis.isEmpty()){
|
||||
parsedName=account.displayName;
|
||||
parsedName= account.getDisplayName();
|
||||
}else{
|
||||
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
|
||||
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
|
||||
emojiHelper.setText(new SpannableStringBuilder(parsedName).append(parsedBio));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,8 +13,10 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.IsOnTop;
|
||||
import org.joinmastodon.android.fragments.ScrollableToTop;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.SearchResult;
|
||||
import org.joinmastodon.android.ui.OutlineProviders;
|
||||
import org.joinmastodon.android.ui.SimpleViewHolder;
|
||||
@@ -155,7 +157,7 @@ public class DiscoverFragment extends AppKitFragment implements ScrollableToTop,
|
||||
}
|
||||
});
|
||||
|
||||
disableDiscover=getArguments().getBoolean("disableDiscover");
|
||||
disableDiscover=AccountSessionManager.get(accountID).getInstance().map(Instance::isAkkoma).orElse(false);
|
||||
searchView=view.findViewById(R.id.search_fragment);
|
||||
if(searchFragment==null){
|
||||
searchFragment=new SearchFragment();
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.stream.Collectors;
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
import me.grishka.appkit.api.SimpleCallback;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class SearchFragment extends BaseStatusListFragment<SearchResult>{
|
||||
@@ -142,7 +143,7 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
|
||||
}*/
|
||||
int offset=_offset;
|
||||
currentRequest=new GetSearchResults(currentQuery, type, type==null, maxID, offset, type==null ? 0 : count)
|
||||
.setCallback(new Callback<>(){
|
||||
.setCallback(new SimpleCallback<>(this){
|
||||
@Override
|
||||
public void onSuccess(SearchResults result){
|
||||
ArrayList<SearchResult> results=new ArrayList<>();
|
||||
@@ -165,16 +166,8 @@ public class SearchFragment extends BaseStatusListFragment<SearchResult>{
|
||||
unfilteredResults=results;
|
||||
onDataLoaded(filterSearchResults(results), type!=null && !results.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error){
|
||||
currentRequest=null;
|
||||
Activity a=getActivity();
|
||||
if(a==null)
|
||||
return;
|
||||
error.showToast(a);
|
||||
}
|
||||
})
|
||||
.setTimeout(180000) // 3 minutes (searches can take a long time)
|
||||
.exec(accountID);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
|
||||
onDataLoaded(results.stream().map(sr->{
|
||||
SearchResultViewModel vm=new SearchResultViewModel(sr, accountID, true);
|
||||
if(sr.type==SearchResult.Type.HASHTAG){
|
||||
vm.hashtagItem.onClick=()->openHashtag(sr);
|
||||
vm.hashtagItem.setOnClick(i->openHashtag(sr));
|
||||
}
|
||||
return vm;
|
||||
}).collect(Collectors.toList()), false);
|
||||
@@ -132,7 +132,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
|
||||
.map(sr->{
|
||||
SearchResultViewModel vm=new SearchResultViewModel(sr, accountID, false);
|
||||
if(sr.type==SearchResult.Type.HASHTAG){
|
||||
vm.hashtagItem.onClick=()->openHashtag(sr);
|
||||
vm.hashtagItem.setOnClick(i->openHashtag(sr));
|
||||
}
|
||||
return vm;
|
||||
})
|
||||
@@ -429,11 +429,11 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
|
||||
wrapSuicideDialog(()->deliverResult(currentQuery, null));
|
||||
}
|
||||
|
||||
private void onOpenURLClick(){
|
||||
private void onOpenURLClick(ListItem<?> item_){
|
||||
UiUtils.openURL(getContext(), accountID, searchViewHelper.getQuery(), false);
|
||||
}
|
||||
|
||||
private void onGoToHashtagClick(){
|
||||
private void onGoToHashtagClick(ListItem<?> item_){
|
||||
wrapSuicideDialog(()->{
|
||||
String q=searchViewHelper.getQuery();
|
||||
if(q.startsWith("#"))
|
||||
@@ -442,7 +442,7 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
|
||||
});
|
||||
}
|
||||
|
||||
private void onGoToAccountClick(){
|
||||
private void onGoToAccountClick(ListItem<?> item_){
|
||||
String q=searchViewHelper.getQuery();
|
||||
if(!q.startsWith("@")){
|
||||
q="@"+q;
|
||||
@@ -459,11 +459,11 @@ public class SearchQueryFragment extends MastodonRecyclerFragment<SearchResultVi
|
||||
}).ifPresent(progress -> progress.wrapProgress((Activity) getContext(), R.string.loading, true));
|
||||
}
|
||||
|
||||
private void onGoToStatusSearchClick(){
|
||||
private void onGoToStatusSearchClick(ListItem<?> item_){
|
||||
wrapSuicideDialog(()->deliverResult(searchViewHelper.getQuery(), SearchResult.Type.STATUS));
|
||||
}
|
||||
|
||||
private void onGoToAccountSearchClick(){
|
||||
private void onGoToAccountSearchClick(ListItem<?> item_){
|
||||
wrapSuicideDialog(()->deliverResult(searchViewHelper.getQuery(), SearchResult.Type.ACCOUNT));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.joinmastodon.android.fragments.onboarding;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
@@ -34,7 +34,6 @@ import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
import me.grishka.appkit.imageloader.ViewImageLoader;
|
||||
import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest;
|
||||
import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class ReportDoneFragment extends MastodonToolbarFragment{
|
||||
|
||||
@@ -73,7 +73,7 @@ public class EditFilterFragment extends BaseSettingsFragment<Void> implements On
|
||||
durationItem=new ListItem<>(R.string.settings_filter_duration, 0, this::onDurationClick),
|
||||
wordsItem=new ListItem<>(R.string.settings_filter_muted_words, 0, this::onWordsClick),
|
||||
contextItem=new ListItem<>(R.string.settings_filter_context, 0, this::onContextClick),
|
||||
cwItem=new CheckableListItem<>(R.string.settings_filter_show_cw, R.string.settings_filter_show_cw_explanation, CheckableListItem.Style.SWITCH, filter==null || filter.filterAction==FilterAction.WARN, ()->toggleCheckableItem(cwItem))
|
||||
cwItem=new CheckableListItem<>(R.string.settings_filter_show_cw, R.string.settings_filter_show_cw_explanation, CheckableListItem.Style.SWITCH, filter==null || filter.filterAction==FilterAction.WARN, this::toggleCheckableItem)
|
||||
));
|
||||
|
||||
if(filter!=null){
|
||||
@@ -113,7 +113,7 @@ public class EditFilterFragment extends BaseSettingsFragment<Void> implements On
|
||||
return 1;
|
||||
}
|
||||
|
||||
private void onDurationClick(){
|
||||
private void onDurationClick(ListItem<Void> item_){
|
||||
int[] durationOptions={
|
||||
1800,
|
||||
3600,
|
||||
@@ -182,21 +182,21 @@ public class EditFilterFragment extends BaseSettingsFragment<Void> implements On
|
||||
alert.setOnDismissListener(dialog->callback.accept(null));
|
||||
}
|
||||
|
||||
private void onWordsClick(){
|
||||
private void onWordsClick(ListItem<Void> item){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putParcelableArrayList("words", (ArrayList<? extends Parcelable>) keywords.stream().map(Parcels::wrap).collect(Collectors.toCollection(ArrayList::new)));
|
||||
Nav.goForResult(getActivity(), FilterWordsFragment.class, args, WORDS_RESULT, this);
|
||||
}
|
||||
|
||||
private void onContextClick(){
|
||||
private void onContextClick(ListItem<Void> item){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putSerializable("context", context);
|
||||
Nav.goForResult(getActivity(), FilterContextFragment.class, args, CONTEXT_RESULT, this);
|
||||
}
|
||||
|
||||
private void onDeleteClick(){
|
||||
private void onDeleteClick(ListItem<Void> item_){
|
||||
AlertDialog alert=new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(getString(R.string.settings_delete_filter_title, filter.title))
|
||||
.setMessage(R.string.settings_delete_filter_confirmation)
|
||||
|
||||
@@ -22,10 +22,9 @@ public class FilterContextFragment extends BaseSettingsFragment<FilterContext> i
|
||||
setTitle(R.string.settings_filter_context);
|
||||
context=(EnumSet<FilterContext>) getArguments().getSerializable("context");
|
||||
onDataLoaded(Arrays.stream(FilterContext.values()).map(c->{
|
||||
CheckableListItem<FilterContext> item=new CheckableListItem<>(c.getDisplayNameRes(), 0, CheckableListItem.Style.CHECKBOX, context.contains(c), null);
|
||||
CheckableListItem<FilterContext> item=new CheckableListItem<>(c.getDisplayNameRes(), 0, CheckableListItem.Style.CHECKBOX, context.contains(c), this::toggleCheckableItem);
|
||||
item.parentObject=c;
|
||||
item.isEnabled=true;
|
||||
item.onClick=()->toggleCheckableItem(item);
|
||||
return item;
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
package org.joinmastodon.android.fragments.settings;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.IntEvaluator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.app.AlertDialog;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
@@ -27,6 +22,7 @@ import org.joinmastodon.android.model.FilterKeyword;
|
||||
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
|
||||
import org.joinmastodon.android.model.viewmodel.ListItem;
|
||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||
import org.joinmastodon.android.ui.utils.ActionModeHelper;
|
||||
import org.joinmastodon.android.ui.utils.SimpleTextWatcher;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.ui.views.FloatingHintEditTextLayout;
|
||||
@@ -37,7 +33,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import me.grishka.appkit.FragmentStackActivity;
|
||||
import me.grishka.appkit.fragments.OnBackPressedListener;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
@@ -60,7 +55,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
|
||||
FilterKeyword word=Parcels.unwrap(p);
|
||||
ListItem<FilterKeyword> item=new ListItem<>(word.keyword, null, null, word);
|
||||
item.isEnabled=true;
|
||||
item.onClick=()->onWordClick(item);
|
||||
item.setOnClick(this::onWordClick);
|
||||
return item;
|
||||
}).collect(Collectors.toList()));
|
||||
setHasOptionsMenu(true);
|
||||
@@ -114,7 +109,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
|
||||
inflater.inflate(R.menu.settings_filter_words, menu);
|
||||
inflater.inflate(R.menu.selectable_list, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -174,7 +169,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
|
||||
w.keyword=input;
|
||||
ListItem<FilterKeyword> item=new ListItem<>(w.keyword, null, null, w);
|
||||
item.isEnabled=true;
|
||||
item.onClick=()->onWordClick(item);
|
||||
item.setOnClick(this::onWordClick);
|
||||
data.add(item);
|
||||
itemsAdapter.notifyItemInserted(data.size()-1);
|
||||
}else{
|
||||
@@ -228,29 +223,15 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
|
||||
return;
|
||||
V.setVisibilityAnimated(fab, View.GONE);
|
||||
|
||||
actionMode=getActivity().startActionMode(new ActionMode.Callback(){
|
||||
actionMode=ActionModeHelper.startActionMode(this, ()->elevationOnScrollListener.getCurrentStatusBarColor(), new ActionMode.Callback(){
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu){
|
||||
ObjectAnimator anim=ObjectAnimator.ofInt(getActivity().getWindow(), "statusBarColor", elevationOnScrollListener.getCurrentStatusBarColor(), UiUtils.getThemeColor(getActivity(), R.attr.colorM3Primary));
|
||||
anim.setEvaluator(new IntEvaluator(){
|
||||
@Override
|
||||
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
|
||||
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
((FragmentStackActivity) getActivity()).invalidateSystemBarColors(FilterWordsFragment.this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu){
|
||||
mode.getMenuInflater().inflate(R.menu.settings_filter_words_action_mode, menu);
|
||||
for(int i=0;i<menu.size();i++){
|
||||
Drawable icon=menu.getItem(i).getIcon().mutate();
|
||||
icon.setTint(UiUtils.getThemeColor(getActivity(), R.attr.colorM3OnPrimary));
|
||||
menu.getItem(i).setIcon(icon);
|
||||
}
|
||||
deleteItem=menu.findItem(R.id.delete);
|
||||
return true;
|
||||
}
|
||||
@@ -266,21 +247,6 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode){
|
||||
leaveSelectionMode(true);
|
||||
ObjectAnimator anim=ObjectAnimator.ofInt(getActivity().getWindow(), "statusBarColor", UiUtils.getThemeColor(getActivity(), R.attr.colorM3Primary), elevationOnScrollListener.getCurrentStatusBarColor());
|
||||
anim.setEvaluator(new IntEvaluator(){
|
||||
@Override
|
||||
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
|
||||
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
|
||||
}
|
||||
});
|
||||
anim.addListener(new AnimatorListenerAdapter(){
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation){
|
||||
getActivity().getWindow().setStatusBarColor(0);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
((FragmentStackActivity) getActivity()).invalidateSystemBarColors(FilterWordsFragment.this);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -289,7 +255,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
|
||||
ListItem<FilterKeyword> item=data.get(i);
|
||||
CheckableListItem<FilterKeyword> newItem=new CheckableListItem<>(item.title, null, CheckableListItem.Style.CHECKBOX, selectAll, null);
|
||||
newItem.isEnabled=true;
|
||||
newItem.onClick=()->onSelectionModeWordClick(newItem);
|
||||
newItem.setOnClick(this::onSelectionModeWordClick);
|
||||
newItem.parentObject=item.parentObject;
|
||||
if(selectAll)
|
||||
selectedItems.add(newItem);
|
||||
@@ -313,7 +279,7 @@ public class FilterWordsFragment extends BaseSettingsFragment<FilterKeyword> imp
|
||||
ListItem<FilterKeyword> item=data.get(i);
|
||||
ListItem<FilterKeyword> newItem=new ListItem<>(item.title, null, null);
|
||||
newItem.isEnabled=true;
|
||||
newItem.onClick=()->onWordClick(newItem);
|
||||
newItem.setOnClick(this::onWordClick);
|
||||
newItem.parentObject=item.parentObject;
|
||||
data.set(i, newItem);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ import org.joinmastodon.android.model.viewmodel.ListItem;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import me.grishka.appkit.imageloader.ImageCache;
|
||||
@@ -26,23 +25,32 @@ import me.grishka.appkit.utils.V;
|
||||
|
||||
public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
|
||||
private ListItem<Void> mediaCacheItem;
|
||||
private AccountSession session;
|
||||
private boolean timelineCacheCleared=false;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
setTitle(getString(R.string.about_app, getString(R.string.sk_app_name)));
|
||||
AccountSession s=AccountSessionManager.get(accountID);
|
||||
session=AccountSessionManager.get(accountID);
|
||||
onDataLoaded(List.of(
|
||||
new ListItem<>(R.string.sk_settings_donate, 0, R.drawable.ic_fluent_heart_24_regular, ()->UiUtils.openHashtagTimeline(getActivity(), accountID, getString(R.string.donate_hashtag))),
|
||||
new ListItem<>(R.string.sk_settings_contribute, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), getString(R.string.repo_url))),
|
||||
new ListItem<>(R.string.settings_tos, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/terms")),
|
||||
new ListItem<>(R.string.settings_privacy_policy, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), getString(R.string.privacy_policy_url)), 0, true),
|
||||
mediaCacheItem=new ListItem<>(R.string.settings_clear_cache, 0, this::onClearMediaCacheClick)
|
||||
new ListItem<>(R.string.sk_settings_donate, 0, R.drawable.ic_fluent_heart_24_regular, i->UiUtils.openHashtagTimeline(getActivity(), accountID, getString(R.string.donate_hashtag))),
|
||||
new ListItem<>(R.string.sk_settings_contribute, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), getString(R.string.repo_url))),
|
||||
new ListItem<>(R.string.settings_tos, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+session.domain+"/terms")),
|
||||
new ListItem<>(R.string.settings_privacy_policy, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), getString(R.string.privacy_policy_url)), 0, true),
|
||||
mediaCacheItem=new ListItem<>(R.string.settings_clear_cache, 0, this::onClearMediaCacheClick),
|
||||
new ListItem<>(getString(R.string.sk_settings_clear_timeline_cache), session.domain, this::onClearTimelineCacheClick)
|
||||
));
|
||||
|
||||
updateMediaCacheItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onHidden(){
|
||||
super.onHidden();
|
||||
if(timelineCacheCleared) getActivity().recreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){}
|
||||
|
||||
@@ -63,7 +71,7 @@ public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
|
||||
return adapter;
|
||||
}
|
||||
|
||||
private void onClearMediaCacheClick(){
|
||||
private void onClearMediaCacheClick(ListItem<?> item){
|
||||
MastodonAPIController.runInBackground(()->{
|
||||
Activity activity=getActivity();
|
||||
ImageCache.getInstance(getActivity()).clear();
|
||||
@@ -74,6 +82,12 @@ public class SettingsAboutAppFragment extends BaseSettingsFragment<Void>{
|
||||
});
|
||||
}
|
||||
|
||||
private void onClearTimelineCacheClick(ListItem<?> item){
|
||||
session.getCacheController().putHomeTimeline(List.of(), true);
|
||||
Toast.makeText(getContext(), R.string.sk_timeline_cache_cleared, Toast.LENGTH_SHORT).show();
|
||||
timelineCacheCleared=true;
|
||||
}
|
||||
|
||||
private void updateMediaCacheItem(){
|
||||
long size=ImageCache.getInstance(getActivity()).getDiskCache().size();
|
||||
mediaCacheItem.subtitle=UiUtils.formatFileSize(getActivity(), size, false);
|
||||
|
||||
@@ -46,20 +46,20 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
|
||||
|
||||
List<ListItem<Void>> items = new ArrayList<>(List.of(
|
||||
languageItem=new ListItem<>(getString(R.string.default_post_language), postLanguage!=null ? postLanguage.getDisplayName(getContext()) : null, R.drawable.ic_fluent_local_language_24_regular, this::onDefaultLanguageClick),
|
||||
altTextItem=new CheckableListItem<>(R.string.settings_alt_text_reminders, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.altTextReminders, R.drawable.ic_fluent_image_alt_text_24_regular, ()->toggleCheckableItem(altTextItem)),
|
||||
playGifsItem=new CheckableListItem<>(R.string.settings_gif, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.playGifs, R.drawable.ic_fluent_gif_24_regular, ()->toggleCheckableItem(playGifsItem)),
|
||||
overlayMediaItem=new CheckableListItem<>(R.string.sk_settings_continues_playback, R.string.sk_settings_continues_playback_summary, CheckableListItem.Style.SWITCH, GlobalUserPreferences.overlayMedia, R.drawable.ic_fluent_play_circle_hint_24_regular, ()->toggleCheckableItem(overlayMediaItem)),
|
||||
customTabsItem=new CheckableListItem<>(R.string.settings_custom_tabs, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.useCustomTabs, R.drawable.ic_fluent_link_24_regular, ()->toggleCheckableItem(customTabsItem)),
|
||||
confirmUnfollowItem=new CheckableListItem<>(R.string.settings_confirm_unfollow, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmUnfollow, R.drawable.ic_fluent_person_delete_24_regular, ()->toggleCheckableItem(confirmUnfollowItem)),
|
||||
confirmBoostItem=new CheckableListItem<>(R.string.settings_confirm_boost, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmBoost, R.drawable.ic_fluent_arrow_repeat_all_24_regular, ()->toggleCheckableItem(confirmBoostItem)),
|
||||
confirmDeleteItem=new CheckableListItem<>(R.string.settings_confirm_delete_post, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmDeletePost, R.drawable.ic_fluent_delete_24_regular, ()->toggleCheckableItem(confirmDeleteItem)),
|
||||
altTextItem=new CheckableListItem<>(R.string.settings_alt_text_reminders, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.altTextReminders, R.drawable.ic_fluent_image_alt_text_24_regular, i->toggleCheckableItem(altTextItem)),
|
||||
playGifsItem=new CheckableListItem<>(R.string.settings_gif, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.playGifs, R.drawable.ic_fluent_gif_24_regular, i->toggleCheckableItem(playGifsItem)),
|
||||
overlayMediaItem=new CheckableListItem<>(R.string.sk_settings_continues_playback, R.string.sk_settings_continues_playback_summary, CheckableListItem.Style.SWITCH, GlobalUserPreferences.overlayMedia, R.drawable.ic_fluent_play_circle_hint_24_regular, i->toggleCheckableItem(overlayMediaItem)),
|
||||
customTabsItem=new CheckableListItem<>(R.string.settings_custom_tabs, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.useCustomTabs, R.drawable.ic_fluent_link_24_regular, i->toggleCheckableItem(customTabsItem)),
|
||||
confirmUnfollowItem=new CheckableListItem<>(R.string.settings_confirm_unfollow, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmUnfollow, R.drawable.ic_fluent_person_delete_24_regular, i->toggleCheckableItem(confirmUnfollowItem)),
|
||||
confirmBoostItem=new CheckableListItem<>(R.string.settings_confirm_boost, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmBoost, R.drawable.ic_fluent_arrow_repeat_all_24_regular, i->toggleCheckableItem(confirmBoostItem)),
|
||||
confirmDeleteItem=new CheckableListItem<>(R.string.settings_confirm_delete_post, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.confirmDeletePost, R.drawable.ic_fluent_delete_24_regular, i->toggleCheckableItem(confirmDeleteItem)),
|
||||
prefixRepliesItem=new ListItem<>(R.string.sk_settings_prefix_reply_cw_with_re, getPrefixWithRepliesString(), R.drawable.ic_fluent_arrow_reply_24_regular, this::onPrefixRepliesClick),
|
||||
forwardReportsItem=new CheckableListItem<>(R.string.sk_settings_forward_report_default, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.forwardReportDefault, R.drawable.ic_fluent_arrow_forward_24_regular, ()->toggleCheckableItem(forwardReportsItem)),
|
||||
loadNewPostsItem=new CheckableListItem<>(R.string.sk_settings_load_new_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.loadNewPosts, R.drawable.ic_fluent_arrow_sync_24_regular, this::onLoadNewPostsClick),
|
||||
seeNewPostsBtnItem=new CheckableListItem<>(R.string.sk_settings_see_new_posts_button, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNewPostsButton, R.drawable.ic_fluent_arrow_up_24_regular, ()->toggleCheckableItem(seeNewPostsBtnItem)),
|
||||
remoteLoadingItem=new CheckableListItem<>(R.string.sk_settings_allow_remote_loading, R.string.sk_settings_allow_remote_loading_explanation, CheckableListItem.Style.SWITCH, GlobalUserPreferences.allowRemoteLoading, R.drawable.ic_fluent_communication_24_regular, ()->toggleCheckableItem(remoteLoadingItem), true),
|
||||
showBoostsItem=new CheckableListItem<>(R.string.sk_settings_show_boosts, 0, CheckableListItem.Style.SWITCH, lp.showBoosts, R.drawable.ic_fluent_arrow_repeat_all_24_regular, ()->toggleCheckableItem(showBoostsItem)),
|
||||
showRepliesItem=new CheckableListItem<>(R.string.sk_settings_show_replies, 0, CheckableListItem.Style.SWITCH, lp.showReplies, R.drawable.ic_fluent_arrow_reply_24_regular, ()->toggleCheckableItem(showRepliesItem))
|
||||
forwardReportsItem=new CheckableListItem<>(R.string.sk_settings_forward_report_default, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.forwardReportDefault, R.drawable.ic_fluent_arrow_forward_24_regular, i->toggleCheckableItem(forwardReportsItem)),
|
||||
loadNewPostsItem=new CheckableListItem<>(R.string.sk_settings_load_new_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.loadNewPosts, R.drawable.ic_fluent_arrow_sync_24_regular, i->onLoadNewPostsClick()),
|
||||
seeNewPostsBtnItem=new CheckableListItem<>(R.string.sk_settings_see_new_posts_button, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNewPostsButton, R.drawable.ic_fluent_arrow_up_24_regular, i->toggleCheckableItem(seeNewPostsBtnItem)),
|
||||
remoteLoadingItem=new CheckableListItem<>(R.string.sk_settings_allow_remote_loading, R.string.sk_settings_allow_remote_loading_explanation, CheckableListItem.Style.SWITCH, GlobalUserPreferences.allowRemoteLoading, R.drawable.ic_fluent_communication_24_regular, i->toggleCheckableItem(remoteLoadingItem), true),
|
||||
showBoostsItem=new CheckableListItem<>(R.string.sk_settings_show_boosts, 0, CheckableListItem.Style.SWITCH, lp.showBoosts, R.drawable.ic_fluent_arrow_repeat_all_24_regular, i->toggleCheckableItem(showBoostsItem)),
|
||||
showRepliesItem=new CheckableListItem<>(R.string.sk_settings_show_replies, 0, CheckableListItem.Style.SWITCH, lp.showReplies, R.drawable.ic_fluent_arrow_reply_24_regular, i->toggleCheckableItem(showRepliesItem))
|
||||
));
|
||||
|
||||
if(isInstanceAkkoma()) items.add(
|
||||
@@ -93,7 +93,7 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){}
|
||||
|
||||
private void onDefaultLanguageClick(){
|
||||
private void onDefaultLanguageClick(ListItem<?> item){
|
||||
if (languageResolver == null) return;
|
||||
ComposeLanguageAlertViewController vc=new ComposeLanguageAlertViewController(getActivity(), null, new ComposeLanguageAlertViewController.SelectedOption(postLanguage), null, languageResolver);
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
@@ -112,14 +112,14 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
|
||||
.show();
|
||||
}
|
||||
|
||||
private void onPrefixRepliesClick(){
|
||||
private void onPrefixRepliesClick(ListItem<?> item){
|
||||
int selected=GlobalUserPreferences.prefixReplies.ordinal();
|
||||
int[] newSelected={selected};
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.sk_settings_prefix_reply_cw_with_re)
|
||||
.setSingleChoiceItems((String[]) IntStream.of(R.string.sk_settings_prefix_replies_never, R.string.sk_settings_prefix_replies_always, R.string.sk_settings_prefix_replies_to_others).mapToObj(this::getString).toArray(String[]::new),
|
||||
selected, (dlg, item)->newSelected[0]=item)
|
||||
.setPositiveButton(R.string.ok, (dlg, item)->{
|
||||
selected, (dlg, which)->newSelected[0]=which)
|
||||
.setPositiveButton(R.string.ok, (dlg, which)->{
|
||||
GlobalUserPreferences.prefixReplies=GlobalUserPreferences.PrefixRepliesMode.values()[newSelected[0]];
|
||||
prefixRepliesItem.subtitleRes=getPrefixWithRepliesString();
|
||||
rebindItem(prefixRepliesItem);
|
||||
@@ -128,7 +128,7 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
|
||||
.show();
|
||||
}
|
||||
|
||||
private void onReplyVisibilityClick(){
|
||||
private void onReplyVisibilityClick(ListItem<?> item){
|
||||
AccountLocalPreferences lp=getLocalPrefs();
|
||||
int selected=lp.timelineReplyVisibility==null ? 2 : switch(lp.timelineReplyVisibility){
|
||||
case "following" -> 0;
|
||||
@@ -139,8 +139,8 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.sk_settings_prefix_reply_cw_with_re)
|
||||
.setSingleChoiceItems((String[]) IntStream.of(R.string.sk_settings_reply_visibility_following, R.string.sk_settings_reply_visibility_self, R.string.sk_settings_reply_visibility_all).mapToObj(this::getString).toArray(String[]::new),
|
||||
selected, (dlg, item)->newSelected[0]=item)
|
||||
.setPositiveButton(R.string.ok, (dlg, item)->{
|
||||
selected, (dlg, which)->newSelected[0]=which)
|
||||
.setPositiveButton(R.string.ok, (dlg, which)->{
|
||||
lp.timelineReplyVisibility=switch(newSelected[0]){
|
||||
case 0 -> "following";
|
||||
case 1 -> "self";
|
||||
@@ -176,6 +176,8 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
|
||||
GlobalUserPreferences.allowRemoteLoading=remoteLoadingItem.checked;
|
||||
GlobalUserPreferences.save();
|
||||
AccountLocalPreferences lp=getLocalPrefs();
|
||||
boolean restartPlease=lp.showBoosts!=showBoostsItem.checked
|
||||
|| lp.showReplies!=showRepliesItem.checked;
|
||||
lp.showBoosts=showBoostsItem.checked;
|
||||
lp.showReplies=showRepliesItem.checked;
|
||||
lp.save();
|
||||
@@ -186,6 +188,7 @@ public class SettingsBehaviorFragment extends BaseSettingsFragment<Void> impleme
|
||||
s.preferences.postingDefaultLanguage=newPostLanguage.language.getLanguage();
|
||||
s.savePreferencesLater();
|
||||
}
|
||||
if(restartPlease) getActivity().recreate();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -39,7 +39,7 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){}
|
||||
|
||||
private void onTestEmailConfirmClick(){
|
||||
private void onTestEmailConfirmClick(ListItem<?> item){
|
||||
AccountSession sess=AccountSessionManager.getInstance().getAccount(accountID);
|
||||
sess.activated=false;
|
||||
sess.activationInfo=new AccountActivationInfo("test@email", System.currentTimeMillis());
|
||||
@@ -49,18 +49,18 @@ public class SettingsDebugFragment extends BaseSettingsFragment<Void>{
|
||||
Nav.goClearingStack(getActivity(), AccountActivationFragment.class, args);
|
||||
}
|
||||
|
||||
private void onForceSelfUpdateClick(){
|
||||
private void onForceSelfUpdateClick(ListItem<?> item){
|
||||
GithubSelfUpdater.forceUpdate=true;
|
||||
GithubSelfUpdater.getInstance().maybeCheckForUpdates();
|
||||
restartUI();
|
||||
}
|
||||
|
||||
private void onResetUpdaterClick(){
|
||||
private void onResetUpdaterClick(ListItem<?> item){
|
||||
GithubSelfUpdater.getInstance().reset();
|
||||
restartUI();
|
||||
}
|
||||
|
||||
private void onResetDiscoverBannersClick(){
|
||||
private void onResetDiscoverBannersClick(ListItem<?> item){
|
||||
DiscoverInfoBannerHelper.reset();
|
||||
restartUI();
|
||||
}
|
||||
|
||||
@@ -56,29 +56,29 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
|
||||
onDataLoaded(List.of(
|
||||
themeItem=new ListItem<>(R.string.settings_theme, getAppearanceValue(), R.drawable.ic_fluent_weather_moon_24_regular, this::onAppearanceClick),
|
||||
colorItem=new ListItem<>(getString(R.string.sk_settings_color_palette), getColorPaletteValue(), R.drawable.ic_fluent_color_24_regular, this::onColorClick),
|
||||
trueBlackModeItem=new CheckableListItem<>(R.string.sk_settings_true_black, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.trueBlackTheme, R.drawable.ic_fluent_dark_theme_24_regular, this::onTrueBlackModeClick, true),
|
||||
trueBlackModeItem=new CheckableListItem<>(R.string.sk_settings_true_black, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.trueBlackTheme, R.drawable.ic_fluent_dark_theme_24_regular, i->onTrueBlackModeClick(), true),
|
||||
publishTextItem=new ListItem<>(getString(R.string.sk_settings_publish_button_text), getPublishButtonText(), R.drawable.ic_fluent_send_24_regular, this::onPublishTextClick),
|
||||
autoRevealCWsItem=new ListItem<>(R.string.sk_settings_auto_reveal_equal_spoilers, getAutoRevealSpoilersText(), R.drawable.ic_fluent_eye_24_regular, this::onAutoRevealSpoilersClick),
|
||||
revealCWsItem=new CheckableListItem<>(R.string.sk_settings_always_reveal_content_warnings, 0, CheckableListItem.Style.SWITCH, lp.revealCWs, R.drawable.ic_fluent_chat_warning_24_regular, ()->toggleCheckableItem(revealCWsItem)),
|
||||
hideSensitiveMediaItem=new CheckableListItem<>(R.string.settings_hide_sensitive_media, 0, CheckableListItem.Style.SWITCH, lp.hideSensitiveMedia, R.drawable.ic_fluent_flag_24_regular, ()->toggleCheckableItem(hideSensitiveMediaItem)),
|
||||
interactionCountsItem=new CheckableListItem<>(R.string.settings_show_interaction_counts, 0, CheckableListItem.Style.SWITCH, lp.showInteractionCounts, R.drawable.ic_fluent_number_row_24_regular, ()->toggleCheckableItem(interactionCountsItem)),
|
||||
emojiInNamesItem=new CheckableListItem<>(R.string.settings_show_emoji_in_names, 0, CheckableListItem.Style.SWITCH, lp.customEmojiInNames, R.drawable.ic_fluent_emoji_24_regular, ()->toggleCheckableItem(emojiInNamesItem)),
|
||||
marqueeItem=new CheckableListItem<>(R.string.sk_settings_enable_marquee, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.toolbarMarquee, R.drawable.ic_fluent_text_more_24_regular, ()->toggleCheckableItem(marqueeItem)),
|
||||
reduceMotionItem=new CheckableListItem<>(R.string.sk_settings_reduce_motion, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.reduceMotion, R.drawable.ic_fluent_star_emphasis_24_regular, ()->toggleCheckableItem(reduceMotionItem)),
|
||||
disableSwipeItem=new CheckableListItem<>(R.string.sk_settings_tabs_disable_swipe, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableSwipe, R.drawable.ic_fluent_swipe_right_24_regular, ()->toggleCheckableItem(disableSwipeItem)),
|
||||
altIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showAltIndicator, R.drawable.ic_fluent_scan_text_24_regular, ()->toggleCheckableItem(altIndicatorItem)),
|
||||
noAltIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_no_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNoAltIndicator, R.drawable.ic_fluent_important_24_regular, ()->toggleCheckableItem(noAltIndicatorItem)),
|
||||
collapsePostsItem=new CheckableListItem<>(R.string.sk_settings_collapse_long_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.collapseLongPosts, R.drawable.ic_fluent_chevron_down_24_regular, ()->toggleCheckableItem(collapsePostsItem)),
|
||||
spectatorModeItem=new CheckableListItem<>(R.string.sk_settings_hide_interaction, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.spectatorMode, R.drawable.ic_fluent_star_off_24_regular, ()->toggleCheckableItem(spectatorModeItem)),
|
||||
hideFabItem=new CheckableListItem<>(R.string.sk_settings_hide_fab, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.autoHideFab, R.drawable.ic_fluent_edit_24_regular, ()->toggleCheckableItem(hideFabItem)),
|
||||
translateOpenedItem=new CheckableListItem<>(R.string.sk_settings_translate_only_opened, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.translateButtonOpenedOnly, R.drawable.ic_fluent_translate_24_regular, ()->toggleCheckableItem(translateOpenedItem)),
|
||||
likeIconItem=new CheckableListItem<>(R.string.sk_settings_like_icon, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.likeIcon, R.drawable.ic_fluent_heart_24_regular, ()->toggleCheckableItem(likeIconItem)),
|
||||
underlinedLinksItem=new CheckableListItem<>(R.string.sk_settings_underlined_links, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.underlinedLinks, R.drawable.ic_fluent_text_underline_24_regular, ()->toggleCheckableItem(underlinedLinksItem)),
|
||||
disablePillItem=new CheckableListItem<>(R.string.sk_disable_pill_shaped_active_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableM3PillActiveIndicator, R.drawable.ic_fluent_pill_24_regular, ()->toggleCheckableItem(disablePillItem)),
|
||||
showNavigationLabelsItem=new CheckableListItem<>(R.string.sk_settings_show_labels_in_navigation_bar, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNavigationLabels, R.drawable.ic_fluent_tag_24_regular, ()->toggleCheckableItem(showNavigationLabelsItem), true),
|
||||
pronounsInTimelinesItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_timelines, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInTimelines, 0, ()->toggleCheckableItem(pronounsInTimelinesItem)),
|
||||
pronounsInThreadsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_threads, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInThreads, 0, ()->toggleCheckableItem(pronounsInThreadsItem)),
|
||||
pronounsInUserListingsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_user_listings, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInUserListings, 0, ()->toggleCheckableItem(pronounsInUserListingsItem))
|
||||
revealCWsItem=new CheckableListItem<>(R.string.sk_settings_always_reveal_content_warnings, 0, CheckableListItem.Style.SWITCH, lp.revealCWs, R.drawable.ic_fluent_chat_warning_24_regular, i->toggleCheckableItem(revealCWsItem)),
|
||||
hideSensitiveMediaItem=new CheckableListItem<>(R.string.settings_hide_sensitive_media, 0, CheckableListItem.Style.SWITCH, lp.hideSensitiveMedia, R.drawable.ic_fluent_flag_24_regular, i->toggleCheckableItem(hideSensitiveMediaItem)),
|
||||
interactionCountsItem=new CheckableListItem<>(R.string.settings_show_interaction_counts, 0, CheckableListItem.Style.SWITCH, lp.showInteractionCounts, R.drawable.ic_fluent_number_row_24_regular, i->toggleCheckableItem(interactionCountsItem)),
|
||||
emojiInNamesItem=new CheckableListItem<>(R.string.settings_show_emoji_in_names, 0, CheckableListItem.Style.SWITCH, lp.customEmojiInNames, R.drawable.ic_fluent_emoji_24_regular, i->toggleCheckableItem(emojiInNamesItem)),
|
||||
marqueeItem=new CheckableListItem<>(R.string.sk_settings_enable_marquee, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.toolbarMarquee, R.drawable.ic_fluent_text_more_24_regular, i->toggleCheckableItem(marqueeItem)),
|
||||
reduceMotionItem=new CheckableListItem<>(R.string.sk_settings_reduce_motion, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.reduceMotion, R.drawable.ic_fluent_star_emphasis_24_regular, i->toggleCheckableItem(reduceMotionItem)),
|
||||
disableSwipeItem=new CheckableListItem<>(R.string.sk_settings_tabs_disable_swipe, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableSwipe, R.drawable.ic_fluent_swipe_right_24_regular, i->toggleCheckableItem(disableSwipeItem)),
|
||||
altIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showAltIndicator, R.drawable.ic_fluent_scan_text_24_regular, i->toggleCheckableItem(altIndicatorItem)),
|
||||
noAltIndicatorItem=new CheckableListItem<>(R.string.sk_settings_show_no_alt_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNoAltIndicator, R.drawable.ic_fluent_important_24_regular, i->toggleCheckableItem(noAltIndicatorItem)),
|
||||
collapsePostsItem=new CheckableListItem<>(R.string.sk_settings_collapse_long_posts, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.collapseLongPosts, R.drawable.ic_fluent_chevron_down_24_regular, i->toggleCheckableItem(collapsePostsItem)),
|
||||
spectatorModeItem=new CheckableListItem<>(R.string.sk_settings_hide_interaction, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.spectatorMode, R.drawable.ic_fluent_star_off_24_regular, i->toggleCheckableItem(spectatorModeItem)),
|
||||
hideFabItem=new CheckableListItem<>(R.string.sk_settings_hide_fab, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.autoHideFab, R.drawable.ic_fluent_edit_24_regular, i->toggleCheckableItem(hideFabItem)),
|
||||
translateOpenedItem=new CheckableListItem<>(R.string.sk_settings_translate_only_opened, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.translateButtonOpenedOnly, R.drawable.ic_fluent_translate_24_regular, i->toggleCheckableItem(translateOpenedItem)),
|
||||
likeIconItem=new CheckableListItem<>(R.string.sk_settings_like_icon, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.likeIcon, R.drawable.ic_fluent_heart_24_regular, i->toggleCheckableItem(likeIconItem)),
|
||||
underlinedLinksItem=new CheckableListItem<>(R.string.sk_settings_underlined_links, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.underlinedLinks, R.drawable.ic_fluent_text_underline_24_regular, i->toggleCheckableItem(underlinedLinksItem)),
|
||||
disablePillItem=new CheckableListItem<>(R.string.sk_disable_pill_shaped_active_indicator, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.disableM3PillActiveIndicator, R.drawable.ic_fluent_pill_24_regular, i->toggleCheckableItem(disablePillItem)),
|
||||
showNavigationLabelsItem=new CheckableListItem<>(R.string.sk_settings_show_labels_in_navigation_bar, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.showNavigationLabels, R.drawable.ic_fluent_tag_24_regular, i->toggleCheckableItem(showNavigationLabelsItem), true),
|
||||
pronounsInTimelinesItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_timelines, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInTimelines, 0, i->toggleCheckableItem(pronounsInTimelinesItem)),
|
||||
pronounsInThreadsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_threads, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInThreads, 0, i->toggleCheckableItem(pronounsInThreadsItem)),
|
||||
pronounsInUserListingsItem=new CheckableListItem<>(R.string.sk_settings_display_pronouns_in_user_listings, 0, CheckableListItem.Style.CHECKBOX, GlobalUserPreferences.displayPronounsInUserListings, 0, i->toggleCheckableItem(pronounsInUserListingsItem))
|
||||
));
|
||||
trueBlackModeItem.checkedChangeListener=checked->onTrueBlackModeClick();
|
||||
}
|
||||
@@ -166,7 +166,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
|
||||
maybeApplyNewThemeRightNow(null, null, prev);
|
||||
}
|
||||
|
||||
private void onAppearanceClick(){
|
||||
private void onAppearanceClick(ListItem<?> item_){
|
||||
int selected=switch(GlobalUserPreferences.theme){
|
||||
case LIGHT -> 0;
|
||||
case DARK -> 1;
|
||||
@@ -197,7 +197,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
|
||||
.show();
|
||||
}
|
||||
|
||||
private void onColorClick(){
|
||||
private void onColorClick(ListItem<?> item_){
|
||||
boolean multiple=AccountSessionManager.getInstance().getLoggedInAccounts().size() > 1;
|
||||
int indexOffset=multiple ? 1 : 0;
|
||||
int selected=lp.color==null ? 0 : lp.color.ordinal() + indexOffset;
|
||||
@@ -234,7 +234,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
|
||||
alert.show();
|
||||
}
|
||||
|
||||
private void onPublishTextClick(){
|
||||
private void onPublishTextClick(ListItem<?> item_){
|
||||
TextInputFrameLayout input = new TextInputFrameLayout(
|
||||
getContext(),
|
||||
getString(R.string.publish),
|
||||
@@ -257,7 +257,7 @@ public class SettingsDisplayFragment extends BaseSettingsFragment<Void>{
|
||||
.show();
|
||||
}
|
||||
|
||||
private void onAutoRevealSpoilersClick(){
|
||||
private void onAutoRevealSpoilersClick(ListItem<?> item_){
|
||||
int selected=GlobalUserPreferences.autoRevealEqualSpoilers.ordinal();
|
||||
int[] newSelected={selected};
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
|
||||
@@ -67,16 +67,14 @@ public class SettingsFiltersFragment extends BaseSettingsFragment<Filter>{
|
||||
Nav.go(getActivity(), EditFilterFragment.class, args);
|
||||
}
|
||||
|
||||
private void onAddFilterClick(){
|
||||
private void onAddFilterClick(ListItem<?> item){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
Nav.go(getActivity(), EditFilterFragment.class, args);
|
||||
}
|
||||
|
||||
private ListItem<Filter> makeListItem(Filter f){
|
||||
ListItem<Filter> item=new ListItem<>(f.title, getString(f.isActive() ? R.string.filter_active : R.string.filter_inactive), null, f);
|
||||
item.onClick=()->onFilterClick(item);
|
||||
item.isEnabled=true;
|
||||
ListItem<Filter> item=new ListItem<>(f.title, getString(f.isActive() ? R.string.filter_active : R.string.filter_inactive), this::onFilterClick, f);
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import me.grishka.appkit.Nav;
|
||||
@@ -36,15 +37,15 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
|
||||
lp=s.getLocalPreferences();
|
||||
onDataLoaded(List.of(
|
||||
new ListItem<>(AccountSessionManager.get(accountID).domain, getString(R.string.settings_server_explanation), R.drawable.ic_fluent_server_24_regular, this::onServerClick),
|
||||
new ListItem<>(R.string.sk_settings_profile, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/profile")),
|
||||
new ListItem<>(R.string.sk_settings_posting, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/preferences/other")),
|
||||
new ListItem<>(R.string.sk_settings_auth, 0, R.drawable.ic_fluent_open_24_regular, ()->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/auth/edit"), 0, true),
|
||||
contentTypesItem=new CheckableListItem<>(R.string.sk_settings_content_types, R.string.sk_settings_content_types_explanation, CheckableListItem.Style.SWITCH, lp.contentTypesEnabled, R.drawable.ic_fluent_text_edit_style_24_regular, this::onContentTypeClick),
|
||||
new ListItem<>(R.string.sk_settings_profile, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/profile")),
|
||||
new ListItem<>(R.string.sk_settings_posting, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/settings/preferences/other")),
|
||||
new ListItem<>(R.string.sk_settings_auth, 0, R.drawable.ic_fluent_open_24_regular, i->UiUtils.launchWebBrowser(getActivity(), "https://"+s.domain+"/auth/edit"), 0, true),
|
||||
contentTypesItem=new CheckableListItem<>(R.string.sk_settings_content_types, R.string.sk_settings_content_types_explanation, CheckableListItem.Style.SWITCH, lp.contentTypesEnabled, R.drawable.ic_fluent_text_edit_style_24_regular, i->onContentTypeClick()),
|
||||
defaultContentTypeItem=new ListItem<>(R.string.sk_settings_default_content_type, lp.defaultContentType.getName(), R.drawable.ic_fluent_text_bold_24_regular, this::onDefaultContentTypeClick, 0, true),
|
||||
emojiReactionsItem=new CheckableListItem<>(R.string.sk_settings_emoji_reactions, R.string.sk_settings_emoji_reactions_explanation, CheckableListItem.Style.SWITCH, lp.emojiReactionsEnabled, R.drawable.ic_fluent_emoji_laugh_24_regular, this::onEmojiReactionsClick),
|
||||
emojiReactionsItem=new CheckableListItem<>(R.string.sk_settings_emoji_reactions, R.string.sk_settings_emoji_reactions_explanation, CheckableListItem.Style.SWITCH, lp.emojiReactionsEnabled, R.drawable.ic_fluent_emoji_laugh_24_regular, i->onEmojiReactionsClick()),
|
||||
showEmojiReactionsItem=new ListItem<>(R.string.sk_settings_show_emoji_reactions, getShowEmojiReactionsString(), R.drawable.ic_fluent_emoji_24_regular, this::onShowEmojiReactionsClick, 0, true),
|
||||
localOnlyItem=new CheckableListItem<>(R.string.sk_settings_support_local_only, R.string.sk_settings_local_only_explanation, CheckableListItem.Style.SWITCH, lp.localOnlySupported, R.drawable.ic_fluent_eye_24_regular, this::onLocalOnlyClick),
|
||||
glitchModeItem=new CheckableListItem<>(R.string.sk_settings_glitch_instance, R.string.sk_settings_glitch_mode_explanation, CheckableListItem.Style.SWITCH, lp.glitchInstance, R.drawable.ic_fluent_eye_24_filled, ()->toggleCheckableItem(glitchModeItem))
|
||||
localOnlyItem=new CheckableListItem<>(R.string.sk_settings_support_local_only, R.string.sk_settings_local_only_explanation, CheckableListItem.Style.SWITCH, lp.localOnlySupported, R.drawable.ic_fluent_eye_24_regular, i->onLocalOnlyClick()),
|
||||
glitchModeItem=new CheckableListItem<>(R.string.sk_settings_glitch_instance, R.string.sk_settings_glitch_mode_explanation, CheckableListItem.Style.SWITCH, lp.glitchInstance, R.drawable.ic_fluent_eye_24_filled, i->toggleCheckableItem(glitchModeItem))
|
||||
));
|
||||
contentTypesItem.checkedChangeListener=checked->onContentTypeClick();
|
||||
defaultContentTypeItem.isEnabled=contentTypesItem.checked;
|
||||
@@ -68,7 +69,7 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
|
||||
E.post(new StatusDisplaySettingsChangedEvent(accountID));
|
||||
}
|
||||
|
||||
private void onServerClick(){
|
||||
private void onServerClick(ListItem<?> item){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
Nav.go(getActivity(), SettingsServerFragment.class, args);
|
||||
@@ -87,23 +88,23 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
|
||||
defaultContentTypeItem.subtitleRes=lp.defaultContentType.getName();
|
||||
}
|
||||
|
||||
private void onDefaultContentTypeClick(){
|
||||
int selected=lp.defaultContentType.ordinal();
|
||||
int[] newSelected={selected};
|
||||
ContentType[] supportedContentTypes=Arrays.stream(ContentType.values())
|
||||
private void onDefaultContentTypeClick(ListItem<?> item_){
|
||||
List<ContentType> supportedContentTypes=Arrays.stream(ContentType.values())
|
||||
.filter(t->t.supportedByInstance(getInstance().orElse(null)))
|
||||
.toArray(ContentType[]::new);
|
||||
String[] names=Arrays.stream(supportedContentTypes)
|
||||
.collect(Collectors.toList());
|
||||
int selected=supportedContentTypes.indexOf(lp.defaultContentType);
|
||||
int[] newSelected={selected};
|
||||
String[] names=supportedContentTypes.stream()
|
||||
.map(ContentType::getName)
|
||||
.map(this::getString)
|
||||
.toArray(String[]::new);
|
||||
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.settings_theme)
|
||||
.setTitle(R.string.sk_settings_default_content_type)
|
||||
.setSingleChoiceItems(names,
|
||||
selected, (dlg, item)->newSelected[0]=item)
|
||||
.setPositiveButton(R.string.ok, (dlg, item)->{
|
||||
ContentType type=supportedContentTypes[newSelected[0]];
|
||||
ContentType type=supportedContentTypes.get(newSelected[0]);
|
||||
lp.defaultContentType=type;
|
||||
defaultContentTypeItem.subtitleRes=type.getName();
|
||||
rebindItem(defaultContentTypeItem);
|
||||
@@ -112,7 +113,7 @@ public class SettingsInstanceFragment extends BaseSettingsFragment<Void> impleme
|
||||
.show();
|
||||
}
|
||||
|
||||
private void onShowEmojiReactionsClick(){
|
||||
private void onShowEmojiReactionsClick(ListItem<?> item_){
|
||||
int selected=lp.showEmojiReactions.ordinal();
|
||||
int[] newSelected={selected};
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.viewmodel.ListItem;
|
||||
import org.joinmastodon.android.ui.AccountSwitcherSheet;
|
||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||
import org.joinmastodon.android.ui.utils.HideableSingleViewRecyclerAdapter;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
@@ -49,7 +50,7 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
account = AccountSessionManager.get(accountID);
|
||||
account=AccountSessionManager.get(accountID);
|
||||
setTitle(R.string.settings);
|
||||
setSubtitle(account.getFullUsername());
|
||||
onDataLoaded(List.of(
|
||||
@@ -59,15 +60,17 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
|
||||
new ListItem<>(R.string.settings_notifications, 0, R.drawable.ic_fluent_alert_24_regular, this::onNotificationsClick),
|
||||
new ListItem<>(R.string.sk_settings_instance, 0, R.drawable.ic_fluent_server_24_regular, this::onInstanceClick),
|
||||
new ListItem<>(getString(R.string.about_app, getString(R.string.sk_app_name)), null, R.drawable.ic_fluent_info_24_regular, this::onAboutClick, null, 0, true),
|
||||
new ListItem<>(R.string.manage_accounts, 0, R.drawable.ic_fluent_person_swap_24_regular, this::onManageAccountsClick),
|
||||
new ListItem<>(R.string.log_out, 0, R.drawable.ic_fluent_sign_out_24_regular, this::onLogOutClick, R.attr.colorM3Error, false)
|
||||
));
|
||||
|
||||
Instance instance = AccountSessionManager.getInstance().getInstanceInfo(account.domain);
|
||||
if (!instance.isAkkoma())
|
||||
Instance instance=AccountSessionManager.getInstance().getInstanceInfo(account.domain);
|
||||
if(!instance.isAkkoma()){
|
||||
data.add(3, new ListItem<>(R.string.settings_filters, 0, R.drawable.ic_fluent_filter_24_regular, this::onFiltersClick));
|
||||
}
|
||||
|
||||
if(BuildConfig.DEBUG || BuildConfig.BUILD_TYPE.equals("appcenterPrivateBeta")){
|
||||
data.add(0, new ListItem<>("Debug settings", null, R.drawable.ic_fluent_wrench_screwdriver_24_regular, ()->Nav.go(getActivity(), SettingsDebugFragment.class, makeFragmentArgs()), null, 0, true));
|
||||
data.add(0, new ListItem<>("Debug settings", null, R.drawable.ic_fluent_wrench_screwdriver_24_regular, i->Nav.go(getActivity(), SettingsDebugFragment.class, makeFragmentArgs()), null, 0, true));
|
||||
}
|
||||
|
||||
AccountSession session=AccountSessionManager.get(accountID);
|
||||
@@ -128,35 +131,39 @@ public class SettingsMainFragment extends BaseSettingsFragment<Void>{
|
||||
return args;
|
||||
}
|
||||
|
||||
private void onBehaviorClick(){
|
||||
private void onBehaviorClick(ListItem<?> item_){
|
||||
Nav.go(getActivity(), SettingsBehaviorFragment.class, makeFragmentArgs());
|
||||
}
|
||||
|
||||
private void onDisplayClick(){
|
||||
private void onDisplayClick(ListItem<?> item_){
|
||||
Nav.go(getActivity(), SettingsDisplayFragment.class, makeFragmentArgs());
|
||||
}
|
||||
|
||||
private void onPrivacyClick(){
|
||||
private void onPrivacyClick(ListItem<?> item_){
|
||||
Nav.go(getActivity(), SettingsPrivacyFragment.class, makeFragmentArgs());
|
||||
}
|
||||
|
||||
private void onFiltersClick(){
|
||||
private void onFiltersClick(ListItem<?> item_){
|
||||
Nav.go(getActivity(), SettingsFiltersFragment.class, makeFragmentArgs());
|
||||
}
|
||||
|
||||
private void onNotificationsClick(){
|
||||
private void onNotificationsClick(ListItem<?> item_){
|
||||
Nav.go(getActivity(), SettingsNotificationsFragment.class, makeFragmentArgs());
|
||||
}
|
||||
|
||||
private void onInstanceClick(){
|
||||
private void onInstanceClick(ListItem<?> item_){
|
||||
Nav.go(getActivity(), SettingsInstanceFragment.class, makeFragmentArgs());
|
||||
}
|
||||
|
||||
private void onAboutClick(){
|
||||
private void onAboutClick(ListItem<?> item_){
|
||||
Nav.go(getActivity(), SettingsAboutAppFragment.class, makeFragmentArgs());
|
||||
}
|
||||
|
||||
private void onLogOutClick(){
|
||||
private void onManageAccountsClick(ListItem<?> item){
|
||||
new AccountSwitcherSheet(getActivity(), null).show();
|
||||
}
|
||||
|
||||
private void onLogOutClick(ListItem<?> item_){
|
||||
AccountSession session=AccountSessionManager.getInstance().getAccount(accountID);
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setMessage(getString(R.string.confirm_log_out, session.getFullUsername()))
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.joinmastodon.android.model.viewmodel.ListItem;
|
||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||
import org.joinmastodon.android.ui.utils.HideableSingleViewRecyclerAdapter;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.unifiedpush.android.connector.RegistrationDialogContent;
|
||||
import org.unifiedpush.android.connector.UnifiedPush;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -73,21 +72,21 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
|
||||
useUnifiedPush=!getDistributor(getContext()).isEmpty();
|
||||
|
||||
onDataLoaded(List.of(
|
||||
pauseItem=new CheckableListItem<>(getString(R.string.pause_all_notifications), getPauseItemSubtitle(), CheckableListItem.Style.SWITCH, false, R.drawable.ic_fluent_alert_snooze_24_regular, ()->onPauseNotificationsClick(false)),
|
||||
pauseItem=new CheckableListItem<>(getString(R.string.pause_all_notifications), getPauseItemSubtitle(), CheckableListItem.Style.SWITCH, false, R.drawable.ic_fluent_alert_snooze_24_regular, i->onPauseNotificationsClick(false)),
|
||||
policyItem=new ListItem<>(R.string.settings_notifications_policy, 0, R.drawable.ic_fluent_people_24_regular, this::onNotificationsPolicyClick, 0, true),
|
||||
|
||||
mentionsItem=new CheckableListItem<>(R.string.notification_type_mentions_and_replies, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.mention, R.drawable.ic_fluent_mention_24_regular, ()->toggleCheckableItem(mentionsItem)),
|
||||
boostsItem=new CheckableListItem<>(R.string.notification_type_reblog, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.reblog, R.drawable.ic_fluent_arrow_repeat_all_24_regular, ()->toggleCheckableItem(boostsItem)),
|
||||
favoritesItem=new CheckableListItem<>(R.string.notification_type_favorite, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.favourite, R.drawable.ic_fluent_star_24_regular, ()->toggleCheckableItem(favoritesItem)),
|
||||
followersItem=new CheckableListItem<>(R.string.notification_type_follow, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.follow, R.drawable.ic_fluent_person_add_24_regular, ()->toggleCheckableItem(followersItem)),
|
||||
pollsItem=new CheckableListItem<>(R.string.notification_type_poll, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.poll, R.drawable.ic_fluent_poll_24_regular, ()->toggleCheckableItem(pollsItem)),
|
||||
updateItem=new CheckableListItem<>(R.string.sk_notification_type_update, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.update, R.drawable.ic_fluent_history_24_regular, ()->toggleCheckableItem(updateItem)),
|
||||
postsItem=new CheckableListItem<>(R.string.sk_notification_type_posts, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.status, R.drawable.ic_fluent_chat_24_regular, ()->toggleCheckableItem(postsItem), true),
|
||||
mentionsItem=new CheckableListItem<>(R.string.notification_type_mentions_and_replies, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.mention, R.drawable.ic_fluent_mention_24_regular, i->toggleCheckableItem(mentionsItem)),
|
||||
boostsItem=new CheckableListItem<>(R.string.notification_type_reblog, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.reblog, R.drawable.ic_fluent_arrow_repeat_all_24_regular, i->toggleCheckableItem(boostsItem)),
|
||||
favoritesItem=new CheckableListItem<>(R.string.notification_type_favorite, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.favourite, R.drawable.ic_fluent_star_24_regular, i->toggleCheckableItem(favoritesItem)),
|
||||
followersItem=new CheckableListItem<>(R.string.notification_type_follow, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.follow, R.drawable.ic_fluent_person_add_24_regular, i->toggleCheckableItem(followersItem)),
|
||||
pollsItem=new CheckableListItem<>(R.string.notification_type_poll, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.poll, R.drawable.ic_fluent_poll_24_regular, i->toggleCheckableItem(pollsItem)),
|
||||
updateItem=new CheckableListItem<>(R.string.sk_notification_type_update, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.update, R.drawable.ic_fluent_history_24_regular, i->toggleCheckableItem(updateItem)),
|
||||
postsItem=new CheckableListItem<>(R.string.sk_notification_type_posts, 0, CheckableListItem.Style.CHECKBOX, pushSubscription.alerts.status, R.drawable.ic_fluent_chat_24_regular, i->toggleCheckableItem(postsItem), true),
|
||||
|
||||
uniformIconItem=new CheckableListItem<>(R.string.sk_settings_uniform_icon_for_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.uniformNotificationIcon, R.drawable.ic_ntf_logo, ()->toggleCheckableItem(uniformIconItem)),
|
||||
deleteItem=new CheckableListItem<>(R.string.sk_settings_enable_delete_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.enableDeleteNotifications, R.drawable.ic_fluent_mail_inbox_dismiss_24_regular, ()->toggleCheckableItem(deleteItem)),
|
||||
onlyLatestItem=new CheckableListItem<>(R.string.sk_settings_single_notification, 0, CheckableListItem.Style.SWITCH, lp.keepOnlyLatestNotification, R.drawable.ic_fluent_convert_range_24_regular, ()->toggleCheckableItem(onlyLatestItem), true),
|
||||
unifiedPushItem=new CheckableListItem<>(R.string.sk_settings_unifiedpush, 0, CheckableListItem.Style.SWITCH, useUnifiedPush, R.drawable.ic_fluent_alert_arrow_up_24_regular, this::onUnifiedPush, true)
|
||||
uniformIconItem=new CheckableListItem<>(R.string.sk_settings_uniform_icon_for_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.uniformNotificationIcon, R.drawable.ic_ntf_logo, i->toggleCheckableItem(uniformIconItem)),
|
||||
deleteItem=new CheckableListItem<>(R.string.sk_settings_enable_delete_notifications, 0, CheckableListItem.Style.SWITCH, GlobalUserPreferences.enableDeleteNotifications, R.drawable.ic_fluent_mail_inbox_dismiss_24_regular, i->toggleCheckableItem(deleteItem)),
|
||||
onlyLatestItem=new CheckableListItem<>(R.string.sk_settings_single_notification, 0, CheckableListItem.Style.SWITCH, lp.keepOnlyLatestNotification, R.drawable.ic_fluent_convert_range_24_regular, i->toggleCheckableItem(onlyLatestItem), true),
|
||||
unifiedPushItem=new CheckableListItem<>(R.string.sk_settings_unifiedpush, 0, CheckableListItem.Style.SWITCH, useUnifiedPush, R.drawable.ic_fluent_alert_arrow_up_24_regular, i->onUnifiedPushClick(), true)
|
||||
));
|
||||
|
||||
//only enable when distributors, who can receive notifications, are available
|
||||
@@ -98,7 +97,7 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
|
||||
|
||||
typeItems=List.of(mentionsItem, boostsItem, favoritesItem, followersItem, pollsItem, updateItem, postsItem);
|
||||
pauseItem.checkedChangeListener=checked->onPauseNotificationsClick(true);
|
||||
unifiedPushItem.checkedChangeListener=checked->onUnifiedPush();
|
||||
unifiedPushItem.checkedChangeListener=checked->onUnifiedPushClick();
|
||||
updatePolicyItem(null);
|
||||
updatePauseItem();
|
||||
}
|
||||
@@ -254,7 +253,7 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
|
||||
alert.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
|
||||
}
|
||||
|
||||
private void onNotificationsPolicyClick(){
|
||||
private void onNotificationsPolicyClick(ListItem<?> item_){
|
||||
String[] items=Stream.of(
|
||||
R.string.notifications_policy_anyone,
|
||||
R.string.notifications_policy_followed,
|
||||
@@ -328,7 +327,7 @@ public class SettingsNotificationsFragment extends BaseSettingsFragment<Void>{
|
||||
}
|
||||
}
|
||||
|
||||
private void onUnifiedPush(){
|
||||
private void onUnifiedPushClick(){
|
||||
if(getDistributor(getContext()).isEmpty()){
|
||||
List<String> distributors = UnifiedPush.getDistributors(getContext(), new ArrayList<>());
|
||||
showUnifiedPushRegisterDialog(distributors);
|
||||
|
||||
@@ -2,40 +2,98 @@ package org.joinmastodon.android.fragments.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.StatusPrivacy;
|
||||
import org.joinmastodon.android.model.viewmodel.CheckableListItem;
|
||||
import org.joinmastodon.android.model.viewmodel.ListItem;
|
||||
import org.joinmastodon.android.ui.M3AlertDialogBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SettingsPrivacyFragment extends BaseSettingsFragment<Void>{
|
||||
private CheckableListItem<Void> discoverableItem, indexableItem;
|
||||
private CheckableListItem<Void> discoverableItem, indexableItem, lockedItem;
|
||||
private ListItem<Void> privacyItem;
|
||||
private StatusPrivacy privacy=null;
|
||||
private Instance instance;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState){
|
||||
super.onCreate(savedInstanceState);
|
||||
setTitle(R.string.settings_privacy);
|
||||
Account self=AccountSessionManager.get(accountID).self;
|
||||
AccountSession session=AccountSessionManager.get(accountID);
|
||||
Account self=session.self;
|
||||
instance=AccountSessionManager.getInstance().getInstanceInfo(session.domain);
|
||||
privacy=self.source.privacy;
|
||||
onDataLoaded(List.of(
|
||||
discoverableItem=new CheckableListItem<>(R.string.settings_discoverable, 0, CheckableListItem.Style.SWITCH, self.discoverable, R.drawable.ic_fluent_thumb_like_dislike_24_regular, ()->toggleCheckableItem(discoverableItem)),
|
||||
indexableItem=new CheckableListItem<>(R.string.settings_indexable, 0, CheckableListItem.Style.SWITCH, self.source.indexable!=null ? self.source.indexable : true, R.drawable.ic_fluent_search_24_regular, ()->toggleCheckableItem(indexableItem))
|
||||
privacyItem=new ListItem<>(R.string.sk_settings_default_visibility, getPrivacyString(privacy), R.drawable.ic_fluent_eye_24_regular, this::onPrivacyClick, 0, true),
|
||||
lockedItem=new CheckableListItem<>(R.string.sk_settings_lock_account, 0, CheckableListItem.Style.SWITCH, self.locked, R.drawable.ic_fluent_person_available_24_regular, i->toggleCheckableItem(lockedItem))
|
||||
));
|
||||
if(self.source.indexable==null)
|
||||
indexableItem.isEnabled=false;
|
||||
|
||||
if(!instance.isAkkoma()){
|
||||
data.addAll(List.of(
|
||||
discoverableItem=new CheckableListItem<>(R.string.settings_discoverable, 0, CheckableListItem.Style.SWITCH, self.discoverable, R.drawable.ic_fluent_thumb_like_dislike_24_regular, i->toggleCheckableItem(discoverableItem)),
|
||||
indexableItem=new CheckableListItem<>(R.string.settings_indexable, 0, CheckableListItem.Style.SWITCH, self.source.indexable!=null ? self.source.indexable : true, R.drawable.ic_fluent_search_24_regular, i->toggleCheckableItem(indexableItem))
|
||||
));
|
||||
if(self.source.indexable==null)
|
||||
indexableItem.isEnabled=false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){}
|
||||
|
||||
private @StringRes int getPrivacyString(StatusPrivacy p){
|
||||
if(p==null) return R.string.visibility_public;
|
||||
return switch(p){
|
||||
case PUBLIC -> R.string.visibility_public;
|
||||
case UNLISTED -> R.string.sk_visibility_unlisted;
|
||||
case PRIVATE -> R.string.visibility_followers_only;
|
||||
case DIRECT -> R.string.visibility_private;
|
||||
case LOCAL -> R.string.sk_local_only;
|
||||
};
|
||||
}
|
||||
|
||||
private void onPrivacyClick(ListItem<?> item_){
|
||||
Account self=AccountSessionManager.get(accountID).self;
|
||||
List<StatusPrivacy> options=new ArrayList<>(List.of(StatusPrivacy.PUBLIC, StatusPrivacy.UNLISTED, StatusPrivacy.PRIVATE, StatusPrivacy.DIRECT));
|
||||
if(instance.isAkkoma()) options.add(StatusPrivacy.LOCAL);
|
||||
int selected=options.indexOf(self.source.privacy);
|
||||
int[] newSelected={selected};
|
||||
new M3AlertDialogBuilder(getActivity())
|
||||
.setTitle(R.string.sk_settings_default_visibility)
|
||||
.setSingleChoiceItems(options.stream().map(this::getPrivacyString).map(this::getString).toArray(String[]::new),
|
||||
selected, (dlg, item)->newSelected[0]=item)
|
||||
.setPositiveButton(R.string.ok, (dlg, item)->{
|
||||
privacy=options.get(newSelected[0]);
|
||||
privacyItem.subtitleRes=getPrivacyString(privacy);
|
||||
rebindItem(privacyItem);
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause(){
|
||||
super.onPause();
|
||||
Account self=AccountSessionManager.get(accountID).self;
|
||||
if(self.discoverable!=discoverableItem.checked || (self.source.indexable!=null && self.source.indexable!=indexableItem.checked)){
|
||||
self.discoverable=discoverableItem.checked;
|
||||
self.source.indexable=indexableItem.checked;
|
||||
AccountSessionManager.get(accountID).savePreferencesLater();
|
||||
AccountSession s=AccountSessionManager.get(accountID);
|
||||
Account self=s.self;
|
||||
boolean savePlease=self.locked!=lockedItem.checked
|
||||
|| self.source.privacy!=privacy
|
||||
|| (discoverableItem!=null && self.discoverable!=discoverableItem.checked)
|
||||
|| (indexableItem!=null && self.source.indexable!=null && self.source.indexable!=indexableItem.checked);
|
||||
if(savePlease){
|
||||
if(discoverableItem!=null) self.discoverable=discoverableItem.checked;
|
||||
if(indexableItem!=null) self.source.indexable=indexableItem.checked;
|
||||
self.locked=lockedItem.checked;
|
||||
s.preferences.postingDefaultVisibility=privacy;
|
||||
s.savePreferencesLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ public class SettingsServerAboutFragment extends LoaderFragment{
|
||||
if(!TextUtils.isEmpty(instance.email)){
|
||||
needDivider=true;
|
||||
SimpleListItemViewHolder holder=new SimpleListItemViewHolder(getActivity(), scrollingLayout);
|
||||
ListItem<Void> item=new ListItem<>(R.string.send_email_to_server_admin, 0, R.drawable.ic_fluent_mail_24_regular, ()->{});
|
||||
ListItem<Void> item=new ListItem<>(R.string.send_email_to_server_admin, 0, R.drawable.ic_fluent_mail_24_regular, i->{});
|
||||
holder.bind(item);
|
||||
holder.itemView.setBackground(UiUtils.getThemeDrawable(getActivity(), android.R.attr.selectableItemBackground));
|
||||
holder.itemView.setOnClickListener(v->openAdminEmail());
|
||||
|
||||
@@ -6,8 +6,6 @@ import android.text.TextUtils;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.joinmastodon.android.api.ObjectValidationException;
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
import org.joinmastodon.android.api.requests.instance.GetInstance;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -15,9 +13,6 @@ import java.time.LocalDate;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
|
||||
/**
|
||||
* Represents a user of Mastodon and their associated profile.
|
||||
*/
|
||||
@@ -163,26 +158,26 @@ public class Account extends BaseModel implements Searchable{
|
||||
if(fields!=null){
|
||||
for(AccountField f:fields)
|
||||
f.postprocess();
|
||||
} else {
|
||||
fields = Collections.emptyList();
|
||||
}else{
|
||||
fields=Collections.emptyList();
|
||||
}
|
||||
if(emojis!=null){
|
||||
for(Emoji e:emojis)
|
||||
e.postprocess();
|
||||
} else {
|
||||
emojis = Collections.emptyList();
|
||||
}else{
|
||||
emojis=Collections.emptyList();
|
||||
}
|
||||
if(moved!=null)
|
||||
moved.postprocess();
|
||||
if(fqn == null) fqn = getFullyQualifiedName();
|
||||
if(id == null) id = "";
|
||||
if(username == null) username = "";
|
||||
if(fqn==null) fqn=getFullyQualifiedName();
|
||||
if(id==null) id="";
|
||||
if(username==null) username="";
|
||||
if(TextUtils.isEmpty(displayName))
|
||||
displayName = !TextUtils.isEmpty(username) ? username : "";
|
||||
if(acct == null) acct = "";
|
||||
if(url == null) url = "";
|
||||
if(note == null) note = "";
|
||||
if(avatar == null) avatar = "";
|
||||
displayName=!TextUtils.isEmpty(username) ? username : "";
|
||||
if(acct==null) acct="";
|
||||
if(url==null) url="";
|
||||
if(note==null) note="";
|
||||
if(avatar==null) avatar="";
|
||||
}
|
||||
|
||||
public boolean isLocal(){
|
||||
@@ -212,6 +207,10 @@ public class Account extends BaseModel implements Searchable{
|
||||
return fqn != null ? fqn : acct.split("@")[0] + "@" + getDomainFromURL();
|
||||
}
|
||||
|
||||
public String getDisplayName(){
|
||||
return '\u2068'+displayName+'\u2069';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(){
|
||||
return "Account{"+
|
||||
|
||||
@@ -26,22 +26,13 @@ import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
import org.joinmastodon.android.api.ObjectValidationException;
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.events.EmojiReactionsUpdatedEvent;
|
||||
import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.utils.StatusTextEncoder;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Parcel
|
||||
@@ -104,6 +95,7 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
||||
private transient String strippedText;
|
||||
public transient TranslationState translationState=TranslationState.HIDDEN;
|
||||
public transient Translation translation;
|
||||
public transient boolean fromStatusCreated;
|
||||
|
||||
public Status(){}
|
||||
|
||||
@@ -203,6 +195,10 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
||||
return reblog!=null ? reblog : this;
|
||||
}
|
||||
|
||||
public String getContentStatusID(){
|
||||
return getContentStatus().id;
|
||||
}
|
||||
|
||||
public String getStrippedText(){
|
||||
if(strippedText==null)
|
||||
strippedText=HtmlParser.strip(content);
|
||||
|
||||
@@ -33,9 +33,9 @@ public class AccountViewModel{
|
||||
V.dp(50), V.dp(50));
|
||||
emojiHelper=new CustomEmojiHelper();
|
||||
if(session.getLocalPreferences().customEmojiInNames)
|
||||
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
|
||||
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
|
||||
else
|
||||
parsedName=account.displayName;
|
||||
parsedName=account.getDisplayName();
|
||||
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
||||
SpannableStringBuilder ssb=new SpannableStringBuilder(parsedName);
|
||||
ssb.append(parsedBio);
|
||||
|
||||
@@ -9,42 +9,42 @@ public class CheckableListItem<T> extends ListItem<T>{
|
||||
public boolean checked;
|
||||
public Consumer<Boolean> checkedChangeListener;
|
||||
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick, T parentObject, boolean dividerAfter){
|
||||
super(title, subtitle, iconRes, onClick, parentObject, 0, dividerAfter);
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick, T parentObject, boolean dividerAfter){
|
||||
super(title, subtitle, iconRes, (Consumer<ListItem<T>>)(Object)onClick, parentObject, 0, dividerAfter);
|
||||
this.style=style;
|
||||
this.checked=checked;
|
||||
}
|
||||
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Runnable onClick){
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick){
|
||||
this(title, subtitle, style, checked, 0, onClick, null, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Runnable onClick, T parentObject){
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick, T parentObject){
|
||||
this(title, subtitle, style, checked, 0, onClick, parentObject, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick){
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick){
|
||||
this(title, subtitle, style, checked, iconRes, onClick, null, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Runnable onClick, T parentObject){
|
||||
public CheckableListItem(String title, String subtitle, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick, T parentObject){
|
||||
this(title, subtitle, style, checked, iconRes, onClick, parentObject, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Runnable onClick){
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick){
|
||||
this(titleRes, subtitleRes, style, checked, 0, onClick, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Runnable onClick, boolean dividerAfter){
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, Consumer<CheckableListItem<T>> onClick, boolean dividerAfter){
|
||||
this(titleRes, subtitleRes, style, checked, 0, onClick, dividerAfter);
|
||||
}
|
||||
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Runnable onClick){
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick){
|
||||
this(titleRes, subtitleRes, style, checked, iconRes, onClick, false);
|
||||
}
|
||||
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Runnable onClick, boolean dividerAfter){
|
||||
super(titleRes, subtitleRes, iconRes, onClick, 0, dividerAfter);
|
||||
public CheckableListItem(int titleRes, int subtitleRes, Style style, boolean checked, int iconRes, Consumer<CheckableListItem<T>> onClick, boolean dividerAfter){
|
||||
super(titleRes, subtitleRes, iconRes, (Consumer<ListItem<T>>)(Object)onClick, 0, dividerAfter);
|
||||
this.style=style;
|
||||
this.checked=checked;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package org.joinmastodon.android.model.viewmodel;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
@@ -16,11 +18,11 @@ public class ListItem<T>{
|
||||
public int iconRes;
|
||||
public int colorOverrideAttr;
|
||||
public boolean dividerAfter;
|
||||
public Runnable onClick;
|
||||
private Consumer<ListItem<T>> onClick;
|
||||
public boolean isEnabled=true;
|
||||
public T parentObject;
|
||||
|
||||
public ListItem(String title, String subtitle, int iconRes, Runnable onClick, T parentObject, int colorOverrideAttr, boolean dividerAfter){
|
||||
public ListItem(String title, String subtitle, int iconRes, Consumer<ListItem<T>> onClick, T parentObject, int colorOverrideAttr, boolean dividerAfter){
|
||||
this.title=title;
|
||||
this.subtitle=subtitle;
|
||||
this.iconRes=iconRes;
|
||||
@@ -32,45 +34,41 @@ public class ListItem<T>{
|
||||
isEnabled=false;
|
||||
}
|
||||
|
||||
public ListItem(String title, String subtitle, Runnable onClick){
|
||||
public ListItem(String title, String subtitle, Consumer<ListItem<T>> onClick){
|
||||
this(title, subtitle, 0, onClick, null, 0, false);
|
||||
}
|
||||
|
||||
public ListItem(String title, String subtitle, Runnable onClick, T parentObject){
|
||||
public ListItem(String title, String subtitle, Consumer<ListItem<T>> onClick, T parentObject){
|
||||
this(title, subtitle, 0, onClick, parentObject, 0, false);
|
||||
}
|
||||
|
||||
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick){
|
||||
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick){
|
||||
this(title, subtitle, iconRes, onClick, null, 0, false);
|
||||
}
|
||||
|
||||
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick, boolean dividerAfter){
|
||||
this(title, subtitle, iconRes, onClick, null, 0, dividerAfter);
|
||||
}
|
||||
|
||||
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Runnable onClick, T parentObject){
|
||||
public ListItem(String title, String subtitle, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick, T parentObject){
|
||||
this(title, subtitle, iconRes, onClick, parentObject, 0, false);
|
||||
}
|
||||
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Runnable onClick){
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Consumer<ListItem<T>> onClick){
|
||||
this(null, null, 0, onClick, null, 0, false);
|
||||
this.titleRes=titleRes;
|
||||
this.subtitleRes=subtitleRes;
|
||||
}
|
||||
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Runnable onClick, int colorOverrideAttr, boolean dividerAfter){
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, Consumer<ListItem<T>> onClick, int colorOverrideAttr, boolean dividerAfter){
|
||||
this(null, null, 0, onClick, null, colorOverrideAttr, dividerAfter);
|
||||
this.titleRes=titleRes;
|
||||
this.subtitleRes=subtitleRes;
|
||||
}
|
||||
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Runnable onClick){
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick){
|
||||
this(null, null, iconRes, onClick, null, 0, false);
|
||||
this.titleRes=titleRes;
|
||||
this.subtitleRes=subtitleRes;
|
||||
}
|
||||
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Runnable onClick, int colorOverrideAttr, boolean dividerAfter){
|
||||
public ListItem(@StringRes int titleRes, @StringRes int subtitleRes, @DrawableRes int iconRes, Consumer<ListItem<T>> onClick, int colorOverrideAttr, boolean dividerAfter){
|
||||
this(null, null, iconRes, onClick, null, colorOverrideAttr, dividerAfter);
|
||||
this.titleRes=titleRes;
|
||||
this.subtitleRes=subtitleRes;
|
||||
@@ -79,4 +77,13 @@ public class ListItem<T>{
|
||||
public int getItemViewType(){
|
||||
return colorOverrideAttr==0 ? R.id.list_item_simple : R.id.list_item_simple_tinted;
|
||||
}
|
||||
|
||||
public void performClick(){
|
||||
if(onClick!=null)
|
||||
onClick.accept(this);
|
||||
}
|
||||
|
||||
public <I extends ListItem<T>> void setOnClick(Consumer<I> onClick){
|
||||
this.onClick=(Consumer<ListItem<T>>) onClick;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import android.graphics.drawable.Animatable;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
@@ -27,6 +27,8 @@ import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.HomeFragment;
|
||||
import org.joinmastodon.android.fragments.SplashFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.CustomWelcomeFragment;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.ui.views.CheckableRelativeLayout;
|
||||
|
||||
@@ -40,7 +42,6 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import me.grishka.appkit.FragmentStackActivity;
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.api.Callback;
|
||||
import me.grishka.appkit.api.ErrorResponse;
|
||||
@@ -282,7 +283,7 @@ public class AccountSwitcherSheet extends BottomSheet{
|
||||
@SuppressLint("SetTextI18n")
|
||||
@Override
|
||||
public void onBind(AccountSession item){
|
||||
name.setText(item.self.displayName);
|
||||
HtmlParser.setTextWithCustomEmoji(name, item.self.getDisplayName(), item.self.emojis);
|
||||
username.setText(item.getFullUsername());
|
||||
radioButton.setVisibility(externalShare ? View.GONE : View.VISIBLE);
|
||||
extraBtnWrap.setVisibility(externalShare && openInApp ? View.VISIBLE : View.GONE);
|
||||
|
||||
@@ -26,9 +26,7 @@ import org.joinmastodon.android.ui.utils.CustomEmojiHelper;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.ui.views.ProgressBarButton;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import me.grishka.appkit.imageloader.ImageLoaderViewHolder;
|
||||
import me.grishka.appkit.imageloader.requests.ImageLoaderRequest;
|
||||
@@ -53,9 +51,9 @@ public class AccountCardStatusDisplayItem extends StatusDisplayItem{
|
||||
coverRequest=new UrlImageLoaderRequest(account.header, 1000, 1000);
|
||||
parsedBio=HtmlParser.parse(account.note, account.emojis, Collections.emptyList(), Collections.emptyList(), parentFragment.getAccountID());
|
||||
if(account.emojis.isEmpty()){
|
||||
parsedName=account.displayName;
|
||||
parsedName=account.getDisplayName();
|
||||
}else{
|
||||
parsedName=HtmlParser.parseCustomEmoji(account.displayName, account.emojis);
|
||||
parsedName=HtmlParser.parseCustomEmoji(account.getDisplayName(), account.emojis);
|
||||
emojiHelper.setText(new SpannableStringBuilder(parsedName).append(parsedBio));
|
||||
}
|
||||
}
|
||||
@@ -149,7 +147,7 @@ public class AccountCardStatusDisplayItem extends StatusDisplayItem{
|
||||
followingCount.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
followingLabel.setVisibility(item.account.followingCount < 0 ? View.GONE : View.VISIBLE);
|
||||
relationship=item.parentFragment.getRelationship(item.account.id);
|
||||
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), null, findViewById(R.id.pronouns), true, false, false, item.account);
|
||||
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), null,true, false, false, item.account);
|
||||
|
||||
if(item.notification.type==Notification.Type.FOLLOW_REQUEST && (relationship==null || !relationship.followedBy)){
|
||||
actionWrap.setVisibility(View.GONE);
|
||||
|
||||
@@ -96,7 +96,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
GlobalUserPreferences.playGifs ? user.avatar : user.avatarStatic,
|
||||
V.dp(50), V.dp(50));
|
||||
this.accountID=accountID;
|
||||
parsedName=new SpannableStringBuilder(user.displayName);
|
||||
parsedName=new SpannableStringBuilder(user.getDisplayName());
|
||||
this.status=status;
|
||||
this.notification=notification;
|
||||
this.scheduledStatus=scheduledStatus;
|
||||
@@ -137,7 +137,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<HeaderStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final TextView name, time, username, extraText, pronouns;
|
||||
private final TextView name, time, username, extraText;
|
||||
private final View collapseBtn, timeUsernameSeparator;
|
||||
private final ImageView avatar, more, visibility, deleteNotification, unreadIndicator, markAsRead, collapseBtnIcon, botIcon;
|
||||
private final PopupMenu optionsMenu;
|
||||
@@ -164,7 +164,6 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
collapseBtn=findViewById(R.id.collapse_btn);
|
||||
collapseBtnIcon=findViewById(R.id.collapse_btn_icon);
|
||||
extraText=findViewById(R.id.extra_text);
|
||||
pronouns=findViewById(R.id.pronouns);
|
||||
avatar.setOnClickListener(this::onAvaClick);
|
||||
avatar.setOutlineProvider(OutlineProviders.roundedRect(12));
|
||||
avatar.setClipToOutline(true);
|
||||
@@ -332,7 +331,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
if(TextUtils.isEmpty(item.extraText)){
|
||||
if (item.status != null) {
|
||||
boolean displayPronouns=item.parentFragment instanceof ThreadFragment ? GlobalUserPreferences.displayPronounsInThreads : GlobalUserPreferences.displayPronounsInTimelines;
|
||||
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), extraText, pronouns, displayPronouns, item.status.visibility==StatusPrivacy.DIRECT, item.status.localOnly || item.status.visibility==StatusPrivacy.LOCAL, item.status.account);
|
||||
UiUtils.setExtraTextInfo(item.parentFragment.getContext(), extraText, displayPronouns, item.status.visibility==StatusPrivacy.DIRECT, item.status.localOnly || item.status.visibility==StatusPrivacy.LOCAL, item.status.account);
|
||||
}
|
||||
}else{
|
||||
extraText.setVisibility(View.VISIBLE);
|
||||
|
||||
@@ -18,7 +18,6 @@ import android.widget.TextView;
|
||||
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.session.AccountLocalPreferences;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.BaseStatusListFragment;
|
||||
@@ -62,7 +61,7 @@ public class NotificationHeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
TextUtils.isEmpty(notification.account.avatar) ? session.getDefaultAvatarUrl() :
|
||||
GlobalUserPreferences.playGifs ? notification.account.avatar : notification.account.avatarStatic,
|
||||
V.dp(50), V.dp(50));
|
||||
SpannableStringBuilder parsedName=new SpannableStringBuilder(notification.account.displayName);
|
||||
SpannableStringBuilder parsedName=new SpannableStringBuilder(notification.account.getDisplayName());
|
||||
HtmlParser.parseCustomEmoji(parsedName, notification.account.emojis);
|
||||
String str = parentFragment.getString(switch(notification.type){
|
||||
case FOLLOW -> R.string.user_followed_you;
|
||||
|
||||
@@ -87,8 +87,9 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
|
||||
@Override
|
||||
public ImageLoaderRequest getImageRequest(int index){
|
||||
CustomEmojiHelper helper=index<emojiHelper.getImageCount() ? emojiHelper : extra.emojiHelper;
|
||||
return helper.getImageRequest(index%emojiHelper.getImageCount());
|
||||
int firstHelperCount=emojiHelper.getImageCount();
|
||||
CustomEmojiHelper helper=index<firstHelperCount ? emojiHelper : extra.emojiHelper;
|
||||
return helper.getImageRequest(firstHelperCount>0 ? index%firstHelperCount : index);
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<ReblogOrReplyLineStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
@@ -136,8 +137,9 @@ public class ReblogOrReplyLineStatusDisplayItem extends StatusDisplayItem{
|
||||
|
||||
@Override
|
||||
public void setImage(int index, Drawable image){
|
||||
CustomEmojiHelper helper=index<item.emojiHelper.getImageCount() ? item.emojiHelper : item.extra.emojiHelper;
|
||||
helper.setImageDrawable(index%item.emojiHelper.getImageCount(), image);
|
||||
int firstHelperCount=item.emojiHelper.getImageCount();
|
||||
CustomEmojiHelper helper=index<firstHelperCount ? item.emojiHelper : item.extra.emojiHelper;
|
||||
helper.setImageDrawable(firstHelperCount>0 ? index%firstHelperCount : index, image);
|
||||
text.invalidate();
|
||||
extraText.invalidate();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.session.AccountLocalPreferences;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
@@ -30,7 +29,6 @@ import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.model.DisplayItemsParent;
|
||||
import org.joinmastodon.android.model.LegacyFilter;
|
||||
import org.joinmastodon.android.model.FilterAction;
|
||||
import org.joinmastodon.android.model.FilterContext;
|
||||
import org.joinmastodon.android.model.FilterResult;
|
||||
import org.joinmastodon.android.model.Notification;
|
||||
@@ -41,7 +39,6 @@ import org.joinmastodon.android.ui.PhotoLayoutHelper;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.ui.viewholders.AccountViewHolder;
|
||||
import org.joinmastodon.android.utils.StatusFilterPredicate;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -92,7 +89,7 @@ public abstract class StatusDisplayItem{
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public String getContentID(){
|
||||
public String getContentStatusID(){
|
||||
if(parentFragment instanceof StatusListFragment slf){
|
||||
Status s=slf.getContentStatusByID(parentID);
|
||||
return s!=null ? s.id : parentID;
|
||||
@@ -142,11 +139,11 @@ public abstract class StatusDisplayItem{
|
||||
String parentID = parent.getID();
|
||||
String text = threadReply ? fragment.getString(R.string.sk_show_thread)
|
||||
: account == null ? fragment.getString(R.string.sk_in_reply)
|
||||
: status.reblog != null ? account.displayName
|
||||
: fragment.getString(R.string.in_reply_to, account.displayName);
|
||||
: status.reblog != null ? account.getDisplayName()
|
||||
: fragment.getString(R.string.in_reply_to, account.getDisplayName());
|
||||
String fullText = threadReply ? fragment.getString(R.string.sk_show_thread)
|
||||
: account == null ? fragment.getString(R.string.sk_in_reply)
|
||||
: fragment.getString(R.string.in_reply_to, account.displayName);
|
||||
: fragment.getString(R.string.in_reply_to, account.getDisplayName());
|
||||
return new ReblogOrReplyLineStatusDisplayItem(
|
||||
parentID, fragment, text, account == null ? List.of() : account.emojis,
|
||||
R.drawable.ic_fluent_arrow_reply_20sp_filled, null, null, fullText, status
|
||||
@@ -176,12 +173,11 @@ public abstract class StatusDisplayItem{
|
||||
|
||||
if(status.reblog!=null){
|
||||
boolean isOwnPost = AccountSessionManager.getInstance().isSelf(fragment.getAccountID(), status.account);
|
||||
String fullText = fragment.getString(R.string.user_boosted, status.account.displayName);
|
||||
String text = replyLine != null ? status.account.displayName : fullText;
|
||||
String text=fragment.getString(R.string.user_boosted, status.account.getDisplayName());
|
||||
items.add(new ReblogOrReplyLineStatusDisplayItem(parentID, fragment, text, status.account.emojis, R.drawable.ic_fluent_arrow_repeat_all_20sp_filled, isOwnPost ? status.visibility : null, i->{
|
||||
args.putParcelable("profileAccount", Parcels.wrap(status.account));
|
||||
Nav.go(fragment.getActivity(), ProfileFragment.class, args);
|
||||
}, fullText, status));
|
||||
}, null, status));
|
||||
} else if (!(status.tags.isEmpty() ||
|
||||
fragment instanceof HashtagTimelineFragment ||
|
||||
fragment instanceof ListTimelineFragment
|
||||
|
||||
@@ -210,9 +210,10 @@ public class TextStatusDisplayItem extends StatusDisplayItem{
|
||||
Translation existingTrans=item.status.getContentStatus().translation;
|
||||
String existingTransLang=existingTrans!=null ? existingTrans.detectedSourceLanguage : null;
|
||||
String lang=existingTransLang!=null ? existingTransLang : item.status.getContentStatus().language;
|
||||
String displayLang=Locale.forLanguageTag(lang != null ? lang
|
||||
: AccountSessionManager.get(item.parentFragment.getAccountID()).preferences.postingDefaultLanguage).getDisplayLanguage();
|
||||
translationButton.setText(item.parentFragment.getString(R.string.translate_post, !displayLang.isBlank() ? displayLang : lang));
|
||||
Locale locale=lang!=null ? Locale.forLanguageTag(lang) : null;
|
||||
translationButton.setText(locale!=null
|
||||
? item.parentFragment.getString(R.string.translate_post, locale.getDisplayLanguage())
|
||||
: item.parentFragment.getString(R.string.sk_translate_post));
|
||||
translationButton.setClickable(true);
|
||||
translationButton.animate().alpha(1).setDuration(100).start();
|
||||
translationInfo.setVisibility(View.GONE);
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
package org.joinmastodon.android.ui.utils;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.IntEvaluator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.view.ActionMode;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
|
||||
import org.joinmastodon.android.R;
|
||||
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
import me.grishka.appkit.FragmentStackActivity;
|
||||
import me.grishka.appkit.fragments.AppKitFragment;
|
||||
|
||||
public class ActionModeHelper{
|
||||
public static ActionMode startActionMode(AppKitFragment fragment, IntSupplier statusBarColorSupplier, ActionMode.Callback callback){
|
||||
FragmentStackActivity activity=(FragmentStackActivity) fragment.getActivity();
|
||||
return activity.startActionMode(new ActionMode.Callback(){
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu){
|
||||
if(!callback.onCreateActionMode(mode, menu))
|
||||
return false;
|
||||
ObjectAnimator anim=ObjectAnimator.ofInt(activity.getWindow(), "statusBarColor", statusBarColorSupplier.getAsInt(), UiUtils.getThemeColor(activity, R.attr.colorM3Primary));
|
||||
anim.setEvaluator(new IntEvaluator(){
|
||||
@Override
|
||||
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
|
||||
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
activity.invalidateSystemBarColors(fragment);
|
||||
View fakeView=new View(activity);
|
||||
// mode.setCustomView(fakeView);
|
||||
// int buttonID=activity.getResources().getIdentifier("action_mode_close_button", "id", "android");
|
||||
// View btn=activity.getWindow().getDecorView().findViewById(buttonID);
|
||||
// if(btn!=null){
|
||||
// ((ViewGroup.MarginLayoutParams)btn.getLayoutParams()).setMarginEnd(0);
|
||||
// }
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu){
|
||||
if(!callback.onPrepareActionMode(mode, menu))
|
||||
return false;
|
||||
for(int i=0;i<menu.size();i++){
|
||||
Drawable icon=menu.getItem(i).getIcon();
|
||||
if(icon!=null){
|
||||
icon=icon.mutate();
|
||||
icon.setTint(UiUtils.getThemeColor(activity, R.attr.colorM3OnPrimary));
|
||||
menu.getItem(i).setIcon(icon);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item){
|
||||
return callback.onActionItemClicked(mode, item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode){
|
||||
ObjectAnimator anim=ObjectAnimator.ofInt(activity.getWindow(), "statusBarColor", UiUtils.getThemeColor(activity, R.attr.colorM3Primary), statusBarColorSupplier.getAsInt());
|
||||
anim.setEvaluator(new IntEvaluator(){
|
||||
@Override
|
||||
public Integer evaluate(float fraction, Integer startValue, Integer endValue){
|
||||
return UiUtils.alphaBlendColors(startValue, endValue, fraction);
|
||||
}
|
||||
});
|
||||
anim.addListener(new AnimatorListenerAdapter(){
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation){
|
||||
activity.getWindow().setStatusBarColor(0);
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
activity.invalidateSystemBarColors(fragment);
|
||||
callback.onDestroyActionMode(mode);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -480,7 +480,7 @@ public class UiUtils {
|
||||
|
||||
public static void confirmToggleBlockUser(Activity activity, String accountID, Account account, boolean currentlyBlocked, Consumer<Relationship> resultCallback) {
|
||||
showConfirmationAlert(activity, activity.getString(currentlyBlocked ? R.string.confirm_unblock_title : R.string.confirm_block_title),
|
||||
activity.getString(currentlyBlocked ? R.string.confirm_unblock : R.string.confirm_block, account.displayName),
|
||||
activity.getString(currentlyBlocked ? R.string.confirm_unblock : R.string.confirm_block, account.getDisplayName()),
|
||||
activity.getString(currentlyBlocked ? R.string.do_unblock : R.string.do_block),
|
||||
R.drawable.ic_fluent_person_prohibited_28_regular,
|
||||
() -> {
|
||||
@@ -508,7 +508,7 @@ public class UiUtils {
|
||||
public static void confirmSoftBlockUser(Activity activity, String accountID, Account account, Consumer<Relationship> resultCallback) {
|
||||
showConfirmationAlert(activity,
|
||||
activity.getString(R.string.sk_remove_follower),
|
||||
activity.getString(R.string.sk_remove_follower_confirm, account.displayName),
|
||||
activity.getString(R.string.sk_remove_follower_confirm, account.getDisplayName()),
|
||||
activity.getString(R.string.sk_do_remove_follower),
|
||||
R.drawable.ic_fluent_person_delete_24_regular,
|
||||
() -> new SetAccountBlocked(account.id, true).setCallback(new Callback<>() {
|
||||
@@ -566,7 +566,7 @@ public class UiUtils {
|
||||
params.setMargins(0, V.dp(-12), 0, 0);
|
||||
durationView.setLayoutParams(params);
|
||||
Button button=durationView.findViewById(R.id.button);
|
||||
((TextView) durationView.findViewById(R.id.message)).setText(context.getString(R.string.confirm_mute, account.displayName));
|
||||
((TextView) durationView.findViewById(R.id.message)).setText(context.getString(R.string.confirm_mute, account.getDisplayName()));
|
||||
|
||||
AtomicReference<Duration> muteDuration=new AtomicReference<>(Duration.ZERO);
|
||||
|
||||
@@ -600,7 +600,7 @@ public class UiUtils {
|
||||
|
||||
new M3AlertDialogBuilder(context)
|
||||
.setTitle(context.getString(currentlyMuted ? R.string.confirm_unmute_title : R.string.confirm_mute_title))
|
||||
.setMessage(currentlyMuted ? context.getString(R.string.confirm_unmute, account.displayName) : null)
|
||||
.setMessage(currentlyMuted ? context.getString(R.string.confirm_unmute, account.getDisplayName()) : null)
|
||||
.setView(currentlyMuted ? null : durationView)
|
||||
.setPositiveButton(context.getString(currentlyMuted ? R.string.do_unmute : R.string.do_mute), (dlg, i)->{
|
||||
new SetAccountMuted(account.id, !currentlyMuted, muteDuration.get().getSeconds())
|
||||
@@ -638,11 +638,8 @@ public class UiUtils {
|
||||
@Override
|
||||
public void onSuccess(Status result) {
|
||||
resultCallback.accept(result);
|
||||
CacheController cache=AccountSessionManager.get(accountID).getCacheController();
|
||||
cache.deleteStatus(s.id);
|
||||
E.post(new StatusDeletedEvent(s.id, accountID));
|
||||
if(status!=s){
|
||||
cache.deleteStatus(status.id);
|
||||
E.post(new StatusDeletedEvent(status.id, accountID));
|
||||
}
|
||||
}
|
||||
@@ -1110,23 +1107,21 @@ public class UiUtils {
|
||||
return back;
|
||||
}
|
||||
|
||||
public static boolean setExtraTextInfo(Context ctx, @Nullable TextView extraText, @Nullable TextView pronouns, boolean displayPronouns, boolean mentionedOnly, boolean localOnly, @Nullable Account account) {
|
||||
List<String> extraParts = extraText!=null && (localOnly || mentionedOnly) ? new ArrayList<>() : null;
|
||||
Optional<String> p=pronouns==null || !displayPronouns ? Optional.empty() : extractPronouns(ctx, account);
|
||||
if(p.isPresent()) {
|
||||
HtmlParser.setTextWithCustomEmoji(pronouns, p.get(), account.emojis);
|
||||
pronouns.setVisibility(View.VISIBLE);
|
||||
}else if(pronouns!=null){
|
||||
pronouns.setVisibility(View.GONE);
|
||||
}
|
||||
public static boolean setExtraTextInfo(Context ctx, @Nullable TextView extraText, boolean displayPronouns, boolean mentionedOnly, boolean localOnly, @Nullable Account account) {
|
||||
List<String> extraParts=new ArrayList<>();
|
||||
Optional<String> p=!displayPronouns ? Optional.empty() : extractPronouns(ctx, account);
|
||||
|
||||
if(localOnly)
|
||||
extraParts.add(ctx.getString(R.string.sk_inline_local_only));
|
||||
if(mentionedOnly)
|
||||
extraParts.add(ctx.getString(R.string.sk_inline_direct));
|
||||
if(extraText!=null && extraParts!=null && !extraParts.isEmpty()) {
|
||||
String sepp = ctx.getString(R.string.sk_separator);
|
||||
String text = String.join(" " + sepp + " ", extraParts);
|
||||
if(account == null) extraText.setText(text);
|
||||
if(p.isPresent() && extraParts.isEmpty())
|
||||
extraParts.add(p.get());
|
||||
|
||||
if(extraText!=null && !extraParts.isEmpty()) {
|
||||
String sepp=ctx.getString(R.string.sk_separator);
|
||||
String text=String.join(" " + sepp + " ", extraParts);
|
||||
if(account==null) extraText.setText(text);
|
||||
else HtmlParser.setTextWithCustomEmoji(extraText, text, account.emojis);
|
||||
extraText.setVisibility(View.VISIBLE);
|
||||
return true;
|
||||
@@ -1702,14 +1697,17 @@ public class UiUtils {
|
||||
|
||||
Matcher matcher=trimPronouns.matcher(text);
|
||||
if(!matcher.find()) return null;
|
||||
String matched=matcher.group(1);
|
||||
String pronouns=matcher.group(1);
|
||||
// crude fix to allow for pronouns like "it(/she)"
|
||||
int missingClosingParens=0;
|
||||
for(char c : matched.toCharArray()){
|
||||
for(char c : pronouns.toCharArray()){
|
||||
if(c=='(') missingClosingParens++;
|
||||
if(c==')') missingClosingParens--;
|
||||
}
|
||||
return matched+")".repeat(Math.max(0, missingClosingParens));
|
||||
pronouns+=")".repeat(Math.max(0, missingClosingParens));
|
||||
// if ends with an un-closed custom emoji
|
||||
if(pronouns.matches("^.*\\s+:[a-zA-Z_]+$")) pronouns+=':';
|
||||
return pronouns;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/9475589/how-to-get-string-from-different-locales-in-android
|
||||
|
||||
@@ -73,6 +73,6 @@ public abstract class ListItemViewHolder<T extends ListItem<?>> extends Bindable
|
||||
|
||||
@Override
|
||||
public void onClick(){
|
||||
item.onClick.run();
|
||||
item.performClick();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,40 @@
|
||||
package org.joinmastodon.android.ui.views;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import me.grishka.appkit.utils.V;
|
||||
import org.joinmastodon.android.R;
|
||||
|
||||
/**
|
||||
* A LinearLayout for TextViews. First child TextView will get truncated if it doesn't fit, remaining will always wrap content.
|
||||
*/
|
||||
public class HeaderSubtitleLinearLayout extends LinearLayout{
|
||||
private float firstFraction;
|
||||
|
||||
public HeaderSubtitleLinearLayout(Context context){
|
||||
super(context);
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public HeaderSubtitleLinearLayout(Context context, AttributeSet attrs){
|
||||
super(context, attrs);
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public HeaderSubtitleLinearLayout(Context context, AttributeSet attrs, int defStyleAttr){
|
||||
super(context, attrs, defStyleAttr);
|
||||
TypedArray ta=context.obtainStyledAttributes(attrs, R.styleable.HeaderSubtitleLinearLayout);
|
||||
firstFraction=ta.getFraction(R.styleable.HeaderSubtitleLinearLayout_firstFraction, 1, 1, 0.5f);
|
||||
ta.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
|
||||
if(getLayoutChildCount()>1){
|
||||
int remainingWidth=MeasureSpec.getSize(widthMeasureSpec);
|
||||
int fullWidth=MeasureSpec.getSize(widthMeasureSpec);
|
||||
int remainingWidth=fullWidth;
|
||||
for(int i=1;i<getChildCount();i++){
|
||||
View v=getChildAt(i);
|
||||
if(v.getVisibility()==GONE)
|
||||
@@ -38,8 +45,7 @@ public class HeaderSubtitleLinearLayout extends LinearLayout{
|
||||
}
|
||||
View first=getChildAt(0);
|
||||
if(first instanceof TextView){
|
||||
// guaranteeing at least 64dp of width for the display name
|
||||
((TextView) first).setMaxWidth(Math.max(remainingWidth, V.dp(64)));
|
||||
((TextView) first).setMaxWidth(Math.max(remainingWidth, (int)(firstFraction*fullWidth)));
|
||||
}
|
||||
}else{
|
||||
View first=getChildAt(0);
|
||||
@@ -58,4 +64,12 @@ public class HeaderSubtitleLinearLayout extends LinearLayout{
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setFirstFraction(float firstFraction){
|
||||
this.firstFraction=firstFraction;
|
||||
}
|
||||
|
||||
public float getFirstFraction(){
|
||||
return firstFraction;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,19 +3,13 @@
|
||||
android:color="@color/m3_primary_overlay">
|
||||
<item android:gravity="center_vertical" android:height="40dp">
|
||||
<selector>
|
||||
<item android:state_enabled="true" android:state_selected="true">
|
||||
<item android:state_enabled="true">
|
||||
<shape>
|
||||
<solid android:color="?colorM3SecondaryContainer"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_selected="false">
|
||||
<shape>
|
||||
<stroke android:color="@color/m3_on_surface_overlay" android:width="1dp"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_enabled="false">
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="?colorM3DisabledBackground"/>
|
||||
<corners android:radius="20dp"/>
|
||||
|
||||
@@ -3,19 +3,13 @@
|
||||
android:color="@color/m3_primary_overlay">
|
||||
<item android:gravity="center" android:height="40dp" android:width="40dp">
|
||||
<selector>
|
||||
<item android:state_enabled="true" android:state_selected="true">
|
||||
<item android:state_enabled="true">
|
||||
<shape>
|
||||
<solid android:color="?colorM3SecondaryContainer"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_selected="false">
|
||||
<shape>
|
||||
<stroke android:color="@color/m3_on_surface_overlay" android:width="1dp"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_enabled="false">
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="?colorM3DisabledBackground"/>
|
||||
<corners android:radius="20dp"/>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/m3_primary_overlay">
|
||||
<item android:gravity="center" android:height="40dp" android:width="40dp">
|
||||
<selector>
|
||||
<item android:state_enabled="true" android:state_selected="true">
|
||||
<shape>
|
||||
<solid android:color="?colorM3SecondaryContainer"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_selected="false">
|
||||
<shape>
|
||||
<stroke android:color="@color/m3_on_surface_overlay" android:width="1dp"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_enabled="false">
|
||||
<shape>
|
||||
<solid android:color="?colorM3DisabledBackground"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
</item>
|
||||
<item android:id="@android:id/mask" android:gravity="center" android:height="40dp" android:width="40dp">
|
||||
<shape>
|
||||
<solid android:color="#000"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:color="@color/m3_primary_overlay">
|
||||
<item android:gravity="center_vertical" android:height="40dp">
|
||||
<selector>
|
||||
<item android:state_enabled="true" android:state_selected="true">
|
||||
<shape>
|
||||
<solid android:color="?colorM3SecondaryContainer"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_selected="false">
|
||||
<shape>
|
||||
<stroke android:color="@color/m3_on_surface_overlay" android:width="1dp"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
<item android:state_enabled="false">
|
||||
<shape>
|
||||
<solid android:color="?colorM3DisabledBackground"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</selector>
|
||||
</item>
|
||||
<item android:id="@android:id/mask" android:gravity="center_vertical" android:height="40dp">
|
||||
<shape>
|
||||
<solid android:color="#000"/>
|
||||
<corners android:radius="20dp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ripple xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/highlight_over_dark">
|
||||
<item>
|
||||
<shape>
|
||||
<solid android:color="?colorPrimary800"/>
|
||||
<corners android:radius="16sp"/>
|
||||
<padding android:left="16sp" android:right="16sp"/>
|
||||
</shape>
|
||||
</item>
|
||||
</ripple>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M17.5 12c3.038 0 5.5 2.463 5.5 5.5 0 3.038-2.462 5.5-5.5 5.5-3.037 0-5.5-2.462-5.5-5.5 0-3.037 2.463-5.5 5.5-5.5zm-2.646 5.147c-0.195-0.196-0.512-0.196-0.707 0-0.196 0.195-0.196 0.512 0 0.707l2 2c0.195 0.195 0.512 0.195 0.707 0l4-4c0.195-0.195 0.195-0.512 0-0.707-0.195-0.196-0.512-0.196-0.707 0L16.5 18.793l-1.646-1.646zM12.023 14c-0.297 0.463-0.537 0.966-0.709 1.5H4.253c-0.414 0-0.75 0.335-0.75 0.75v0.577c0 0.535 0.192 1.053 0.54 1.46 1.253 1.469 3.22 2.214 5.957 2.214 0.597 0 1.157-0.035 1.68-0.106 0.246 0.495 0.553 0.954 0.912 1.367-0.795 0.16-1.66 0.24-2.592 0.24-3.146 0-5.532-0.906-7.098-2.74-0.58-0.679-0.898-1.543-0.898-2.435v-0.578C2.004 15.007 3.01 14 4.253 14h7.77zM10 2.005c2.762 0 5 2.239 5 5s-2.238 5-5 5c-2.761 0-5-2.239-5-5s2.239-5 5-5zm0 1.5c-1.933 0-3.5 1.567-3.5 3.5s1.567 3.5 3.5 3.5 3.5-1.567 3.5-3.5-1.567-3.5-3.5-3.5z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -30,7 +30,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:minHeight="48dp"
|
||||
android:minWidth="48dp"
|
||||
android:background="@drawable/bg_button_m3_tonal_circle"
|
||||
android:background="@drawable/bg_button_m3_tonal_circle_selector"
|
||||
android:tooltipText="@string/sk_button_react"
|
||||
android:contentDescription="@string/sk_button_react"
|
||||
android:src="@drawable/ic_fluent_add_24_filled" />
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="15dp">
|
||||
<!-- avatar width (46sp) / 2 - button width (24dp) / 2 -->
|
||||
|
||||
<FrameLayout
|
||||
android:layout_weight="1"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingHorizontal="16dp">
|
||||
@@ -10,7 +11,7 @@
|
||||
android:id="@+id/buttons"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentEnd="true">
|
||||
|
||||
@@ -107,6 +108,7 @@
|
||||
|
||||
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
|
||||
android:id="@+id/name_wrap"
|
||||
app:firstFraction="60%"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/avatar"
|
||||
@@ -125,20 +127,6 @@
|
||||
android:gravity="start|center_vertical"
|
||||
tools:text="Eugen" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pronouns"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8sp"
|
||||
android:maxWidth="161sp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:fontFamily="sans-serif"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="they/them" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/extra_text"
|
||||
android:layout_width="wrap_content"
|
||||
@@ -146,8 +134,7 @@
|
||||
android:layout_marginStart="8sp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:fontFamily="sans-serif"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="boosted your cat picture" />
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
app:firstFraction="30%"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -45,6 +47,6 @@
|
||||
android:drawableTint="?colorM3OnSurface"
|
||||
android:drawablePadding="6dp"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"/>
|
||||
android:ellipsize="middle"/>
|
||||
|
||||
</org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout>
|
||||
@@ -49,7 +49,7 @@
|
||||
<Button
|
||||
android:id="@+id/advanced"
|
||||
style="@style/Widget.Mastodon.M3.Button.Outlined"
|
||||
android:background="@drawable/bg_button_m3_tonal"
|
||||
android:background="@drawable/bg_button_m3_tonal_selector"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
android:layout_marginStart="8sp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:textAppearance="@style/m3_body_medium"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?colorM3OnSurface"
|
||||
tools:text="@string/sk_inline_local_only" />
|
||||
@@ -366,6 +366,7 @@
|
||||
|
||||
<Button
|
||||
style="@style/Widget.Mastodon.M3.Button.Tonal.Icon"
|
||||
android:background="@drawable/bg_button_m3_tonal_selector"
|
||||
android:id="@+id/sensitive_item"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
style="@style/Widget.Mastodon.M3.Button.Tonal"
|
||||
android:background="@drawable/bg_button_m3_tonal_circle"
|
||||
android:background="@drawable/bg_button_m3_tonal_circle_selector"
|
||||
android:paddingStart="12dp"
|
||||
android:drawableStart="@drawable/ic_fluent_alert_24_selector" />
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
android:visibility="gone" />
|
||||
<TextView
|
||||
android:id="@+id/timeline_title"
|
||||
style="?android:attr/titleTextAppearance"
|
||||
style="@style/action_bar_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
@@ -47,22 +47,21 @@
|
||||
android:layout_height="match_parent">
|
||||
<Button
|
||||
android:id="@+id/show_new_posts_btn"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="2dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:minHeight="32sp"
|
||||
android:maxLines="2"
|
||||
style="@style/Widget.Mastodon.M3.Button.Tonal.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/bg_button_m3_tonal_selector"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:lineSpacingMultiplier="0.8"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/see_new_posts"
|
||||
android:textColor="@color/gray_25"
|
||||
android:background="@drawable/bg_button_new_posts"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/see_new_posts"
|
||||
android:drawableStart="@drawable/ic_fluent_arrow_up_16_filled"
|
||||
android:drawablePadding="8dp"
|
||||
android:layout_gravity="center" />
|
||||
<!--
|
||||
using the selector background because..
|
||||
the selected=false state's border looks better than the one from the outline style
|
||||
(as per m3 spec) :( i should probably fix this at some point
|
||||
-->
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
@@ -23,5 +23,5 @@
|
||||
android:layout_marginEnd="8dp"
|
||||
android:drawableTint="@null"
|
||||
android:drawableStart="@drawable/image_placeholder"
|
||||
android:background="@drawable/bg_button_m3_tonal"/>
|
||||
android:background="@drawable/bg_button_m3_tonal_selector"/>
|
||||
</FrameLayout>
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<group android:id="@+id/menu_group1">
|
||||
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:visible="false" android:icon="@drawable/ic_fluent_person_swap_24_regular">
|
||||
<menu android:id="@+id/accounts" />
|
||||
</item>
|
||||
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
|
||||
<item android:id="@+id/open_in_browser" android:title="@string/open_in_browser" android:icon="@drawable/ic_fluent_globe_24_regular"/>
|
||||
</group>
|
||||
<group android:id="@+id/menu_group2">
|
||||
<item android:id="@+id/manage_user_lists" android:title="@string/sk_lists_with_user" android:icon="@drawable/ic_fluent_people_24_regular"/>
|
||||
<item android:id="@+id/mute" android:title="@string/mute_user" android:icon="@drawable/ic_fluent_speaker_off_24_regular"/>
|
||||
<item android:id="@+id/hide_boosts" android:title="@string/hide_boosts_from_user" android:icon="@drawable/ic_fluent_arrow_repeat_all_off_24_regular"/>
|
||||
@@ -16,4 +9,11 @@
|
||||
<item android:id="@+id/report" android:title="@string/report_user" android:icon="@drawable/ic_fluent_warning_24_regular"/>
|
||||
<item android:id="@+id/block_domain" android:title="@string/block_domain" android:icon="@drawable/ic_fluent_shield_prohibited_24_regular"/>
|
||||
</group>
|
||||
<group android:id="@+id/menu_group2">
|
||||
<item android:id="@+id/open_in_browser" android:title="@string/open_in_browser" android:icon="@drawable/ic_fluent_globe_24_regular"/>
|
||||
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
|
||||
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:visible="false" android:icon="@drawable/ic_fluent_person_swap_24_regular">
|
||||
<menu android:id="@+id/accounts" />
|
||||
</item>
|
||||
</group>
|
||||
</menu>
|
||||
@@ -1,14 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/followed_hashtags" android:title="@string/sk_hashtags_you_follow" android:icon="@drawable/ic_fluent_number_symbol_24_regular" android:showAsAction="always"/>
|
||||
<item android:id="@+id/bookmarks" android:title="@string/bookmarks" android:icon="@drawable/ic_fluent_bookmark_multiple_24_regular" android:showAsAction="always"/>
|
||||
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:icon="@drawable/ic_fluent_person_swap_24_regular">
|
||||
<menu android:id="@+id/accounts" />
|
||||
</item>
|
||||
<item android:id="@+id/manage_user_lists" android:title="@string/sk_your_lists" android:icon="@drawable/ic_fluent_people_24_regular"/>
|
||||
<item android:id="@+id/favorites" android:title="@string/your_favorites" android:icon="@drawable/ic_fluent_star_24_regular"/>
|
||||
<item android:id="@+id/muted_accounts" android:title="@string/sk_muted_accounts" android:icon="@drawable/ic_fluent_speaker_off_24_regular"/>
|
||||
<item android:id="@+id/blocked_accounts" android:title="@string/sk_blocked_accounts" android:icon="@drawable/ic_fluent_shield_24_regular"/>
|
||||
<item android:id="@+id/scheduled" android:title="@string/sk_unsent_posts" android:icon="@drawable/ic_fluent_folder_open_24_regular"/>
|
||||
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
|
||||
<group android:id="@+id/menu_group1">
|
||||
<item android:id="@+id/followed_hashtags" android:title="@string/sk_hashtags_you_follow" android:icon="@drawable/ic_fluent_number_symbol_24_regular" android:showAsAction="always"/>
|
||||
<item android:id="@+id/bookmarks" android:title="@string/bookmarks" android:icon="@drawable/ic_fluent_bookmark_multiple_24_regular" android:showAsAction="always"/>
|
||||
<item android:id="@+id/manage_user_lists" android:title="@string/sk_your_lists" android:icon="@drawable/ic_fluent_people_24_regular"/>
|
||||
<item android:id="@+id/favorites" android:title="@string/your_favorites" android:icon="@drawable/ic_fluent_star_24_regular"/>
|
||||
<item android:id="@+id/muted_accounts" android:title="@string/sk_muted_accounts" android:icon="@drawable/ic_fluent_speaker_off_24_regular"/>
|
||||
<item android:id="@+id/blocked_accounts" android:title="@string/sk_blocked_accounts" android:icon="@drawable/ic_fluent_shield_24_regular"/>
|
||||
<item android:id="@+id/scheduled" android:title="@string/sk_unsent_posts" android:icon="@drawable/ic_fluent_folder_open_24_regular"/>
|
||||
</group>
|
||||
<group android:id="@+id/menu_group2">
|
||||
<item android:id="@+id/open_in_browser" android:title="@string/open_in_browser" android:icon="@drawable/ic_fluent_globe_24_regular"/>
|
||||
<item android:id="@+id/share" android:title="@string/share_user" android:icon="@drawable/ic_fluent_share_24_regular"/>
|
||||
<item android:id="@+id/open_with_account" android:title="@string/sk_open_with_account" android:visible="false" android:icon="@drawable/ic_fluent_person_swap_24_regular">
|
||||
<menu android:id="@+id/accounts" />
|
||||
</item>
|
||||
</group>
|
||||
</menu>
|
||||
@@ -314,7 +314,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">هذه هي جميع المشاركات من جميع المستخدمين في الخادم الخاص بك (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">قد تعجبك هذه الحسابات استنادا إلى حسابات أخرى تتابعها.</string>
|
||||
<string name="see_new_posts">استعرض المنشورات الجديدة</string>
|
||||
<string name="load_missing_posts">حمّل المَنشورات المَفقودَة</string>
|
||||
<string name="follow_back">رُدّ المتابعة</string>
|
||||
<string name="button_follow_pending">معلق</string>
|
||||
|
||||
@@ -324,4 +324,5 @@
|
||||
<string name="sk_settings_continues_playback">تراكُب صوتي</string>
|
||||
<string name="sk_settings_enable_marquee">تمكين تمرير النص في عناوين الأشرطة</string>
|
||||
<string name="sk_settings_tabs_disable_swipe">تعطيل التمرير بين الألسِنة</string>
|
||||
<string name="sk_settings_color_palette_default">افتراضي (%s)</string>
|
||||
</resources>
|
||||
@@ -273,7 +273,6 @@
|
||||
<string name="downloading">Спампоўванне…</string>
|
||||
<string name="local_timeline">Лакальнае</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="see_new_posts">Паказаць новыя допісы</string>
|
||||
<string name="load_missing_posts">Загрузіць адсутныя допісы</string>
|
||||
<string name="follow_back">Падпісацца ў адказ</string>
|
||||
<string name="button_follow_pending">Чакаюць</string>
|
||||
|
||||
@@ -208,7 +208,6 @@
|
||||
<string name="file_saved">Fitxer desat</string>
|
||||
<string name="downloading">S\'està baixant…</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="see_new_posts">Publicacions noves</string>
|
||||
<string name="load_missing_posts">Carrega les publicacions faltants</string>
|
||||
<string name="follow_back">Segueix</string>
|
||||
<string name="button_follow_pending">Pendent</string>
|
||||
|
||||
@@ -288,7 +288,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Toto jsou všechny příspěvky od všech uživatelů na vašem serveru (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Podle toho, koho sledujete, by se vám mohly líbit tyto účty.</string>
|
||||
<string name="see_new_posts">Zobrazit nové příspěvky</string>
|
||||
<string name="load_missing_posts">Načíst chybějící příspěvky</string>
|
||||
<string name="follow_back">Sledovat nazpět</string>
|
||||
<string name="button_follow_pending">Čekající</string>
|
||||
|
||||
@@ -262,7 +262,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Disse er alle indlæg fra alle brugere på din server (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Baseret på andre, du følger, vil du måske synes om disse konti.</string>
|
||||
<string name="see_new_posts">Se nye indlæg</string>
|
||||
<string name="load_missing_posts">Indlæs manglende indlæg</string>
|
||||
<string name="follow_back">Følg Tilbage</string>
|
||||
<string name="button_follow_pending">Afventer</string>
|
||||
|
||||
@@ -262,7 +262,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Dies sind alle Beiträge von allen Benutzern auf deinem Server (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Dir könnten diese Konten gefallen, basierend auf Leuten, denen du folgst.</string>
|
||||
<string name="see_new_posts">Neue Beiträge anzeigen</string>
|
||||
<string name="load_missing_posts">Weitere Beiträge laden</string>
|
||||
<string name="follow_back">Zurückfolgen</string>
|
||||
<string name="button_follow_pending">Ausstehend</string>
|
||||
|
||||
@@ -255,7 +255,7 @@
|
||||
<string name="sk_expand">Erweitern</string>
|
||||
<string name="sk_collapse">Einklappen</string>
|
||||
<string name="sk_settings_collapse_long_posts">Sehr lange Beiträge einklappen</string>
|
||||
<string name="sk_unfinished_attachments">Anhänge richtig stellen\?</string>
|
||||
<string name="sk_unfinished_attachments">Anhänge laden hoch</string>
|
||||
<string name="sk_settings_hide_interaction">Interaktions-Buttons verstecken</string>
|
||||
<string name="sk_unfinished_attachments_message">Einige Anhänge sind nicht fertig hochgeladen.</string>
|
||||
<string name="sk_followed_as">Mit %s gefolgt</string>
|
||||
@@ -295,7 +295,7 @@
|
||||
<string name="sk_settings_allow_remote_loading">Infos von Remote-Instanzen laden</string>
|
||||
<string name="sk_no_remote_info_hint">keine Remote-Infos abrufbar</string>
|
||||
<string name="sk_error_loading_profile">Konnte das Profil via %s nicht laden</string>
|
||||
<string name="sk_settings_allow_remote_loading_explanation">Für vollständigere Auflistung von Follower*innen, Likes und Boosts können die Informationen von der Ursprungs-Instanz geladen werden.</string>
|
||||
<string name="sk_settings_allow_remote_loading_explanation">Für vollständigere Auflistung von Follower_innen, Likes und Boosts können die Informationen von der Ursprungs-Instanz geladen werden.</string>
|
||||
<string name="sk_settings_auto_reveal_equal_spoilers">Automatisches Aufdecken von gleichen CWs in Antworten von</string>
|
||||
<string name="sk_settings_auto_reveal_nobody">Nie</string>
|
||||
<string name="sk_settings_auto_reveal_author">Antworten, die von der gleichen Person verfasst wurden</string>
|
||||
@@ -410,4 +410,9 @@
|
||||
<string name="sk_settings_color_palette_default">Standardwert (%s)</string>
|
||||
<string name="sk_settings_underlined_links">Unterstrichene Links</string>
|
||||
<string name="sk_recently_used">Zuletzt verwendet</string>
|
||||
<string name="sk_settings_clear_timeline_cache">Start-Timeline leeren</string>
|
||||
<string name="sk_edit_alt_text">Bildbeschreibung bearbeiten</string>
|
||||
<string name="sk_settings_default_visibility">Standard-Sichtbarkeit für Posts</string>
|
||||
<string name="sk_settings_lock_account">Neue Follower_innen manuell genehmigen</string>
|
||||
<string name="sk_timeline_cache_cleared">Start-Timeline geleert</string>
|
||||
</resources>
|
||||
@@ -262,7 +262,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Αυτές είναι όλες οι αναρτήσεις από όλους τους χρήστες στο διακομιστή σου (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Μπορεί να σου αρέσουν αυτοί οι λογαριασμοί με βάση άλλους που ακολουθείς.</string>
|
||||
<string name="see_new_posts">Δες νέες αναρτήσεις</string>
|
||||
<string name="load_missing_posts">Φόρτωση αναρτήσεων που λείπουν</string>
|
||||
<string name="follow_back">Ακολούθησε και εσύ</string>
|
||||
<string name="button_follow_pending">Εκκρεμεί</string>
|
||||
|
||||
@@ -262,7 +262,7 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Estos son todos los mensajes de todos los usuarios de tu servidor (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Es posible que te gusten estas cuentas basadas en otras que sigues.</string>
|
||||
<string name="see_new_posts">Ver nuevas publicaciones</string>
|
||||
<string name="see_new_posts">Nuevas publicaciones</string>
|
||||
<string name="load_missing_posts">Cargar publicaciones faltantes</string>
|
||||
<string name="follow_back">Seguir de vuelta</string>
|
||||
<string name="button_follow_pending">Pendiente</string>
|
||||
@@ -387,6 +387,7 @@
|
||||
<string name="welcome_to_mastodon">Bienvenido/da a Mastodon</string>
|
||||
<string name="welcome_paragraph1">Mastodon es una red social descentralizada, lo que significa que no la controla una sola compañía. Está formada por muchos servidores independientes, todos juntos conectados.</string>
|
||||
<string name="what_are_servers">¿Qué son los servidores?</string>
|
||||
<string name="welcome_paragraph2">Cada cuenta de Mastodon está alojada en un servidor — cada uno con sus propios valores, reglas y administradores. Sin importar cuál elijas, puedes seguir e interactuar con personas en cualquier servidor.</string>
|
||||
<string name="opening_link">Abriendo enlace…</string>
|
||||
<string name="link_not_supported">Este enlace no es compatible con la aplicación</string>
|
||||
<string name="log_out_all_accounts">Cerrar sesión en todas las cuentas</string>
|
||||
@@ -414,6 +415,7 @@
|
||||
<string name="alt_text">Texto alternativo</string>
|
||||
<string name="help">Ayuda</string>
|
||||
<string name="what_is_alt_text">¿Qué es el texto alternativo?</string>
|
||||
<string name="alt_text_help">El texto alternativo entrega descripciones de una imagen a las personas con discapacidad visual, conexiones de internet de bajo ancho de banda o a quienes buscan más contexto.\n\nPuedes mejorar la accesibilidad y la comprensión de todos al escribir texto alternativo que sea claro, conciso y objetivo.\n\n<ul><il> Captura elementos importantes</li>\n<li>Resume el texto en las imágenes</li>\n<li>Construye las frases de manera normal</li>\n<li>Evita la información redundante</li>\n<li>Enfócate en tendencias y en hallazgos claves en imágenes complejas (como diagramas o mapas)</li></ul></string>
|
||||
<string name="edit_post">Editar publicación</string>
|
||||
<string name="no_verified_link">Enlace no verificado</string>
|
||||
<string name="compose_autocomplete_emoji_empty">Explorar emojis</string>
|
||||
@@ -433,6 +435,7 @@
|
||||
<string name="forward_report_to_server">Reenviar a %s</string>
|
||||
<!-- Shown on the "stamp" on the screen that appears after you report a post/user. Please keep the translation short, preferably a single word -->
|
||||
<string name="reported">Reportado</string>
|
||||
<string name="report_unfollow_explanation">Para no ver más sus publicaciones en tu feed de inicio, deja de seguirle.</string>
|
||||
<string name="muted_user">Silenciado %s</string>
|
||||
<string name="report_sent_already_blocked">Ya has bloqueado a este usuario, así que no tienes nada más que hacer mientras revisamos tu informe.</string>
|
||||
<string name="report_personal_already_blocked">Ya has bloqueado a este usuario, así que no tienes nada más que hacer.\n\n¡Gracias por ayudar a mantener Mastodon un lugar seguro para todos!</string>
|
||||
@@ -475,9 +478,13 @@
|
||||
<string name="about_server">Acerca de</string>
|
||||
<string name="server_rules">Reglas</string>
|
||||
<string name="server_administrator">Administrador</string>
|
||||
<string name="send_email_to_server_admin">Contacta a un administrador</string>
|
||||
<string name="notifications_disabled_in_system">Active las notificaciones desde la configuración de su dispositivo para ver actualizaciones desde cualquier lugar.</string>
|
||||
<string name="settings_even_more">Aún más ajustes</string>
|
||||
<string name="settings_show_cws">Mostrar advertencias de contenido</string>
|
||||
<string name="settings_hide_sensitive_media">Esconder contenidos marcados como explícitos</string>
|
||||
<string name="settings_show_interaction_counts">Contador de interacciones con una publicación</string>
|
||||
<string name="settings_show_emoji_in_names">Emoji personalizado en los nombres de las pantallas</string>
|
||||
<plurals name="in_x_seconds">
|
||||
<item quantity="one">en %d segundo</item>
|
||||
<item quantity="other">en %d segundos</item>
|
||||
@@ -532,6 +539,7 @@
|
||||
<string name="selection_4_or_more">%1$s, %2$s, y %3$d más</string>
|
||||
<string name="filter_context_home_lists">Inicio y listas</string>
|
||||
<string name="filter_context_notifications">Notificaciones</string>
|
||||
<string name="filter_context_public_timelines">Líneas de tiempo públicas</string>
|
||||
<string name="filter_context_threads_replies">Hilos y respuestas</string>
|
||||
<string name="filter_context_profiles">Profiles</string>
|
||||
<string name="settings_filter_title">Título</string>
|
||||
@@ -541,6 +549,7 @@
|
||||
<string name="edit_muted_word">Editar palabra silenciada</string>
|
||||
<string name="add">Añadir</string>
|
||||
<string name="filter_word_or_phrase">Palabra o frase</string>
|
||||
<string name="filter_add_word_help">Las palabras no distinguen letras mayúsculas y solo reconocen palabras completas.\n\nSi filtras la palabra \"Agua\", se ocultarán posteos que incluyan \"agua\" o \"aGua\", pero no los que contengan \"paraguas\".</string>
|
||||
<string name="settings_delete_filter_word">¿Eliminar palabra “%s”?</string>
|
||||
<string name="enter_selection_mode">Seleccionar</string>
|
||||
<string name="select_all">Seleccionar todo</string>
|
||||
@@ -574,8 +583,46 @@
|
||||
<string name="time_hours_ago_short">hace %dh</string>
|
||||
<string name="time_days_ago_short">hace %dd</string>
|
||||
<!-- %s is the name of the post language -->
|
||||
<string name="translate_post">Traducir desde %s</string>
|
||||
<!-- %1$s is the language, %2$s is the name of the translation service -->
|
||||
<string name="post_translated">Traducido desde %1$s usando %2$s</string>
|
||||
<string name="translation_show_original">Ver original</string>
|
||||
<string name="translation_failed">Error al traducir. Tal vez el administrador no ha habilitado las traducciones en este servidor o este servidor está ejecutando una versión antigua de Mastodon donde las traducciones aún no están soportadas.</string>
|
||||
<string name="settings_privacy">Privacidad y alcance</string>
|
||||
<string name="settings_discoverable">Mostrar perfil y publicaciones en algoritmos de descubrimiento</string>
|
||||
<string name="settings_indexable">Incluir publicaciones públicas en los resultados de búsqueda</string>
|
||||
<string name="error_playing_video">Error al reproducir el video</string>
|
||||
<string name="timeline_following">Siguiendo</string>
|
||||
<string name="lists">Listas</string>
|
||||
<string name="followed_hashtags">Etiquetas seguidas</string>
|
||||
<string name="no_lists">Aún no tienes ninguna lista.</string>
|
||||
<string name="no_followed_hashtags">Aún no sigues ninguna etiqueta.</string>
|
||||
<string name="manage_lists">Administrar listas</string>
|
||||
<string name="manage_hashtags">Administrar etiquetas</string>
|
||||
<!-- Screen reader description for the menu on the home timeline screen -->
|
||||
<string name="dropdown_menu">Menú desplegable</string>
|
||||
<string name="edit_list">Editar lista</string>
|
||||
<string name="list_members">Miembros de la lista</string>
|
||||
<string name="delete_list">Borrar lista</string>
|
||||
<!-- %s is the name of the list -->
|
||||
<string name="delete_list_confirm">¿Eliminar “%s”?</string>
|
||||
<string name="list_exclusive">Ocultar miembros en la lista de Seguidos</string>
|
||||
<string name="list_exclusive_subtitle">Si alguien está en esta lista, ocúltalos en tu línea de tiempo para evitar ver sus publicaciones dos veces.</string>
|
||||
<string name="list_name">Nombre de la lista</string>
|
||||
<string name="list_show_replies_to">Mostrar respuestas a</string>
|
||||
<string name="list_replies_no_one">Nadie</string>
|
||||
<string name="list_replies_members">Miembros de la lista</string>
|
||||
<string name="list_replies_anyone">Cualquiera que yo siga</string>
|
||||
<string name="confirm_remove_list_members">¿Eliminar miembros?</string>
|
||||
<string name="remove">Eliminar</string>
|
||||
<string name="add_list_member">Añadir miembro</string>
|
||||
<string name="search_among_people_you_follow">Buscar entre las personas a las que sigues</string>
|
||||
<string name="add_user_to_list">Añadir a lista…</string>
|
||||
<string name="add_user_to_list_title">Añadir a lista</string>
|
||||
<!-- %s is a username -->
|
||||
<string name="manage_user_lists">Administrar las listas en las que %s aparece</string>
|
||||
<string name="remove_from_list">Quitar de lista</string>
|
||||
<string name="confirm_remove_list_member">¿Eliminar miembro?</string>
|
||||
<string name="no_followed_hashtags_title">Manténgase al día con los intereses siguiendo las etiquetas</string>
|
||||
<string name="no_followed_hashtags_subtitle">Los seguidores aparecerán aquí</string>
|
||||
</resources>
|
||||
|
||||
@@ -254,7 +254,7 @@
|
||||
<string name="sk_expand">Ampliar</string>
|
||||
<string name="sk_collapse">Minimizar</string>
|
||||
<string name="sk_settings_collapse_long_posts">Minimizar publicaciones largas</string>
|
||||
<string name="sk_unfinished_attachments">¿Corregir adjuntos\?</string>
|
||||
<string name="sk_unfinished_attachments">Cargando los archivos adjuntos</string>
|
||||
<string name="sk_unfinished_attachments_message">Algunos adjuntos no han terminado de subirse.</string>
|
||||
<string name="sk_settings_prefix_reply_cw_with_re">Añadir \"re\" a Avisos de Contenido</string>
|
||||
<string name="sk_spectator_mode">Modo espectador</string>
|
||||
@@ -407,4 +407,5 @@
|
||||
<string name="sk_set_as_default">Establecer por defecto</string>
|
||||
<string name="sk_settings_color_palette_default">Por defecto (%s)</string>
|
||||
<string name="sk_settings_underlined_links">Enlaces subrayados</string>
|
||||
<string name="sk_edit_alt_text">Editar el texto alternativo</string>
|
||||
</resources>
|
||||
@@ -246,7 +246,6 @@
|
||||
<string name="local_timeline">Lokala</string>
|
||||
<string name="trending_posts_info_banner">Hauek dira zure Mastodon txokoan beraien lekua hartzen ari diren argitalpenak.</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="see_new_posts">Ikusi bidalketa berriak</string>
|
||||
<string name="load_missing_posts">Falta diren bidalketak kargatu</string>
|
||||
<string name="follow_back">Jarraitu</string>
|
||||
<string name="button_follow_pending">Zain</string>
|
||||
|
||||
@@ -262,7 +262,7 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">اینها همه فرستههای همه کاربران در سرور شما (%s) هستند.</string>
|
||||
<string name="recommended_accounts_info_banner">ممکن است این حسابها را بر اساس حسابهای دیگری که پی میگیرید بپسندید.</string>
|
||||
<string name="see_new_posts">فرستههای جدید را ببینید</string>
|
||||
<string name="see_new_posts">فرستههای جدید</string>
|
||||
<string name="load_missing_posts">بارگذاری فرستههای گم شده</string>
|
||||
<string name="follow_back">پیگیری متقابل</string>
|
||||
<string name="button_follow_pending">منتظر</string>
|
||||
@@ -599,7 +599,37 @@
|
||||
<item quantity="one">%,d فرسته امروز</item>
|
||||
<item quantity="other">%,d فرسته امروز</item>
|
||||
</plurals>
|
||||
<string name="error_playing_video">خطا در پخش ویدئو</string>
|
||||
<string name="timeline_following">پیگرفته</string>
|
||||
<string name="lists">سیاههها</string>
|
||||
<string name="followed_hashtags">برچسبهای پیگرفته</string>
|
||||
<string name="no_lists">شما هنوز هیچ سیاههای ندارید.</string>
|
||||
<string name="no_followed_hashtags">شما هیچ برچسبی را پی نمیگیرید.</string>
|
||||
<string name="manage_lists">مدیریت سیاههها</string>
|
||||
<string name="manage_hashtags">مدیریت برچسبها</string>
|
||||
<!-- Screen reader description for the menu on the home timeline screen -->
|
||||
<string name="dropdown_menu">منوی کشویی</string>
|
||||
<string name="edit_list">ویرایش سیاهه</string>
|
||||
<string name="list_members">اعضای سیاهه</string>
|
||||
<string name="delete_list">حذف سیاهه</string>
|
||||
<!-- %s is the name of the list -->
|
||||
<string name="delete_list_confirm">حذف \"%s\"؟</string>
|
||||
<string name="list_exclusive">نهفتن اعضای پیگرفته</string>
|
||||
<string name="list_name">اسم سیاهه</string>
|
||||
<string name="list_show_replies_to">نمایش پاسخها به</string>
|
||||
<string name="list_replies_no_one">هیچکس</string>
|
||||
<string name="list_replies_members">اعضای سیاهه</string>
|
||||
<string name="confirm_remove_list_members">حذف اعضا؟</string>
|
||||
<string name="remove">برداشتن</string>
|
||||
<string name="add_list_member">افزودن عضو</string>
|
||||
<string name="add_user_to_list">افزودن به سیاهه…</string>
|
||||
<string name="add_user_to_list_title">افزودن به سیاهه</string>
|
||||
<!-- %s is a username -->
|
||||
<string name="remove_from_list">برداشتن از سیاهه</string>
|
||||
<string name="confirm_remove_list_member">حذف عضو؟</string>
|
||||
<string name="manage_accounts">افزودن یا جابجا شدن بین حسابها</string>
|
||||
<plurals name="x_posts_recently">
|
||||
<item quantity="one">%,d فرسته اخیرا ارسال کرده</item>
|
||||
<item quantity="other">%,d فرسته اخیرا ارسال کرده</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
||||
@@ -310,7 +310,7 @@
|
||||
<string name="sk_reacted">%s واکنش نشان داد</string>
|
||||
<string name="sk_external_share_title">همرسانی با حساب</string>
|
||||
<string name="sk_settings_prefix_reply_cw_with_re">وارد کردن پیشوند CW با “re:” هنگام پاسخ دادن</string>
|
||||
<string name="sk_unfinished_attachments">رفع مشکل پیوستها؟</string>
|
||||
<string name="sk_unfinished_attachments">درحال بارگذاری پیوستها</string>
|
||||
<string name="sk_settings_allow_remote_loading">بارگیری اطلاعات از نمونه های راه دور</string>
|
||||
<string name="sk_error_loading_profile">بارگیری نمایه از طریق %s شکست خورد</string>
|
||||
<string name="sk_settings_reply_visibility_following">پاسخ به پیگیر های من</string>
|
||||
@@ -363,7 +363,7 @@
|
||||
<string name="sk_button_react">واکنش با ایموجی</string>
|
||||
<string name="sk_again_for_system_keyboard">دوباره برای کیبورد سامانه ضربه بزنید</string>
|
||||
<string name="sk_enter_emoji_toast">لطفا یک ایموجی تایپ کنید</string>
|
||||
<string name="sk_enter_emoji_hint">برای واکنش با ایموجی تایپ کنید</string>
|
||||
<string name="sk_enter_emoji_hint">یک ایموجی بنویسید یا جستجو کنید</string>
|
||||
<plurals name="sk_users_reacted_with">
|
||||
<item quantity="one">یک کاربر با %2$s واکنش نشان داد</item>
|
||||
<item quantity="other">%1$,d کاربر با %2$s واکنش نشان دادند</item>
|
||||
@@ -388,11 +388,19 @@
|
||||
<string name="sk_search_suicide_hotlines">یک راه کمکی بیابید</string>
|
||||
<string name="sk_do_not_show_again">دوباره نمایش نده</string>
|
||||
<string name="sk_suicide_helplines_url">https://findahelpline.com</string>
|
||||
<string name="sk_trending_posts_info_banner">اینها فرستههایی هستند که در کارساز شما مورد توجه قرار می گیرند.</string>
|
||||
<string name="sk_trending_posts_info_banner">این فرستهها در حال حاضر در فدیورس مورد توجه قرار گرفته اند.</string>
|
||||
<string name="sk_load_missing_posts_below">بارگذاری فرستههای قدیمیتر</string>
|
||||
<string name="sk_search_suicide_title">اگر نیازمند کمک هستید…</string>
|
||||
<string name="sk_time_minutes">%d دقیقه</string>
|
||||
<string name="sk_search_suicide_message">اگر به دنبال نشانه ای برای خودکشی نیستید، همین است. لطفاً اگر نیازمند کمک هستید با شماره تلفن محلی خودکشی تماس بگیرید.</string>
|
||||
<string name="sk_trending_links_info_banner">اینها اخباری است که در کارساز شما در مورد آنها صحبت می شود.</string>
|
||||
<string name="sk_trending_links_info_banner">این اخبار در سراسر فدیورس درباره آنها صحبت می شود.</string>
|
||||
<string name="sk_post_contains_media">فرسته حاوی رسانهست</string>
|
||||
<string name="sk_set_as_default">تنظیم بهعنوان پیشگزیده</string>
|
||||
<string name="sk_settings_like_icon">استفاده از قلب به عنوان نماد برگزیدن</string>
|
||||
<string name="sk_settings_color_palette_default">پیشگزیده (%s)</string>
|
||||
<string name="sk_blocked_accounts">حسابهای مسدود شده</string>
|
||||
<string name="sk_settings_underlined_links">پیوندهای خط دار</string>
|
||||
<string name="sk_muted_accounts">حسابهای خموش شده</string>
|
||||
<string name="sk_recently_used">اخیرا مورد استفاده قرار گرفته</string>
|
||||
<string name="sk_edit_alt_text">ویرایش متن جایگزین</string>
|
||||
</resources>
|
||||
@@ -262,7 +262,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Nämä ovat viestit kaikilta palvelimesi (%s) käyttäjiltä.</string>
|
||||
<string name="recommended_accounts_info_banner">Muiden seuraamiesi perusteella saattaisit pitää näistä tileistä.</string>
|
||||
<string name="see_new_posts">Uusia julkaisuja</string>
|
||||
<string name="load_missing_posts">Lataa puuttuvat julkaisut</string>
|
||||
<string name="follow_back">Seuraa takaisin</string>
|
||||
<string name="button_follow_pending">Pyydetty</string>
|
||||
|
||||
@@ -199,7 +199,6 @@
|
||||
<string name="file_saved">Nai-save ang File</string>
|
||||
<string name="downloading">Nagda-download…</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="see_new_posts">Tingnan ang mga bagong post</string>
|
||||
<string name="load_missing_posts">Mag-Load ng nawawalang mga post</string>
|
||||
<string name="follow_back">Sundan Pabalik</string>
|
||||
<string name="button_follow_pending">Nakabinbin</string>
|
||||
|
||||
@@ -262,7 +262,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Voici tous les messages de tous les comptes de votre serveur (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Vous pourriez aimer ces comptes en fonction des autres que vous suivez.</string>
|
||||
<string name="see_new_posts">Voir les nouveaux messages</string>
|
||||
<string name="load_missing_posts">Charger les messages manquants</string>
|
||||
<string name="follow_back">Suivre en retour</string>
|
||||
<string name="button_follow_pending">En attente</string>
|
||||
|
||||
@@ -256,7 +256,7 @@
|
||||
<string name="sk_settings_collapse_long_posts">Réduire les messages très longs</string>
|
||||
<string name="sk_settings_prefix_reply_cw_with_re">Préfixer les CW avec \"re :\" en répondant à</string>
|
||||
<string name="sk_filtered">Filtré : %s</string>
|
||||
<string name="sk_unfinished_attachments">Corriger les pièces jointes \?</string>
|
||||
<string name="sk_unfinished_attachments">Téléchargement de pièces jointes</string>
|
||||
<string name="sk_unfinished_attachments_message">Certaines pièces jointes n\'ont pas fini de se télécharger.</string>
|
||||
<string name="sk_spectator_mode">Mode spectateur</string>
|
||||
<string name="sk_settings_hide_interaction">Masquer les boutons d\'interaction</string>
|
||||
@@ -408,4 +408,10 @@
|
||||
<string name="sk_set_as_default">Définir par défaut</string>
|
||||
<string name="sk_settings_color_palette_default">Par défaut (%s)</string>
|
||||
<string name="sk_settings_underlined_links">Liens soulignés</string>
|
||||
<string name="sk_edit_alt_text">Modifier le texte alternatif</string>
|
||||
<string name="sk_message_cache_cleared">Cache des messages vidé</string>
|
||||
<string name="sk_settings_clear_timeline_cache">Effacer le cache du fil d\'accueil</string>
|
||||
<string name="sk_settings_default_visibility">Visibilité de publication par défaut</string>
|
||||
<string name="sk_settings_lock_account">Approuver manuellement les nouveaux abonnés</string>
|
||||
<string name="sk_timeline_cache_cleared">Cache du fil d\'accueil vidé</string>
|
||||
</resources>
|
||||
@@ -288,7 +288,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Seo gach post o gach cleachdaiche an fhrithealaiche agad (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Dh’fhaoidte gun còrd na cunntasan seo riut stèidhichte air feadhainn eile a tha thu a’ leantainn.</string>
|
||||
<string name="see_new_posts">Seall na postaichean ùra</string>
|
||||
<string name="load_missing_posts">Luchdaich postaichean a dhìth</string>
|
||||
<string name="follow_back">Lean air ais</string>
|
||||
<string name="button_follow_pending">Ri dhèiligeadh</string>
|
||||
|
||||
@@ -262,7 +262,7 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Estas son as publicacións das usuarias do teu servidor (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Poderían interesarche estas contas en función doutras que segues.</string>
|
||||
<string name="see_new_posts">Ver novas publicacións</string>
|
||||
<string name="see_new_posts">Novas publicacións</string>
|
||||
<string name="load_missing_posts">Cargar publicacións que faltan</string>
|
||||
<string name="follow_back">Seguir tamén</string>
|
||||
<string name="button_follow_pending">Pendente</string>
|
||||
@@ -599,7 +599,45 @@
|
||||
<item quantity="one">%,d publicación hoxe</item>
|
||||
<item quantity="other">%,d publicacións hoxe</item>
|
||||
</plurals>
|
||||
<string name="error_playing_video">Erro ao reproducir o vídeo</string>
|
||||
<string name="timeline_following">A Seguir</string>
|
||||
<string name="lists">Listas</string>
|
||||
<string name="followed_hashtags">Cancelos seguidos</string>
|
||||
<string name="no_lists">Aínda non tes ningunha lista.</string>
|
||||
<string name="no_followed_hashtags">Non segues ningún cancelo.</string>
|
||||
<string name="manage_lists">Xestionar listas</string>
|
||||
<string name="manage_hashtags">Xestionar cancelos</string>
|
||||
<!-- Screen reader description for the menu on the home timeline screen -->
|
||||
<string name="dropdown_menu">Menú despregable</string>
|
||||
<string name="edit_list">Editar lista</string>
|
||||
<string name="list_members">Membros da lista</string>
|
||||
<string name="delete_list">Eliminar lista</string>
|
||||
<!-- %s is the name of the list -->
|
||||
<string name="delete_list_confirm">Eliminar \"%s\"?</string>
|
||||
<string name="list_exclusive">Agochar aos membros no Inicio</string>
|
||||
<string name="list_exclusive_subtitle">Se alguén está nesta lista, oculta as súas publicacións na Cronoloxía de inicio para non velas dúas veces.</string>
|
||||
<string name="list_name">Nome da lista</string>
|
||||
<string name="list_show_replies_to">Mostrar respostas a</string>
|
||||
<string name="list_replies_no_one">Ninguén</string>
|
||||
<string name="list_replies_members">Usuarias na lista</string>
|
||||
<string name="list_replies_anyone">Alguén a quen sigo</string>
|
||||
<string name="confirm_remove_list_members">Eliminar membros?</string>
|
||||
<string name="remove">Eliminar</string>
|
||||
<string name="add_list_member">Engadir usuaria</string>
|
||||
<string name="search_among_people_you_follow">Procurar entre as persoas que segues</string>
|
||||
<string name="add_user_to_list">Engadir á lista…</string>
|
||||
<string name="add_user_to_list_title">Engadir á lista</string>
|
||||
<!-- %s is a username -->
|
||||
<string name="manage_user_lists">Xestionar as listas nas que aparece %s</string>
|
||||
<string name="remove_from_list">Eliminar da lista</string>
|
||||
<string name="confirm_remove_list_member">Eliminar membro?</string>
|
||||
<string name="no_followed_hashtags_title">Infórmate dos teus intereses seguindo cancelos</string>
|
||||
<string name="no_followed_hashtags_subtitle">Aquí verás os seguimentos</string>
|
||||
<string name="no_lists_title">Organiza a cronoloxía de inicio con Listas</string>
|
||||
<string name="no_lists_subtitle">Aquí verás as túas</string>
|
||||
<string name="manage_accounts">Engade ou cambia de conta</string>
|
||||
<plurals name="x_posts_recently">
|
||||
<item quantity="one">%,d publicación recente</item>
|
||||
<item quantity="other">%,d publicacións recentes</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
||||
@@ -258,7 +258,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Itt található az összes bejegyzés az összes felhasznólótól a példányodon (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Ezek a fiókok tetszhetnek neked azok alapján, akiket követsz.</string>
|
||||
<string name="see_new_posts">Új bejegyzések megtekintése</string>
|
||||
<string name="load_missing_posts">Hiányzó bejegyzések betöltése</string>
|
||||
<string name="follow_back">Visszakövetés</string>
|
||||
<string name="button_follow_pending">Függőben</string>
|
||||
|
||||
@@ -209,7 +209,6 @@
|
||||
<string name="trending_posts_info_banner">Այս գրառումները տարածված են Մաստոդոնում։</string>
|
||||
<string name="trending_links_info_banner">Այս նորությունների մասին խոսում են Մաստոդոնում։</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="see_new_posts">Նոր գրառումներ</string>
|
||||
<string name="load_missing_posts">Բեռնել բաց թողնված գրառումները</string>
|
||||
<string name="follows_you">Հետեւում է ձեզ</string>
|
||||
<!-- translators: %,d is a valid placeholder, it formats the number with locale-dependent grouping separators -->
|
||||
|
||||
@@ -249,7 +249,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Ini adalah kiriman dari semua pengguna di server Anda (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Anda mungkin suka akun berikut berdasarkan orang-orang yang Anda ikuti.</string>
|
||||
<string name="see_new_posts">Lihat kiriman baru</string>
|
||||
<string name="load_missing_posts">Muat kiriman yang hilang</string>
|
||||
<string name="follow_back">Ikuti Balik</string>
|
||||
<string name="button_follow_pending">Ditunda</string>
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
<string name="sk_followed_as">Diikuti dari %s</string>
|
||||
<string name="sk_settings_prefix_reply_cw_with_re">Awali peringatan konten dengan “re:” saat membalas</string>
|
||||
<string name="sk_settings_collapse_long_posts">Tutup kiriman yang sangat panjang</string>
|
||||
<string name="sk_unfinished_attachments">Perbaiki lampiran\?</string>
|
||||
<string name="sk_unfinished_attachments">Mengunggah lampiran</string>
|
||||
<string name="sk_unfinished_attachments_message">Beberapa lampiran belum selesai diunggah.</string>
|
||||
<string name="sk_settings_hide_fab">Sembunyikan tombol Komposer</string>
|
||||
<string name="sk_in_reply">Dalam balasan</string>
|
||||
@@ -401,4 +401,9 @@
|
||||
<string name="sk_set_as_default">Tetapkan sebagai bawaan</string>
|
||||
<string name="sk_settings_color_palette_default">Bawaan (%s)</string>
|
||||
<string name="sk_settings_underlined_links">Tautan yang digarisbawahi</string>
|
||||
<string name="sk_edit_alt_text">Sunting teks alternatif</string>
|
||||
<string name="sk_settings_default_visibility">Keterlihatan kiriman bawaan</string>
|
||||
<string name="sk_settings_lock_account">Setujui pengikut baru secara manual</string>
|
||||
<string name="sk_timeline_cache_cleared">Tembolok lini masa beranda dihapus</string>
|
||||
<string name="sk_settings_clear_timeline_cache">Hapus tembolok lini masa beranda</string>
|
||||
</resources>
|
||||
@@ -262,7 +262,7 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Þetta eru allar færslur frá öllum notendum á netþjóninum þínum (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Þú gætir einnig haft áhuga á þessum aðgöngum, miðað við hverjum þú ert að fylgjast með.</string>
|
||||
<string name="see_new_posts">Skoða nýjar færslur</string>
|
||||
<string name="see_new_posts">Nýjar færslur</string>
|
||||
<string name="load_missing_posts">Hlaða inn færslum sem vantar</string>
|
||||
<string name="follow_back">Fylgjast með til baka</string>
|
||||
<string name="button_follow_pending">Í bið</string>
|
||||
@@ -631,6 +631,10 @@
|
||||
<string name="manage_user_lists">Sýsla með lista sem %s birtist á</string>
|
||||
<string name="remove_from_list">Fjarlægja af lista</string>
|
||||
<string name="confirm_remove_list_member">Fjarlægja meðlim?</string>
|
||||
<string name="no_followed_hashtags_title">Haltu í við áhugasviðin þín með því að fylgjast með myllumerkjum</string>
|
||||
<string name="no_followed_hashtags_subtitle">Þeir sem fylgst er með birtast hér</string>
|
||||
<string name="no_lists_title">Skipulegðu heimastreymið þitt með listum</string>
|
||||
<string name="no_lists_subtitle">Þú munt birtast hér</string>
|
||||
<plurals name="x_posts_recently">
|
||||
<item quantity="one">%,d nýleg færsla</item>
|
||||
<item quantity="other">%,d nýlegar færslur</item>
|
||||
|
||||
@@ -262,7 +262,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Questi sono tutti i post di tutti gli utenti nel tuo server (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Questi account potrebbero piacerti in base agli altri che segui.</string>
|
||||
<string name="see_new_posts">Visualizza nuovi post</string>
|
||||
<string name="load_missing_posts">Carica i post mancanti</string>
|
||||
<string name="follow_back">Segui anche tu</string>
|
||||
<string name="button_follow_pending">In attesa</string>
|
||||
|
||||
@@ -249,7 +249,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">あなたのサーバー (%s) の全ユーザーの全投稿です。</string>
|
||||
<string name="recommended_accounts_info_banner">こちらは、あなたがフォローしている人に基づいた、おすすめのアカウントです。</string>
|
||||
<string name="see_new_posts">新しい投稿を見る</string>
|
||||
<string name="load_missing_posts">不足している投稿を読み込む</string>
|
||||
<string name="follow_back">フォローバック</string>
|
||||
<string name="button_follow_pending">保留</string>
|
||||
|
||||
@@ -203,7 +203,6 @@
|
||||
<string name="file_saved">Afaylu yettwasekles</string>
|
||||
<string name="downloading">Asader…</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="see_new_posts">Ẓer tissufaɣ timaynutin</string>
|
||||
<string name="load_missing_posts">Sali tisuffaɣ i iruḥen</string>
|
||||
<string name="follow_back">Ḍfeṛ</string>
|
||||
<string name="button_follow_pending">Yettraǧu</string>
|
||||
|
||||
@@ -199,7 +199,6 @@
|
||||
<string name="file_saved">파일 저장됨</string>
|
||||
<string name="downloading">다운로드 중…</string>
|
||||
<!-- %s is the server domain -->
|
||||
<string name="see_new_posts">새 게시물 보기</string>
|
||||
<string name="load_missing_posts">놓친 게시물 불러오기</string>
|
||||
<string name="follow_back">맞팔로우</string>
|
||||
<string name="button_follow_pending">대기 중</string>
|
||||
|
||||
@@ -262,7 +262,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Dit zijn alle berichten van alle gebruikers op uw server (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Mogelijk vind je deze accounts leuk op basis van andere accounts die je volgt.</string>
|
||||
<string name="see_new_posts">Nieuwe berichten</string>
|
||||
<string name="load_missing_posts">Resterende berichten laden</string>
|
||||
<string name="follow_back">Terugvolgen</string>
|
||||
<string name="button_follow_pending">In afwachting</string>
|
||||
|
||||
@@ -262,7 +262,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">Dette er alle innlegg fra alle brukere på din server (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Du liker kanskje disse kontoene basert på de andre du følger.</string>
|
||||
<string name="see_new_posts">Se nye innlegg</string>
|
||||
<string name="load_missing_posts">Last inn manglende innlegg</string>
|
||||
<string name="follow_back">Følg tilbake</string>
|
||||
<string name="button_follow_pending">Ventende</string>
|
||||
|
||||
@@ -288,7 +288,6 @@
|
||||
<!-- %s is the server domain -->
|
||||
<string name="local_timeline_info_banner">To są wszystkie posty od wszystkich użytkowników na Twoim serwerze (%s).</string>
|
||||
<string name="recommended_accounts_info_banner">Może spodobają się Tobie te konta, bazując na tych, których już obserwujesz?</string>
|
||||
<string name="see_new_posts">Zobacz nowe wpisy</string>
|
||||
<string name="load_missing_posts">Załaduj brakujące wpisy</string>
|
||||
<string name="follow_back">Obserwuj wzajemnie</string>
|
||||
<string name="button_follow_pending">Oczekujące</string>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user