Fixes
This commit is contained in:
parent
c60bc253e5
commit
10655e4c98
|
@ -10,7 +10,7 @@ android {
|
||||||
applicationId "org.joinmastodon.android"
|
applicationId "org.joinmastodon.android"
|
||||||
minSdk 23
|
minSdk 23
|
||||||
targetSdk 31
|
targetSdk 31
|
||||||
versionCode 17
|
versionCode 18
|
||||||
versionName "0.1"
|
versionName "0.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.joinmastodon.android.api;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class ApiUtils{
|
||||||
|
private ApiUtils(){
|
||||||
|
//no instance
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <E extends Enum<E>> List<String> enumSetToStrings(EnumSet<E> e, Class<E> cls){
|
||||||
|
return e.stream().map(ev->{
|
||||||
|
try{
|
||||||
|
SerializedName annotation=cls.getField(ev.name()).getAnnotation(SerializedName.class);
|
||||||
|
return annotation!=null ? annotation.value() : ev.name().toLowerCase();
|
||||||
|
}catch(NoSuchFieldException x){
|
||||||
|
throw new RuntimeException(x);
|
||||||
|
}
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
|
@ -129,7 +129,7 @@ public class CacheController{
|
||||||
Log.w(TAG, "getNotifications: corrupted notification object in database", x);
|
Log.w(TAG, "getNotifications: corrupted notification object in database", x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new GetNotifications(maxID, count, onlyMentions ? EnumSet.complementOf(EnumSet.of(Notification.Type.MENTION)): null)
|
new GetNotifications(maxID, count, onlyMentions ? EnumSet.of(Notification.Type.MENTION): EnumSet.allOf(Notification.Type.class))
|
||||||
.setCallback(new Callback<>(){
|
.setCallback(new Callback<>(){
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(List<Notification> result){
|
public void onSuccess(List<Notification> result){
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.app.Activity;
|
||||||
import android.app.ProgressDialog;
|
import android.app.ProgressDialog;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
@ -16,6 +17,7 @@ import org.joinmastodon.android.model.Token;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -27,6 +29,7 @@ import okhttp3.Call;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
|
|
||||||
public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
|
public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
|
||||||
|
private static final String TAG="MastodonAPIRequest";
|
||||||
|
|
||||||
private String domain;
|
private String domain;
|
||||||
private AccountSession account;
|
private AccountSession account;
|
||||||
|
@ -41,6 +44,7 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
|
||||||
boolean canceled;
|
boolean canceled;
|
||||||
Map<String, String> headers;
|
Map<String, String> headers;
|
||||||
private ProgressDialog progressDialog;
|
private ProgressDialog progressDialog;
|
||||||
|
protected boolean removeUnsupportedItems;
|
||||||
|
|
||||||
public MastodonAPIRequest(HttpMethod method, String path, Class<T> respClass){
|
public MastodonAPIRequest(HttpMethod method, String path, Class<T> respClass){
|
||||||
this.path=path;
|
this.path=path;
|
||||||
|
@ -150,9 +154,29 @@ public abstract class MastodonAPIRequest<T> extends APIRequest<T>{
|
||||||
if(respObj instanceof BaseModel){
|
if(respObj instanceof BaseModel){
|
||||||
((BaseModel) respObj).postprocess();
|
((BaseModel) respObj).postprocess();
|
||||||
}else if(respObj instanceof List){
|
}else if(respObj instanceof List){
|
||||||
for(Object item : ((List) respObj)){
|
if(removeUnsupportedItems){
|
||||||
if(item instanceof BaseModel)
|
Iterator<?> itr=((List<?>) respObj).iterator();
|
||||||
((BaseModel) item).postprocess();
|
while(itr.hasNext()){
|
||||||
|
Object item=itr.next();
|
||||||
|
if(item instanceof BaseModel){
|
||||||
|
try{
|
||||||
|
((BaseModel) item).postprocess();
|
||||||
|
}catch(ObjectValidationException x){
|
||||||
|
Log.w(TAG, "Removing invalid object from list", x);
|
||||||
|
itr.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(Object item:((List<?>) respObj)){
|
||||||
|
if(item instanceof BaseModel){
|
||||||
|
((BaseModel) item).postprocess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
for(Object item:((List<?>) respObj)){
|
||||||
|
if(item instanceof BaseModel)
|
||||||
|
((BaseModel) item).postprocess();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.joinmastodon.android.api.requests.notifications;
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
|
import org.joinmastodon.android.api.ApiUtils;
|
||||||
import org.joinmastodon.android.api.MastodonAPIRequest;
|
import org.joinmastodon.android.api.MastodonAPIRequest;
|
||||||
import org.joinmastodon.android.model.Notification;
|
import org.joinmastodon.android.model.Notification;
|
||||||
|
|
||||||
|
@ -10,18 +11,20 @@ import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class GetNotifications extends MastodonAPIRequest<List<Notification>>{
|
public class GetNotifications extends MastodonAPIRequest<List<Notification>>{
|
||||||
public GetNotifications(String maxID, int limit, EnumSet<Notification.Type> excludeTypes){
|
public GetNotifications(String maxID, int limit, EnumSet<Notification.Type> includeTypes){
|
||||||
super(HttpMethod.GET, "/notifications", new TypeToken<>(){});
|
super(HttpMethod.GET, "/notifications", new TypeToken<>(){});
|
||||||
if(maxID!=null)
|
if(maxID!=null)
|
||||||
addQueryParameter("max_id", maxID);
|
addQueryParameter("max_id", maxID);
|
||||||
if(limit>0)
|
if(limit>0)
|
||||||
addQueryParameter("limit", ""+limit);
|
addQueryParameter("limit", ""+limit);
|
||||||
if(excludeTypes!=null){
|
if(includeTypes!=null){
|
||||||
for(Notification.Type nt:excludeTypes){
|
for(String type:ApiUtils.enumSetToStrings(includeTypes, Notification.Type.class)){
|
||||||
try{
|
addQueryParameter("types[]", type);
|
||||||
addQueryParameter("exclude_types[]", nt.getDeclaringClass().getField(nt.name()).getAnnotation(SerializedName.class).value());
|
}
|
||||||
}catch(NoSuchFieldException ignore){}
|
for(String type:ApiUtils.enumSetToStrings(EnumSet.complementOf(includeTypes), Notification.Type.class)){
|
||||||
|
addQueryParameter("exclude_types[]", type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
removeUnsupportedItems=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,8 +111,8 @@ public class ComposeFragment extends ToolbarFragment implements OnBackPressedLis
|
||||||
private static final Pattern MENTION_PATTERN=Pattern.compile("(^|[^\\/\\w])@(([a-z0-9_]+)@[a-z0-9\\.\\-]+[a-z0-9]+)", Pattern.CASE_INSENSITIVE);
|
private static final Pattern MENTION_PATTERN=Pattern.compile("(^|[^\\/\\w])@(([a-z0-9_]+)@[a-z0-9\\.\\-]+[a-z0-9]+)", Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
// from https://github.com/mastodon/mastodon-ios/blob/main/Mastodon/Helper/MastodonRegex.swift
|
// from https://github.com/mastodon/mastodon-ios/blob/main/Mastodon/Helper/MastodonRegex.swift
|
||||||
private static final Pattern AUTO_COMPLETE_PATTERN=Pattern.compile("(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+))|(^\\B:|\\s:)([a-zA-Z0-9_]+)");
|
private static final Pattern AUTO_COMPLETE_PATTERN=Pattern.compile("(?<!\\w)(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+))|(^\\B:|\\s:)([a-zA-Z0-9_]+)");
|
||||||
private static final Pattern HIGHLIGHT_PATTERN=Pattern.compile("(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+))");
|
private static final Pattern HIGHLIGHT_PATTERN=Pattern.compile("(?<!\\w)(?:@([a-zA-Z0-9_]+)(@[a-zA-Z0-9_.-]+)?|#([^\\s.]+))");
|
||||||
|
|
||||||
private static final String VALID_URL_PATTERN_STRING =
|
private static final String VALID_URL_PATTERN_STRING =
|
||||||
"(" + // $1 total match
|
"(" + // $1 total match
|
||||||
|
|
|
@ -333,6 +333,11 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
||||||
page.loadData();
|
page.loadData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrollStateChanged(int state){
|
||||||
|
refreshLayout.setEnabled(state!=ViewPager2.SCROLL_STATE_DRAGGING);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,7 @@ public class InstanceRulesFragment extends AppKitFragment{
|
||||||
View headerView=inflater.inflate(R.layout.item_list_header, list, false);
|
View headerView=inflater.inflate(R.layout.item_list_header, list, false);
|
||||||
TextView title=headerView.findViewById(R.id.title);
|
TextView title=headerView.findViewById(R.id.title);
|
||||||
TextView subtitle=headerView.findViewById(R.id.subtitle);
|
TextView subtitle=headerView.findViewById(R.id.subtitle);
|
||||||
|
headerView.findViewById(R.id.step_counter).setVisibility(View.GONE);
|
||||||
title.setText(R.string.instance_rules_title);
|
title.setText(R.string.instance_rules_title);
|
||||||
subtitle.setText(getString(R.string.instance_rules_subtitle, instance.uri));
|
subtitle.setText(getString(R.string.instance_rules_subtitle, instance.uri));
|
||||||
|
|
||||||
|
|
|
@ -78,8 +78,10 @@ public abstract class BaseReportChoiceFragment extends ToolbarFragment{
|
||||||
View headerView=inflater.inflate(R.layout.item_list_header, list, false);
|
View headerView=inflater.inflate(R.layout.item_list_header, list, false);
|
||||||
TextView title=headerView.findViewById(R.id.title);
|
TextView title=headerView.findViewById(R.id.title);
|
||||||
TextView subtitle=headerView.findViewById(R.id.subtitle);
|
TextView subtitle=headerView.findViewById(R.id.subtitle);
|
||||||
|
TextView stepCounter=headerView.findViewById(R.id.step_counter);
|
||||||
title.setText(header.title);
|
title.setText(header.title);
|
||||||
subtitle.setText(header.subtitle);
|
subtitle.setText(header.subtitle);
|
||||||
|
stepCounter.setText(getString(R.string.step_x_of_n, getStepNumber(), 3));
|
||||||
|
|
||||||
adapter=new MergeRecyclerAdapter();
|
adapter=new MergeRecyclerAdapter();
|
||||||
adapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
|
adapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
|
||||||
|
@ -98,6 +100,7 @@ public abstract class BaseReportChoiceFragment extends ToolbarFragment{
|
||||||
protected abstract Item getHeaderItem();
|
protected abstract Item getHeaderItem();
|
||||||
protected abstract void populateItems();
|
protected abstract void populateItems();
|
||||||
protected abstract void onButtonClick();
|
protected abstract void onButtonClick();
|
||||||
|
protected abstract int getStepNumber();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onApplyWindowInsets(WindowInsets insets){
|
public void onApplyWindowInsets(WindowInsets insets){
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.joinmastodon.android.ui.utils.UiUtils;
|
||||||
import org.parceler.Parcels;
|
import org.parceler.Parcels;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -102,6 +103,7 @@ public class ReportAddPostsChoiceFragment extends StatusListFragment{
|
||||||
btn=view.findViewById(R.id.btn_next);
|
btn=view.findViewById(R.id.btn_next);
|
||||||
btn.setEnabled(!selectedIDs.isEmpty());
|
btn.setEnabled(!selectedIDs.isEmpty());
|
||||||
btn.setOnClickListener(this::onButtonClick);
|
btn.setOnClickListener(this::onButtonClick);
|
||||||
|
view.findViewById(R.id.btn_back).setOnClickListener(this::onButtonClick);
|
||||||
buttonBar=view.findViewById(R.id.button_bar);
|
buttonBar=view.findViewById(R.id.button_bar);
|
||||||
|
|
||||||
list.addItemDecoration(new RecyclerView.ItemDecoration(){
|
list.addItemDecoration(new RecyclerView.ItemDecoration(){
|
||||||
|
@ -216,8 +218,10 @@ public class ReportAddPostsChoiceFragment extends StatusListFragment{
|
||||||
View headerView=getActivity().getLayoutInflater().inflate(R.layout.item_list_header, list, false);
|
View headerView=getActivity().getLayoutInflater().inflate(R.layout.item_list_header, list, false);
|
||||||
TextView title=headerView.findViewById(R.id.title);
|
TextView title=headerView.findViewById(R.id.title);
|
||||||
TextView subtitle=headerView.findViewById(R.id.subtitle);
|
TextView subtitle=headerView.findViewById(R.id.subtitle);
|
||||||
|
TextView stepCounter=headerView.findViewById(R.id.step_counter);
|
||||||
title.setText(R.string.report_choose_posts);
|
title.setText(R.string.report_choose_posts);
|
||||||
subtitle.setText(R.string.report_choose_posts_subtitle);
|
subtitle.setText(R.string.report_choose_posts_subtitle);
|
||||||
|
stepCounter.setText(getString(R.string.step_x_of_n, 2, 3));
|
||||||
|
|
||||||
MergeRecyclerAdapter adapter=new MergeRecyclerAdapter();
|
MergeRecyclerAdapter adapter=new MergeRecyclerAdapter();
|
||||||
adapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
|
adapter.addAdapter(new SingleViewRecyclerAdapter(headerView));
|
||||||
|
@ -248,7 +252,14 @@ public class ReportAddPostsChoiceFragment extends StatusListFragment{
|
||||||
Bundle args=new Bundle();
|
Bundle args=new Bundle();
|
||||||
args.putString("account", accountID);
|
args.putString("account", accountID);
|
||||||
args.putParcelable("reportAccount", Parcels.wrap(reportAccount));
|
args.putParcelable("reportAccount", Parcels.wrap(reportAccount));
|
||||||
args.putStringArrayList("statusIDs", selectedIDs);
|
if(v.getId()==R.id.btn_next){
|
||||||
|
args.putStringArrayList("statusIDs", selectedIDs);
|
||||||
|
}else{
|
||||||
|
ArrayList<String> ids=new ArrayList<>();
|
||||||
|
if(reportStatus!=null)
|
||||||
|
ids.add(reportStatus.id);
|
||||||
|
args.putStringArrayList("statusIDs", ids);
|
||||||
|
}
|
||||||
args.putStringArrayList("ruleIDs", getArguments().getStringArrayList("ruleIDs"));
|
args.putStringArrayList("ruleIDs", getArguments().getStringArrayList("ruleIDs"));
|
||||||
args.putString("reason", getArguments().getString("reason"));
|
args.putString("reason", getArguments().getString("reason"));
|
||||||
Nav.go(getActivity(), ReportCommentFragment.class, args);
|
Nav.go(getActivity(), ReportCommentFragment.class, args);
|
||||||
|
|
|
@ -66,11 +66,14 @@ public class ReportCommentFragment extends ToolbarFragment{
|
||||||
|
|
||||||
TextView title=view.findViewById(R.id.title);
|
TextView title=view.findViewById(R.id.title);
|
||||||
TextView subtitle=view.findViewById(R.id.subtitle);
|
TextView subtitle=view.findViewById(R.id.subtitle);
|
||||||
|
TextView stepCounter=view.findViewById(R.id.step_counter);
|
||||||
title.setText(R.string.report_comment_title);
|
title.setText(R.string.report_comment_title);
|
||||||
subtitle.setText(R.string.report_comment_subtitle);
|
subtitle.setVisibility(View.GONE);
|
||||||
|
stepCounter.setText(getString(R.string.step_x_of_n, 3, 3));
|
||||||
|
|
||||||
btn=view.findViewById(R.id.btn_next);
|
btn=view.findViewById(R.id.btn_next);
|
||||||
btn.setOnClickListener(this::onButtonClick);
|
btn.setOnClickListener(this::onButtonClick);
|
||||||
|
view.findViewById(R.id.btn_back).setOnClickListener(this::onButtonClick);
|
||||||
buttonBar=view.findViewById(R.id.button_bar);
|
buttonBar=view.findViewById(R.id.button_bar);
|
||||||
commentEdit=view.findViewById(R.id.text);
|
commentEdit=view.findViewById(R.id.text);
|
||||||
|
|
||||||
|
@ -98,7 +101,7 @@ public class ReportCommentFragment extends ToolbarFragment{
|
||||||
ReportReason reason=ReportReason.valueOf(getArguments().getString("reason"));
|
ReportReason reason=ReportReason.valueOf(getArguments().getString("reason"));
|
||||||
ArrayList<String> statusIDs=getArguments().getStringArrayList("statusIDs");
|
ArrayList<String> statusIDs=getArguments().getStringArrayList("statusIDs");
|
||||||
ArrayList<String> ruleIDs=getArguments().getStringArrayList("ruleIDs");
|
ArrayList<String> ruleIDs=getArguments().getStringArrayList("ruleIDs");
|
||||||
new SendReport(reportAccount.id, reason, statusIDs, ruleIDs, commentEdit.getText().toString(), false)
|
new SendReport(reportAccount.id, reason, statusIDs, ruleIDs, v.getId()==R.id.btn_back ? null : commentEdit.getText().toString(), false)
|
||||||
.setCallback(new Callback<>(){
|
.setCallback(new Callback<>(){
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(Object result){
|
public void onSuccess(Object result){
|
||||||
|
|
|
@ -14,7 +14,7 @@ import me.grishka.appkit.Nav;
|
||||||
public class ReportReasonChoiceFragment extends BaseReportChoiceFragment{
|
public class ReportReasonChoiceFragment extends BaseReportChoiceFragment{
|
||||||
@Override
|
@Override
|
||||||
protected Item getHeaderItem(){
|
protected Item getHeaderItem(){
|
||||||
return new Item(getString(R.string.report_choose_reason), getString(R.string.report_choose_reason_subtitle), null);
|
return new Item(reportStatus!=null ? getString(R.string.report_choose_reason) : getString(R.string.report_choose_reason_account, reportAccount.acct), getString(R.string.report_choose_reason_subtitle), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,6 +43,11 @@ public class ReportReasonChoiceFragment extends BaseReportChoiceFragment{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getStepNumber(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onFinishReportFragments(FinishReportFragmentsEvent ev){
|
public void onFinishReportFragments(FinishReportFragmentsEvent ev){
|
||||||
if(ev.reportAccountID.equals(reportAccount.id))
|
if(ev.reportAccountID.equals(reportAccount.id))
|
||||||
|
|
|
@ -40,6 +40,11 @@ public class ReportRuleChoiceFragment extends BaseReportChoiceFragment{
|
||||||
Nav.go(getActivity(), ReportAddPostsChoiceFragment.class, args);
|
Nav.go(getActivity(), ReportAddPostsChoiceFragment.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getStepNumber(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onFinishReportFragments(FinishReportFragmentsEvent ev){
|
public void onFinishReportFragments(FinishReportFragmentsEvent ev){
|
||||||
if(ev.reportAccountID.equals(reportAccount.id))
|
if(ev.reportAccountID.equals(reportAccount.id))
|
||||||
|
|
|
@ -36,6 +36,9 @@ import org.joinmastodon.android.ui.text.CustomEmojiSpan;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -58,6 +61,7 @@ import okhttp3.MediaType;
|
||||||
|
|
||||||
public class UiUtils{
|
public class UiUtils{
|
||||||
private static Handler mainHandler=new Handler(Looper.getMainLooper());
|
private static Handler mainHandler=new Handler(Looper.getMainLooper());
|
||||||
|
private static final DateTimeFormatter DATE_FORMATTER_SHORT_WITH_YEAR=DateTimeFormatter.ofPattern("d MMM uuuu"), DATE_FORMATTER_SHORT=DateTimeFormatter.ofPattern("d MMM");
|
||||||
|
|
||||||
private UiUtils(){}
|
private UiUtils(){}
|
||||||
|
|
||||||
|
@ -80,7 +84,16 @@ public class UiUtils{
|
||||||
}else if(diff<3600_000L*24L){
|
}else if(diff<3600_000L*24L){
|
||||||
return context.getString(R.string.time_hours, diff/3600_000L);
|
return context.getString(R.string.time_hours, diff/3600_000L);
|
||||||
}else{
|
}else{
|
||||||
return context.getString(R.string.time_days, diff/(3600_000L*24L));
|
int days=(int)(diff/(3600_000L*24L));
|
||||||
|
if(days>30){
|
||||||
|
ZonedDateTime dt=instant.atZone(ZoneId.systemDefault());
|
||||||
|
if(dt.getYear()==ZonedDateTime.now().getYear()){
|
||||||
|
return DATE_FORMATTER_SHORT.format(dt);
|
||||||
|
}else{
|
||||||
|
return DATE_FORMATTER_SHORT_WITH_YEAR.format(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return context.getString(R.string.time_days, days);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?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:id="@+id/button_bar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:windowBackground"
|
||||||
|
android:outlineProvider="bounds"
|
||||||
|
android:elevation="3dp"
|
||||||
|
tools:showIn="@layout/fragment_report_posts">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_back"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:minWidth="145dp"
|
||||||
|
style="?secondaryLargeButtonStyle"
|
||||||
|
android:text="@string/skip"/>
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_weight="1"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btn_next"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:minWidth="145dp"
|
||||||
|
style="?primaryLargeButtonStyle"
|
||||||
|
android:text="@string/next" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -30,6 +30,6 @@
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<include layout="@layout/button_bar_one"/>
|
<include layout="@layout/button_bar_two"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -32,6 +32,6 @@
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
<include layout="@layout/button_bar_one"/>
|
<include layout="@layout/button_bar_two"/>
|
||||||
|
|
||||||
</me.grishka.appkit.views.FragmentRootLinearLayout>
|
</me.grishka.appkit.views.FragmentRootLinearLayout>
|
|
@ -9,6 +9,15 @@
|
||||||
android:paddingTop="32dp"
|
android:paddingTop="32dp"
|
||||||
android:paddingBottom="8dp">
|
android:paddingBottom="8dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/step_counter"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="12dp"
|
||||||
|
android:textAppearance="@style/m3_title_medium"
|
||||||
|
android:textColor="?android:textColorSecondary"
|
||||||
|
tools:text="@string/step_x_of_n"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
@ -147,8 +147,9 @@
|
||||||
<item quantity="other">Discussed %d times</item>
|
<item quantity="other">Discussed %d times</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="report_title">Report %s</string>
|
<string name="report_title">Report %s</string>
|
||||||
<string name="report_choose_reason">Tell us what\'s going on with this post.</string>
|
<string name="report_choose_reason">What\'s wrong with this post?</string>
|
||||||
<string name="report_choose_reason_subtitle">Choose the best match</string>
|
<string name="report_choose_reason_account">What\'s wrong with %s?</string>
|
||||||
|
<string name="report_choose_reason_subtitle">Select the best match</string>
|
||||||
<string name="report_reason_personal">I don\'t like it</string>
|
<string name="report_reason_personal">I don\'t like it</string>
|
||||||
<string name="report_reason_personal_subtitle">It is not something you want to see</string>
|
<string name="report_reason_personal_subtitle">It is not something you want to see</string>
|
||||||
<string name="report_reason_spam">It\'s spam</string>
|
<string name="report_reason_spam">It\'s spam</string>
|
||||||
|
@ -160,9 +161,8 @@
|
||||||
<string name="report_choose_rule">Which rules are being violated?</string>
|
<string name="report_choose_rule">Which rules are being violated?</string>
|
||||||
<string name="report_choose_rule_subtitle">Select all that apply</string>
|
<string name="report_choose_rule_subtitle">Select all that apply</string>
|
||||||
<string name="report_choose_posts">Are there any posts that back up this report?</string>
|
<string name="report_choose_posts">Are there any posts that back up this report?</string>
|
||||||
<string name="report_choose_posts_subtitle">Optional. Select all that apply</string>
|
<string name="report_choose_posts_subtitle">Select all that apply</string>
|
||||||
<string name="report_comment_title">Is there anything else you think we should know?</string>
|
<string name="report_comment_title">Is there anything else we should know?</string>
|
||||||
<string name="report_comment_subtitle">Optional.</string>
|
|
||||||
<string name="report_comment_hint">Additional comments</string>
|
<string name="report_comment_hint">Additional comments</string>
|
||||||
<string name="sending_report">Sending report…</string>
|
<string name="sending_report">Sending report…</string>
|
||||||
<string name="report_sent_title">Thanks for reporting, we\'ll look into this.</string>
|
<string name="report_sent_title">Thanks for reporting, we\'ll look into this.</string>
|
||||||
|
@ -221,4 +221,6 @@
|
||||||
<string name="search_all">All</string>
|
<string name="search_all">All</string>
|
||||||
<string name="search_people">People</string>
|
<string name="search_people">People</string>
|
||||||
<string name="recent_searches">Recent searches</string>
|
<string name="recent_searches">Recent searches</string>
|
||||||
|
<string name="step_x_of_n">Step %1$d of %2$d</string>
|
||||||
|
<string name="skip">Skip</string>
|
||||||
</resources>
|
</resources>
|
|
@ -42,6 +42,7 @@
|
||||||
<item name="android:windowLightStatusBar">true</item>
|
<item name="android:windowLightStatusBar">true</item>
|
||||||
<item name="android:windowLightNavigationBar" tools:ignore="NewApi">true</item>
|
<item name="android:windowLightNavigationBar" tools:ignore="NewApi">true</item>
|
||||||
<item name="android:popupMenuStyle">@style/Widget.Mastodon.PopupMenu</item>
|
<item name="android:popupMenuStyle">@style/Widget.Mastodon.PopupMenu</item>
|
||||||
|
<item name="android:actionOverflowMenuStyle">@style/Widget.Mastodon.PopupMenu</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Theme.Mastodon.Dark" parent="Theme.AppKit">
|
<style name="Theme.Mastodon.Dark" parent="Theme.AppKit">
|
||||||
|
@ -87,6 +88,8 @@
|
||||||
|
|
||||||
<item name="android:windowLightStatusBar">false</item>
|
<item name="android:windowLightStatusBar">false</item>
|
||||||
<item name="android:windowLightNavigationBar" tools:ignore="NewApi">false</item>
|
<item name="android:windowLightNavigationBar" tools:ignore="NewApi">false</item>
|
||||||
|
<item name="android:popupMenuStyle">@style/Widget.Mastodon.PopupMenu</item>
|
||||||
|
<item name="android:actionOverflowMenuStyle">@style/Widget.Mastodon.PopupMenu</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Theme.Mastodon.AutoLightDark" parent="Theme.Mastodon.Light"/>
|
<style name="Theme.Mastodon.AutoLightDark" parent="Theme.Mastodon.Light"/>
|
||||||
|
|
Loading…
Reference in New Issue