Merge branch 'LucasGGamerM:master' into master
This commit is contained in:
39
mastodon/src/main/assets/blocks.tsv
Normal file
39
mastodon/src/main/assets/blocks.tsv
Normal file
@@ -0,0 +1,39 @@
|
||||
# lists.d Mastodon Blocklist (c) 2022 Greyhat Academy LICENSED UNDER: CC-BY-NC-SA 4.0
|
||||
# https://raw.githubusercontent.com/greyhat-academy/lists.d/main/mastodon.domains.block.list.tsv
|
||||
# This list contains domains of toxic mastodon instances
|
||||
# Last-Modified: 1672044500
|
||||
|
||||
# gab - a neonazi social network
|
||||
gab.ai
|
||||
gab.com
|
||||
gab.protohype.net
|
||||
|
||||
# consequence-free speech
|
||||
social.unzensiert.to
|
||||
freeatlantis.com
|
||||
|
||||
# reactionary bigotry and hatespeech against magrinalized groups
|
||||
poa.st
|
||||
freespeechextremist.com
|
||||
rdrama.cc
|
||||
outpoa.st
|
||||
anime.website
|
||||
gameliberty.club
|
||||
social.byoblu.com
|
||||
yggdrasil.social
|
||||
smuglo.li
|
||||
dogeposting.social
|
||||
unsafe.space
|
||||
freezepeach.xyz
|
||||
|
||||
# + CSAM
|
||||
rojogato.com
|
||||
|
||||
# antivaxxer shitposting & fearmongering
|
||||
shadowsocial.org
|
||||
|
||||
# Kiwifarms
|
||||
kiwifarms.net
|
||||
kiwifarms.cc
|
||||
kiwifarms.is
|
||||
kiwifarms.pleroma.net
|
||||
|
@@ -53,7 +53,10 @@ public class ExternalShareActivity extends FragmentStackActivity{
|
||||
Intent intent=getIntent();
|
||||
StringBuilder builder=new StringBuilder();
|
||||
String subject = "";
|
||||
if (intent.hasExtra(Intent.EXTRA_SUBJECT)) builder.append(subject = intent.getStringExtra(Intent.EXTRA_SUBJECT)).append("\n\n");
|
||||
if (intent.hasExtra(Intent.EXTRA_SUBJECT)) {
|
||||
subject = intent.getStringExtra(Intent.EXTRA_SUBJECT);
|
||||
if (!subject.isBlank()) builder.append(subject).append("\n\n");
|
||||
}
|
||||
if (intent.hasExtra(Intent.EXTRA_TEXT)) builder.append(intent.getStringExtra(Intent.EXTRA_TEXT)).append("\n");
|
||||
String text=builder.toString();
|
||||
List<Uri> mediaUris;
|
||||
|
||||
@@ -16,7 +16,8 @@ import org.joinmastodon.android.fragments.HomeFragment;
|
||||
import org.joinmastodon.android.fragments.ProfileFragment;
|
||||
import org.joinmastodon.android.fragments.ThreadFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.AccountActivationFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.CustomLoginFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.CustomWelcomeFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.CustomWelcomeFragment;
|
||||
import org.joinmastodon.android.model.Notification;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.joinmastodon.android.updater.GithubSelfUpdater;
|
||||
@@ -33,7 +34,7 @@ public class MainActivity extends FragmentStackActivity{
|
||||
|
||||
if(savedInstanceState==null){
|
||||
if(AccountSessionManager.getInstance().getLoggedInAccounts().isEmpty()){
|
||||
showFragmentClearingBackStack(new CustomLoginFragment());
|
||||
showFragmentClearingBackStack(new CustomWelcomeFragment());
|
||||
}else{
|
||||
AccountSessionManager.getInstance().maybeUpdateLocalInfo();
|
||||
AccountSession session;
|
||||
|
||||
@@ -12,11 +12,14 @@ import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import org.joinmastodon.android.BuildConfig;
|
||||
import org.joinmastodon.android.MastodonApp;
|
||||
import org.joinmastodon.android.api.gson.IsoInstantTypeAdapter;
|
||||
import org.joinmastodon.android.api.gson.IsoLocalDateTypeAdapter;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
@@ -47,9 +50,22 @@ public class MastodonAPIController{
|
||||
private static OkHttpClient httpClient=new OkHttpClient.Builder().build();
|
||||
|
||||
private AccountSession session;
|
||||
private static List<String> badDomains = new ArrayList<>();
|
||||
|
||||
static{
|
||||
thread.start();
|
||||
try {
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(
|
||||
MastodonApp.context.getAssets().open("blocks.tsv")
|
||||
));
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.isBlank() || line.startsWith("#")) continue;
|
||||
badDomains.add(line.toLowerCase().trim());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public MastodonAPIController(@Nullable AccountSession session){
|
||||
@@ -57,8 +73,11 @@ public class MastodonAPIController{
|
||||
}
|
||||
|
||||
public <T> void submitRequest(final MastodonAPIRequest<T> req){
|
||||
final String host = req.getURL().getHost().toLowerCase();
|
||||
final boolean isBad = badDomains.stream().anyMatch(host::endsWith);
|
||||
thread.postRunnable(()->{
|
||||
try{
|
||||
if (isBad) throw new IllegalArgumentException();
|
||||
if(req.canceled)
|
||||
return;
|
||||
Request.Builder builder=new Request.Builder()
|
||||
|
||||
@@ -162,6 +162,8 @@ public class PushSubscriptionManager{
|
||||
@Override
|
||||
public void onSuccess(PushSubscription result){
|
||||
MastodonAPIController.runInBackground(()->{
|
||||
result.serverKey=result.serverKey.replace('/','_');
|
||||
result.serverKey=result.serverKey.replace('+','-');
|
||||
serverKey=deserializeRawPublicKey(Base64.decode(result.serverKey, Base64.URL_SAFE));
|
||||
|
||||
AccountSession session=AccountSessionManager.getInstance().tryGetAccount(accountID);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.joinmastodon.android.api.requests.announcements;
|
||||
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
|
||||
public class DismissAnnouncement extends MastodonAPIRequest<Object>{
|
||||
public DismissAnnouncement(String id){
|
||||
super(HttpMethod.POST, "/announcements/" + id + "/dismiss", Object.class);
|
||||
setRequestBody(new Object());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.joinmastodon.android.api.requests.announcements;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||
import org.joinmastodon.android.model.Announcement;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GetAnnouncements extends MastodonAPIRequest<List<Announcement>> {
|
||||
public GetAnnouncements(boolean withDismissed) {
|
||||
super(MastodonAPIRequest.HttpMethod.GET, "/announcements", new TypeToken<>(){});
|
||||
addQueryParameter("with_dismissed", withDismissed ? "true" : "false");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package org.joinmastodon.android.fragments;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.joinmastodon.android.E;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.announcements.GetAnnouncements;
|
||||
import org.joinmastodon.android.api.requests.statuses.CreateStatus;
|
||||
import org.joinmastodon.android.api.requests.statuses.GetScheduledStatuses;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.events.ScheduledStatusCreatedEvent;
|
||||
import org.joinmastodon.android.events.ScheduledStatusDeletedEvent;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Announcement;
|
||||
import org.joinmastodon.android.model.HeaderPaginationList;
|
||||
import org.joinmastodon.android.model.Instance;
|
||||
import org.joinmastodon.android.model.ScheduledStatus;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
import org.joinmastodon.android.ui.displayitems.HeaderStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.StatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.displayitems.TextStatusDisplayItem;
|
||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
import org.parceler.Parcels;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.api.PaginatedList;
|
||||
import me.grishka.appkit.api.SimpleCallback;
|
||||
|
||||
public class AnnouncementsFragment extends BaseStatusListFragment<Announcement> {
|
||||
private Instance instance;
|
||||
private AccountSession session;
|
||||
private List<String> unreadIDs = null;
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity){
|
||||
super.onAttach(activity);
|
||||
setTitle(R.string.sk_announcements);
|
||||
session = AccountSessionManager.getInstance().getAccount(accountID);
|
||||
instance = AccountSessionManager.getInstance().getInstanceInfo(session.domain);
|
||||
loadData();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<StatusDisplayItem> buildDisplayItems(Announcement a) {
|
||||
if(TextUtils.isEmpty(a.content)) return List.of();
|
||||
Account instanceUser = new Account();
|
||||
instanceUser.id = instanceUser.acct = instanceUser.username = session.domain;
|
||||
instanceUser.displayName = instance.title;
|
||||
instanceUser.url = "https://"+session.domain+"/about";
|
||||
instanceUser.avatar = instanceUser.avatarStatic = instance.thumbnail;
|
||||
instanceUser.emojis = List.of();
|
||||
Status fakeStatus = a.toStatus();
|
||||
return List.of(
|
||||
HeaderStatusDisplayItem.fromAnnouncement(a, fakeStatus, instanceUser, this, accountID, this::onMarkAsRead),
|
||||
new TextStatusDisplayItem(a.id, HtmlParser.parse(a.content, a.emojis, a.mentions, a.tags, accountID), this, fakeStatus)
|
||||
);
|
||||
}
|
||||
|
||||
public void onMarkAsRead(String id) {
|
||||
if (unreadIDs == null) return;
|
||||
unreadIDs.remove(id);
|
||||
if (unreadIDs.size() == 0) setResult(true, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addAccountToKnown(Announcement s) {}
|
||||
|
||||
@Override
|
||||
public void onItemClick(String id) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDataLoaded(List<Announcement> d, boolean more) {
|
||||
unreadIDs = d.stream().filter(a -> !a.read).map(a -> a.id).collect(Collectors.toList());
|
||||
super.onDataLoaded(d, more);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doLoadData(int offset, int count){
|
||||
currentRequest=new GetAnnouncements(true)
|
||||
.setCallback(new SimpleCallback<>(this){
|
||||
@Override
|
||||
public void onSuccess(List<Announcement> result){
|
||||
onDataLoaded(result, false);
|
||||
}
|
||||
})
|
||||
.exec(accountID);
|
||||
}
|
||||
}
|
||||
@@ -307,12 +307,14 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
|
||||
draftsBtn=view.findViewById(R.id.drafts_btn);
|
||||
draftsBtn.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
charCounter=view.findViewById(R.id.char_counter);
|
||||
charCounter.setVisibility(View.VISIBLE);
|
||||
charCounter.setText(String.valueOf(charLimit));
|
||||
}
|
||||
|
||||
mainEditText=view.findViewById(R.id.toot_text);
|
||||
mainEditTextWrap=view.findViewById(R.id.toot_text_wrap);
|
||||
charCounter=view.findViewById(R.id.char_counter);
|
||||
charCounter.setText(String.valueOf(charLimit));
|
||||
scrollView=view.findViewById(R.id.scroll_view);
|
||||
|
||||
selfName=view.findViewById(R.id.self_name);
|
||||
@@ -588,10 +590,10 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
scrollView.post(() -> {
|
||||
int bottom = scrollView.getChildAt(0).getBottom();
|
||||
int delta = bottom - (scrollView.getScrollY() + scrollView.getHeight());
|
||||
int space = GlobalUserPreferences.reduceMotion ? 0 : Math.min(V.dp(120), delta);
|
||||
int space = GlobalUserPreferences.reduceMotion ? 0 : Math.min(V.dp(70), delta);
|
||||
scrollView.scrollBy(0, delta - space);
|
||||
if (!GlobalUserPreferences.reduceMotion) {
|
||||
scrollView.postDelayed(() -> scrollView.smoothScrollBy(0, space), 100);
|
||||
scrollView.postDelayed(() -> scrollView.smoothScrollBy(0, space), 130);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -621,6 +623,7 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
args.putParcelable("profileAccount", Parcels.wrap(replyTo.account));
|
||||
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||||
Nav.go(getActivity(), ProfileFragment.class, args);
|
||||
});
|
||||
|
||||
@@ -651,6 +654,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
|
||||
replyText.setText(getString(R.string.in_reply_to, replyTo.account.displayName));
|
||||
replyText.setContentDescription(getString(R.string.in_reply_to, replyTo.account.displayName) + ". " + getString(R.string.post_visibility) + ": " + UiUtils.getVisibilityText(replyTo));
|
||||
replyText.setOnClickListener(v->{
|
||||
scrollView.smoothScrollTo(0, 0);
|
||||
});
|
||||
|
||||
ArrayList<String> mentions=new ArrayList<>();
|
||||
String ownID=AccountSessionManager.getInstance().getAccount(accountID).self.id;
|
||||
@@ -748,6 +754,10 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
||||
|
||||
draftsBtn = wrap.findViewById(R.id.drafts_btn);
|
||||
draftsBtn.setVisibility(View.VISIBLE);
|
||||
}else{
|
||||
charCounter = wrap.findViewById(R.id.char_counter);
|
||||
charCounter.setVisibility(View.VISIBLE);
|
||||
charCounter.setText(String.valueOf(charLimit));
|
||||
}
|
||||
|
||||
// draftsBtn = wrap.findViewById(R.id.drafts_btn);
|
||||
|
||||
@@ -29,10 +29,12 @@ import com.squareup.otto.Subscribe;
|
||||
import org.joinmastodon.android.E;
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.announcements.GetAnnouncements;
|
||||
import org.joinmastodon.android.api.requests.timelines.GetHomeTimeline;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.events.SelfUpdateStateChangedEvent;
|
||||
import org.joinmastodon.android.events.StatusCreatedEvent;
|
||||
import org.joinmastodon.android.model.Announcement;
|
||||
import org.joinmastodon.android.model.CacheablePaginatedResponse;
|
||||
import org.joinmastodon.android.model.Filter;
|
||||
import org.joinmastodon.android.model.Status;
|
||||
@@ -56,11 +58,14 @@ import me.grishka.appkit.utils.CubicBezierInterpolator;
|
||||
import me.grishka.appkit.utils.V;
|
||||
|
||||
public class HomeTimelineFragment extends StatusListFragment{
|
||||
private static final int ANNOUNCEMENTS_RESULT = 654;
|
||||
|
||||
private ImageButton fab;
|
||||
private ImageView toolbarLogo;
|
||||
private Button toolbarShowNewPostsBtn;
|
||||
private boolean newPostsBtnShown;
|
||||
private AnimatorSet currentNewPostsAnim;
|
||||
private MenuItem announcements;
|
||||
|
||||
private String maxID;
|
||||
|
||||
@@ -126,16 +131,40 @@ public class HomeTimelineFragment extends StatusListFragment{
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater){
|
||||
inflater.inflate(R.menu.home, menu);
|
||||
announcements = menu.findItem(R.id.announcements);
|
||||
|
||||
new GetAnnouncements(false).setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(List<Announcement> result) {
|
||||
boolean hasUnread = result.stream().anyMatch(a -> !a.read);
|
||||
announcements.setIcon(hasUnread ? R.drawable.ic_announcements_24_badged : R.drawable.ic_fluent_megaphone_24_regular);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error) {
|
||||
error.showToast(getActivity());
|
||||
}
|
||||
}).exec(accountID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item){
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", accountID);
|
||||
Nav.go(getActivity(), SettingsFragment.class, args);
|
||||
if (item.getItemId() == R.id.settings) Nav.go(getActivity(), SettingsFragment.class, args);
|
||||
if (item.getItemId() == R.id.announcements) {
|
||||
Nav.goForResult(getActivity(), AnnouncementsFragment.class, args, ANNOUNCEMENTS_RESULT, this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFragmentResult(int reqCode, boolean noMoreUnread, Bundle result){
|
||||
if (reqCode == ANNOUNCEMENTS_RESULT && noMoreUnread) {
|
||||
announcements.setIcon(R.drawable.ic_fluent_megaphone_24_regular);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig){
|
||||
super.onConfigurationChanged(newConfig);
|
||||
@@ -188,10 +217,8 @@ public class HomeTimelineFragment extends StatusListFragment{
|
||||
result.get(result.size()-1).hasGapAfter=true;
|
||||
toAdd=result;
|
||||
}
|
||||
List<Filter> filters=AccountSessionManager.getInstance().getAccount(accountID).wordFilters.stream().filter(f->f.context.contains(Filter.FilterContext.HOME)).collect(Collectors.toList());
|
||||
if(!filters.isEmpty()){
|
||||
toAdd=toAdd.stream().filter(new StatusFilterPredicate(filters)).collect(Collectors.toList());
|
||||
}
|
||||
StatusFilterPredicate filterPredicate=new StatusFilterPredicate(accountID, Filter.FilterContext.HOME);
|
||||
toAdd=toAdd.stream().filter(filterPredicate).collect(Collectors.toList());
|
||||
if(!toAdd.isEmpty()){
|
||||
prependItems(toAdd, true);
|
||||
showNewPostsButton();
|
||||
|
||||
@@ -36,10 +36,10 @@ import me.grishka.appkit.utils.SingleViewRecyclerAdapter;
|
||||
import me.grishka.appkit.utils.V;
|
||||
import me.grishka.appkit.views.UsableRecyclerView;
|
||||
|
||||
public class CustomLoginFragment extends InstanceCatalogFragment {
|
||||
public class CustomWelcomeFragment extends InstanceCatalogFragment {
|
||||
private View headerView;
|
||||
|
||||
public CustomLoginFragment() {
|
||||
public CustomWelcomeFragment() {
|
||||
super(R.layout.fragment_welcome_custom, 1);
|
||||
}
|
||||
|
||||
@@ -55,9 +55,9 @@ public class CustomLoginFragment extends InstanceCatalogFragment {
|
||||
dataLoaded();
|
||||
}
|
||||
|
||||
// @Override
|
||||
@Override
|
||||
protected void onUpdateToolbar(){
|
||||
// super.onUpdateToolbar();
|
||||
super.onUpdateToolbar();
|
||||
|
||||
if (!canGoBack()) {
|
||||
ImageView toolbarLogo=new ImageView(getActivity());
|
||||
@@ -137,9 +137,11 @@ public class CustomLoginFragment extends InstanceCatalogFragment {
|
||||
|
||||
headerView.findViewById(R.id.more).setVisibility(View.GONE);
|
||||
headerView.findViewById(R.id.visibility).setVisibility(View.GONE);
|
||||
((TextView) headerView.findViewById(R.id.username)).setText("@moshidon");
|
||||
headerView.findViewById(R.id.separator).setVisibility(View.GONE);
|
||||
headerView.findViewById(R.id.timestamp).setVisibility(View.GONE);
|
||||
headerView.findViewById(R.id.unread_indicator).setVisibility(View.GONE);
|
||||
((TextView) headerView.findViewById(R.id.username)).setText(R.string.sk_app_username);
|
||||
((TextView) headerView.findViewById(R.id.name)).setText(R.string.sk_app_name);
|
||||
((TextView) headerView.findViewById(R.id.timestamp)).setText(R.string.time_now);
|
||||
((ImageView) headerView.findViewById(R.id.avatar)).setImageDrawable(getActivity().getDrawable(R.mipmap.ic_launcher));
|
||||
((FragmentStackActivity) getActivity()).invalidateSystemBarColors(this);
|
||||
|
||||
@@ -168,7 +170,7 @@ public class CustomLoginFragment extends InstanceCatalogFragment {
|
||||
return mergeAdapter;
|
||||
}
|
||||
|
||||
private class InstancesAdapter extends UsableRecyclerView.Adapter<InstanceViewHolder>{
|
||||
private class InstancesAdapter extends UsableRecyclerView.Adapter<InstanceViewHolder> {
|
||||
public InstancesAdapter(){
|
||||
super(imgLoader);
|
||||
}
|
||||
@@ -204,11 +206,6 @@ public class CustomLoginFragment extends InstanceCatalogFragment {
|
||||
|
||||
public InstanceViewHolder(){
|
||||
super(getActivity(), R.layout.item_instance_custom, list);
|
||||
|
||||
// itemView.setPadding(V.dp(16), V.dp(16), V.dp(16), V.dp(16));
|
||||
// TypedValue value = new TypedValue();
|
||||
// getActivity().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true);
|
||||
// itemView.setBackground(getActivity().getTheme().getDrawable(R.drawable.bg_search_field));
|
||||
title=findViewById(R.id.title);
|
||||
description=findViewById(R.id.description);
|
||||
userCount=findViewById(R.id.user_count);
|
||||
@@ -0,0 +1,63 @@
|
||||
package org.joinmastodon.android.model;
|
||||
|
||||
import org.joinmastodon.android.api.RequiredField;
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Parcel
|
||||
public class Announcement extends BaseModel implements DisplayItemsParent {
|
||||
@RequiredField
|
||||
public String id;
|
||||
@RequiredField
|
||||
public String content;
|
||||
public Instant startsAt;
|
||||
public Instant endsAt;
|
||||
public boolean published;
|
||||
public boolean allDay;
|
||||
public Instant publishedAt;
|
||||
public Instant updatedAt;
|
||||
public boolean read;
|
||||
public List<Emoji> emojis;
|
||||
public List<Mention> mentions;
|
||||
public List<Hashtag> tags;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Announcement{" +
|
||||
"id='" + id + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
", startsAt=" + startsAt +
|
||||
", endsAt=" + endsAt +
|
||||
", published=" + published +
|
||||
", allDay=" + allDay +
|
||||
", publishedAt=" + publishedAt +
|
||||
", updatedAt=" + updatedAt +
|
||||
", read=" + read +
|
||||
", emojis=" + emojis +
|
||||
", mentions=" + mentions +
|
||||
", tags=" + tags +
|
||||
'}';
|
||||
}
|
||||
|
||||
public Status toStatus() {
|
||||
Status s = new Status();
|
||||
s.id = id;
|
||||
s.mediaAttachments = List.of();
|
||||
s.createdAt = startsAt != null ? startsAt : publishedAt;
|
||||
if (updatedAt != null) s.editedAt = updatedAt;
|
||||
s.content = s.text = content;
|
||||
s.spoilerText = "";
|
||||
s.visibility = StatusPrivacy.PUBLIC;
|
||||
s.mentions = List.of();
|
||||
s.tags = List.of();
|
||||
s.emojis = List.of();
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,8 @@ import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.oauth.RevokeOauthToken;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
import org.joinmastodon.android.api.session.AccountSessionManager;
|
||||
import org.joinmastodon.android.fragments.onboarding.CustomLoginFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.CustomWelcomeFragment;
|
||||
import org.joinmastodon.android.fragments.onboarding.CustomWelcomeFragment;
|
||||
import org.joinmastodon.android.ui.utils.UiUtils;
|
||||
|
||||
import java.util.List;
|
||||
@@ -77,7 +78,7 @@ public class AccountSwitcherSheet extends BottomSheet{
|
||||
holder.avatar.setImageResource(R.drawable.ic_fluent_add_circle_24_filled);
|
||||
holder.avatar.setImageTintList(ColorStateList.valueOf(UiUtils.getThemeColor(activity, android.R.attr.textColorPrimary)));
|
||||
adapter.addAdapter(new ClickableSingleViewRecyclerAdapter(holder.itemView, ()->{
|
||||
Nav.go(activity, CustomLoginFragment.class, null);
|
||||
Nav.go(activity, CustomWelcomeFragment.class, null);
|
||||
dismiss();
|
||||
}));
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.widget.Toast;
|
||||
import org.joinmastodon.android.GlobalUserPreferences;
|
||||
import org.joinmastodon.android.R;
|
||||
import org.joinmastodon.android.api.requests.accounts.GetAccountRelationships;
|
||||
import org.joinmastodon.android.api.requests.announcements.DismissAnnouncement;
|
||||
import org.joinmastodon.android.api.requests.statuses.CreateStatus;
|
||||
import org.joinmastodon.android.api.requests.statuses.GetStatusSourceText;
|
||||
import org.joinmastodon.android.api.session.AccountSession;
|
||||
@@ -35,6 +36,7 @@ import org.joinmastodon.android.fragments.ProfileFragment;
|
||||
import org.joinmastodon.android.fragments.ThreadFragment;
|
||||
import org.joinmastodon.android.fragments.report.ReportReasonChoiceFragment;
|
||||
import org.joinmastodon.android.model.Account;
|
||||
import org.joinmastodon.android.model.Announcement;
|
||||
import org.joinmastodon.android.model.Attachment;
|
||||
import org.joinmastodon.android.model.Notification;
|
||||
import org.joinmastodon.android.model.Relationship;
|
||||
@@ -52,6 +54,7 @@ import java.time.format.FormatStyle;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import me.grishka.appkit.Nav;
|
||||
import me.grishka.appkit.api.APIRequest;
|
||||
@@ -75,6 +78,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
private String extraText;
|
||||
private Notification notification;
|
||||
private ScheduledStatus scheduledStatus;
|
||||
private Announcement announcement;
|
||||
private Consumer<String> consumeReadAnnouncement;
|
||||
|
||||
public HeaderStatusDisplayItem(String parentID, Account user, Instant createdAt, BaseStatusListFragment parentFragment, String accountID, Status status, String extraText, Notification notification, ScheduledStatus scheduledStatus){
|
||||
super(parentID, parentFragment);
|
||||
@@ -103,6 +108,13 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
this.extraText=extraText;
|
||||
}
|
||||
|
||||
public static HeaderStatusDisplayItem fromAnnouncement(Announcement a, Status fakeStatus, Account instanceUser, BaseStatusListFragment parentFragment, String accountID, Consumer<String> consumeReadID) {
|
||||
HeaderStatusDisplayItem item = new HeaderStatusDisplayItem(a.id, instanceUser, a.startsAt, parentFragment, accountID, fakeStatus, null, null, null);
|
||||
item.announcement = a;
|
||||
item.consumeReadAnnouncement = consumeReadID;
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(){
|
||||
return Type.HEADER;
|
||||
@@ -122,8 +134,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
}
|
||||
|
||||
public static class Holder extends StatusDisplayItem.Holder<HeaderStatusDisplayItem> implements ImageLoaderViewHolder{
|
||||
private final TextView name, username, timestamp, extraText;
|
||||
private final ImageView avatar, more, visibility, deleteNotification;
|
||||
private final TextView name, username, timestamp, extraText, separator;
|
||||
private final ImageView avatar, more, visibility, deleteNotification, unreadIndicator;
|
||||
private final PopupMenu optionsMenu;
|
||||
private Relationship relationship;
|
||||
private APIRequest<?> currentRelationshipRequest;
|
||||
@@ -139,11 +151,13 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
super(activity, R.layout.display_item_header, parent);
|
||||
name=findViewById(R.id.name);
|
||||
username=findViewById(R.id.username);
|
||||
separator=findViewById(R.id.separator);
|
||||
timestamp=findViewById(R.id.timestamp);
|
||||
avatar=findViewById(R.id.avatar);
|
||||
more=findViewById(R.id.more);
|
||||
visibility=findViewById(R.id.visibility);
|
||||
deleteNotification=findViewById(R.id.delete_notification);
|
||||
unreadIndicator=findViewById(R.id.unread_indicator);
|
||||
extraText=findViewById(R.id.extra_text);
|
||||
avatar.setOnClickListener(this::onAvaClick);
|
||||
avatar.setOutlineProvider(roundCornersOutline);
|
||||
@@ -268,6 +282,8 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
public void onBind(HeaderStatusDisplayItem item){
|
||||
name.setText(item.parsedName);
|
||||
username.setText('@'+item.user.acct);
|
||||
separator.setVisibility(View.VISIBLE);
|
||||
|
||||
|
||||
username.setCompoundDrawablesWithIntrinsicBounds(item.user.bot ? R.drawable.ic_fluent_bot_24_filled : 0, 0, 0, 0);
|
||||
|
||||
@@ -278,10 +294,14 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withLocale(Locale.getDefault());
|
||||
timestamp.setText(item.scheduledStatus.scheduledAt.atZone(ZoneId.systemDefault()).format(formatter));
|
||||
}
|
||||
else if(item.status==null || item.status.editedAt==null)
|
||||
else if ((item.status==null || item.status.editedAt==null) && item.createdAt != null)
|
||||
timestamp.setText(UiUtils.formatRelativeTimestamp(itemView.getContext(), item.createdAt));
|
||||
else
|
||||
else if (item.status != null && item.status.editedAt != null)
|
||||
timestamp.setText(item.parentFragment.getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(itemView.getContext(), item.status.editedAt)));
|
||||
else {
|
||||
separator.setVisibility(View.GONE);
|
||||
timestamp.setText("");
|
||||
}
|
||||
visibility.setVisibility(item.hasVisibilityToggle && !item.inset ? View.VISIBLE : View.GONE);
|
||||
deleteNotification.setVisibility(GlobalUserPreferences.enableDeleteNotifications && item.notification!=null && !item.inset ? View.VISIBLE : View.GONE);
|
||||
if(item.hasVisibilityToggle){
|
||||
@@ -305,6 +325,42 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
currentRelationshipRequest.cancel();
|
||||
}
|
||||
relationship=null;
|
||||
|
||||
String desc;
|
||||
if (item.announcement != null) {
|
||||
if (unreadIndicator.getVisibility() == View.GONE) {
|
||||
more.setAlpha(0f);
|
||||
unreadIndicator.setAlpha(0f);
|
||||
unreadIndicator.setVisibility(View.VISIBLE);
|
||||
}
|
||||
float alpha = item.announcement.read ? 0 : 1;
|
||||
more.setImageResource(R.drawable.ic_fluent_checkmark_20_filled);
|
||||
desc = item.parentFragment.getString(R.string.sk_mark_as_read);
|
||||
more.animate().alpha(alpha);
|
||||
unreadIndicator.animate().alpha(alpha);
|
||||
more.setOnClickListener(v -> {
|
||||
new DismissAnnouncement(item.announcement.id).setCallback(new Callback<>() {
|
||||
@Override
|
||||
public void onSuccess(Object o) {
|
||||
item.consumeReadAnnouncement.accept(item.announcement.id);
|
||||
item.announcement.read = true;
|
||||
rebind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(ErrorResponse error) {
|
||||
error.showToast(item.parentFragment.getActivity());
|
||||
}
|
||||
}).exec(item.accountID);
|
||||
});
|
||||
} else {
|
||||
more.setImageResource(R.drawable.ic_fluent_more_vertical_20_filled);
|
||||
desc = item.parentFragment.getString(R.string.more_options);
|
||||
more.setOnClickListener(this::onMoreClick);
|
||||
}
|
||||
|
||||
more.setContentDescription(desc);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) more.setTooltipText(desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -325,6 +381,10 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
}
|
||||
|
||||
private void onAvaClick(View v){
|
||||
if (item.announcement != null) {
|
||||
UiUtils.openURL(item.parentFragment.getActivity(), item.parentFragment.getAccountID(), item.user.url);
|
||||
return;
|
||||
}
|
||||
Bundle args=new Bundle();
|
||||
args.putString("account", item.accountID);
|
||||
args.putParcelable("profileAccount", Parcels.wrap(item.user));
|
||||
@@ -356,6 +416,7 @@ public class HeaderStatusDisplayItem extends StatusDisplayItem{
|
||||
}
|
||||
|
||||
private void updateOptionsMenu(){
|
||||
if (item.announcement != null) return;
|
||||
boolean hasMultipleAccounts = AccountSessionManager.getInstance().getLoggedInAccounts().size() > 1;
|
||||
Menu menu=optionsMenu.getMenu();
|
||||
|
||||
|
||||
@@ -498,7 +498,7 @@ public class UiUtils{
|
||||
pinned ? R.string.sk_confirm_pin_post_title : R.string.sk_confirm_unpin_post_title,
|
||||
pinned ? R.string.sk_confirm_pin_post : R.string.sk_confirm_unpin_post,
|
||||
pinned ? R.string.sk_pin_post : R.string.sk_unpin_post,
|
||||
pinned ? R.drawable.ic_fluent_pin_off_28_regular : R.drawable.ic_fluent_pin_28_regular,
|
||||
pinned ? R.drawable.ic_fluent_pin_28_regular : R.drawable.ic_fluent_pin_off_28_regular,
|
||||
()->{
|
||||
new SetStatusPinned(status.id, pinned)
|
||||
.setCallback(new Callback<>() {
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_fluent_megaphone_24_regular" android:left="2dp" android:right="2dp" android:top="2dp" android:bottom="2dp"/>
|
||||
<item android:width="14dp" android:height="14dp" android:gravity="top|right">
|
||||
<shape android:shape="oval">
|
||||
<stroke android:color="?android:colorPrimary" android:width="2dp"/>
|
||||
<solid android:color="?android:colorAccent"/>
|
||||
</shape>
|
||||
</item>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20">
|
||||
<path android:pathData="M7.032 13.907l-3.471-3.905C3.285 9.692 2.81 9.664 2.5 9.939 2.193 10.215 2.165 10.69 2.44 11l4 4.5c0.287 0.322 0.786 0.336 1.091 0.031l10.5-10.5c0.293-0.293 0.293-0.767 0-1.06-0.293-0.293-0.767-0.293-1.06 0l-9.938 9.937z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20">
|
||||
<path android:pathData="M13 10c0 1.657-1.343 3-3 3s-3-1.343-3-3 1.343-3 3-3 3 1.343 3 3z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24">
|
||||
<path android:pathData="M21.907 5.622C21.969 5.83 22 6.046 22 6.263V17.74c0 1.242-1.007 2.25-2.25 2.25-0.217 0-0.433-0.032-0.641-0.094l-5.514-1.64C12.938 19.602 11.558 20.5 10 20.5c-2.142 0-3.891-1.683-3.995-3.8L6 16.5 5.999 16l-2.39-0.711C2.655 15.004 2 14.127 2 13.131V10.87c0-0.995 0.655-1.873 1.61-2.156l15.5-4.606c1.19-0.355 2.443 0.324 2.797 1.515zM7.499 16.445L7.5 16.499C7.5 17.88 8.62 19 10 19c0.885 0 1.678-0.464 2.124-1.179l-4.625-1.375zm12.037-10.9l-15.5 4.605C3.718 10.245 3.5 10.537 3.5 10.87v2.261c0 0.332 0.218 0.625 0.536 0.72l15.5 4.607c0.07 0.02 0.142 0.03 0.214 0.03 0.414 0 0.75-0.335 0.75-0.75V6.264c0-0.072-0.01-0.144-0.031-0.213-0.118-0.397-0.536-0.624-0.933-0.506z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,3 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="20dp" android:height="20dp" android:viewportWidth="20" android:viewportHeight="20">
|
||||
<path android:pathData="M10 6.5c-0.966 0-1.75-0.784-1.75-1.75S9.034 3 10 3s1.75 0.784 1.75 1.75S10.966 6.5 10 6.5zM10 17c-0.966 0-1.75-0.784-1.75-1.75S9.034 13.5 10 13.5s1.75 0.784 1.75 1.75S10.966 17 10 17zm-1.75-7c0 0.966 0.784 1.75 1.75 1.75s1.75-0.784 1.75-1.75S10.966 8.25 10 8.25 8.25 9.034 8.25 10z" android:fillColor="@color/fluent_default_icon_tint"/>
|
||||
</vector>
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
@@ -54,6 +55,16 @@
|
||||
android:contentDescription="@string/sk_schedule_or_draft"
|
||||
android:tooltipText="@string/sk_schedule_or_draft" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/char_counter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:layout_marginHorizontal="8dp"
|
||||
android:visibility="gone"
|
||||
tools:text="500"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/publish_btn"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
android:layout_below="@id/retry_or_cancel_upload"
|
||||
android:layout_marginTop="16dp"
|
||||
android:textColor="?colorGray200"
|
||||
android:textSize="14dp"
|
||||
android:textSize="14sp"
|
||||
android:gravity="center_horizontal"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
android:background="?android:selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/more_options"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_post_more"
|
||||
android:src="@drawable/ic_fluent_more_vertical_20_filled"
|
||||
android:tint="?android:textColorSecondary" />
|
||||
|
||||
<ImageView
|
||||
@@ -47,10 +47,21 @@
|
||||
android:src="@drawable/ic_visibility"
|
||||
android:tint="?android:textColorSecondary" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/unread_indicator"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginTop="-6dp"
|
||||
android:layout_toStartOf="@id/visibility"
|
||||
android:visibility="gone"
|
||||
android:tint="?android:colorAccent"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_fluent_circle_small_20_filled" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="46dp"
|
||||
android:layout_height="46dp"
|
||||
android:layout_width="46sp"
|
||||
android:layout_height="46sp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginEnd="12dp" />
|
||||
@@ -58,15 +69,17 @@
|
||||
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
|
||||
android:id="@+id/name_wrap"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="24dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_toStartOf="@id/visibility"
|
||||
android:layout_toEndOf="@id/avatar">
|
||||
android:layout_marginTop="2sp"
|
||||
android:layout_toStartOf="@id/unread_indicator"
|
||||
android:layout_toEndOf="@id/avatar"
|
||||
android:minHeight="24sp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewStart"
|
||||
@@ -76,7 +89,7 @@
|
||||
<TextView
|
||||
android:id="@+id/extra_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="24dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="sans-serif"
|
||||
@@ -89,18 +102,19 @@
|
||||
|
||||
<org.joinmastodon.android.ui.views.HeaderSubtitleLinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/name_wrap"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_toStartOf="@id/visibility"
|
||||
android:layout_toStartOf="@id/unread_indicator"
|
||||
android:layout_toEndOf="@id/avatar"
|
||||
android:layoutDirection="locale"
|
||||
android:minHeight="20sp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/username"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
@@ -109,9 +123,9 @@
|
||||
<TextView
|
||||
android:id="@+id/separator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="4sp"
|
||||
android:layout_marginRight="4sp"
|
||||
android:importantForAccessibility="no"
|
||||
android:text="·"
|
||||
android:textAppearance="@style/m3_title_small" />
|
||||
@@ -119,7 +133,7 @@
|
||||
<TextView
|
||||
android:id="@+id/timestamp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="20dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
tools:text="3h" />
|
||||
|
||||
@@ -56,10 +56,10 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/reply_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="-12dp"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
@@ -68,8 +68,7 @@
|
||||
android:drawableTint="?android:textColorSecondary"
|
||||
android:drawablePadding="6dp"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:background="?android:selectableItemBackground"/>
|
||||
android:ellipsize="end"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
@@ -80,8 +79,8 @@
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/self_avatar"
|
||||
android:layout_width="46dp"
|
||||
android:layout_height="46dp"
|
||||
android:layout_width="46sp"
|
||||
android:layout_height="46sp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginEnd="12dp" />
|
||||
@@ -89,8 +88,9 @@
|
||||
<TextView
|
||||
android:id="@+id/self_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="24dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toEndOf="@id/self_avatar"
|
||||
android:minHeight="24sp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_medium"
|
||||
@@ -99,9 +99,10 @@
|
||||
<TextView
|
||||
android:id="@+id/self_username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/self_name"
|
||||
android:layout_toEndOf="@id/self_avatar"
|
||||
android:minHeight="20sp"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/m3_title_small"
|
||||
@@ -422,6 +423,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/m3_body_large"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:visibility="gone"
|
||||
tools:text="500"/>
|
||||
|
||||
<Button
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
android:hint="@string/search_hint"
|
||||
android:textColorHint="?colorSearchHint"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="16dp"
|
||||
android:textSize="16sp"
|
||||
android:singleLine="true"
|
||||
android:inputType="textFilter"
|
||||
android:imeOptions="actionSearch"
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
android:textColor="?colorGray50t"
|
||||
android:textAllCaps="true"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:textSize="14dp"
|
||||
android:textSize="14sp"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/bg_profile_follows_you"
|
||||
android:visibility="gone"
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginVertical="12dp"
|
||||
android:text="@string/sk_welcome_title"
|
||||
/>
|
||||
android:text="@string/sk_welcome_title" />
|
||||
|
||||
<TextView
|
||||
style="@style/m3_body_large"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="24dp"
|
||||
android:textSize="16dp"
|
||||
android:textSize="16sp"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"/>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:textSize="12dp"
|
||||
android:textSize="12sp"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:textAllCaps="true"
|
||||
android:paddingTop="24dp"
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
android:textAllCaps="true"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:textSize="14dp"
|
||||
android:textSize="14sp"
|
||||
android:gravity="center_vertical"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
|
||||
<TextView
|
||||
android:id="@+id/number"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_width="24sp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textColor="?android:colorAccent"
|
||||
android:fontFamily="sans-serif-condensed"
|
||||
android:textStyle="bold"
|
||||
android:textSize="22dp"
|
||||
android:textSize="22sp"
|
||||
android:gravity="center"
|
||||
android:includeFontPadding="false"
|
||||
tools:text="1"/>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
android:layout_marginEnd="8dp"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="20dp"
|
||||
android:textSize="20sp"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
@@ -26,7 +26,7 @@
|
||||
android:layout_height="32dp"
|
||||
android:background="@drawable/bg_inline_button"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="20dp"
|
||||
android:textSize="20sp"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp"
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:id="@+id/announcements"
|
||||
android:icon="@drawable/ic_fluent_megaphone_24_regular"
|
||||
android:showAsAction="always"
|
||||
android:title="@string/sk_announcements" />
|
||||
<item
|
||||
android:id="@+id/settings"
|
||||
android:icon="@drawable/ic_fluent_settings_24_regular"
|
||||
|
||||
@@ -137,9 +137,12 @@
|
||||
<string name="sk_clear_recent_emoji">Clear recently used emoji</string>
|
||||
<string name="sk_disable_relocate_publish_button_to_enable_customization">Disable "Relocate publish button" to allow customization</string>
|
||||
<string name="sk_keep_only_latest_notification">Keep only latest notification</string>
|
||||
<string name="sk_announcements">Announcements</string>
|
||||
<string name="sk_mark_as_read">Mark as read</string>
|
||||
|
||||
<!-- accessibility labels-->
|
||||
<string name="sk_poll_option_add">Add new poll option</string>
|
||||
<string name="sk_fab_compose">Compose</string>
|
||||
<string name="sk_sending_error">Error publishing</string>
|
||||
|
||||
</resources>
|
||||
@@ -381,7 +381,7 @@
|
||||
|
||||
<style name="Widget.Mastodon.M3.Button" parent="android:Widget.Material.Button">
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:textSize">14dp</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:minHeight">40dp</item>
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:stateListAnimator">@null</item>
|
||||
@@ -403,45 +403,45 @@
|
||||
|
||||
<style name="alert_title">
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
<item name="android:textSize">24dp</item>
|
||||
<item name="android:textSize">24sp</item>
|
||||
<item name="android:minHeight">38dp</item>
|
||||
<item name="android:gravity">center_vertical</item>
|
||||
</style>
|
||||
|
||||
<style name="m3_body_large">
|
||||
<item name="android:textSize">16dp</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
<item name="android:lineSpacingExtra">5dp</item>
|
||||
</style>
|
||||
|
||||
<style name="m3_body_medium">
|
||||
<item name="android:textSize">14dp</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
<item name="android:lineSpacingExtra">4dp</item>
|
||||
</style>
|
||||
|
||||
<style name="m3_body_small">
|
||||
<item name="android:textSize">12dp</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:textColor">?android:textColorSecondary</item>
|
||||
<item name="android:lineSpacingExtra">2dp</item>
|
||||
</style>
|
||||
|
||||
<style name="m3_title_medium">
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:textSize">16dp</item>
|
||||
<item name="android:textSize">16sp</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
<item name="android:lineSpacingExtra">5dp</item>
|
||||
</style>
|
||||
|
||||
<style name="m3_title_small">
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:textSize">14dp</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textColor">?android:textColorSecondary</item>
|
||||
</style>
|
||||
|
||||
<style name="m3_label_medium">
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:textSize">12dp</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
<item name="android:lineSpacingMultiplier">1.14</item>
|
||||
</style>
|
||||
@@ -449,12 +449,12 @@
|
||||
<style name="m3_label_large">
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:textColor">?android:textColorSecondary</item>
|
||||
<item name="android:textSize">14dp</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
</style>
|
||||
|
||||
<style name="m3_title_large">
|
||||
<item name="android:fontFamily">sans-serif-medium</item>
|
||||
<item name="android:textSize">22dp</item>
|
||||
<item name="android:textSize">22sp</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
@@ -465,12 +465,12 @@
|
||||
</style>
|
||||
|
||||
<style name="m3_headline_small">
|
||||
<item name="android:textSize">24dp</item>
|
||||
<item name="android:textSize">24sp</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="m3_headline_medium">
|
||||
<item name="android:textSize">28dp</item>
|
||||
<item name="android:textSize">28sp</item>
|
||||
<item name="android:textColor">?android:textColorPrimary</item>
|
||||
<item name="android:lineSpacingExtra">3dp</item>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user