some barebones calckey compatibility
re: sk22#429
This commit is contained in:
@@ -16,6 +16,7 @@ import org.joinmastodon.android.MastodonApp;
|
|||||||
import org.joinmastodon.android.api.gson.IsoInstantTypeAdapter;
|
import org.joinmastodon.android.api.gson.IsoInstantTypeAdapter;
|
||||||
import org.joinmastodon.android.api.gson.IsoLocalDateTypeAdapter;
|
import org.joinmastodon.android.api.gson.IsoLocalDateTypeAdapter;
|
||||||
import org.joinmastodon.android.api.session.AccountSession;
|
import org.joinmastodon.android.api.session.AccountSession;
|
||||||
|
import org.joinmastodon.android.model.Status;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -40,12 +41,15 @@ import okhttp3.ResponseBody;
|
|||||||
|
|
||||||
public class MastodonAPIController{
|
public class MastodonAPIController{
|
||||||
private static final String TAG="MastodonAPIController";
|
private static final String TAG="MastodonAPIController";
|
||||||
public static final Gson gson=new GsonBuilder()
|
public static final Gson gsonWithoutDeserializer = new GsonBuilder()
|
||||||
.disableHtmlEscaping()
|
.disableHtmlEscaping()
|
||||||
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
|
||||||
.registerTypeAdapter(Instant.class, new IsoInstantTypeAdapter())
|
.registerTypeAdapter(Instant.class, new IsoInstantTypeAdapter())
|
||||||
.registerTypeAdapter(LocalDate.class, new IsoLocalDateTypeAdapter())
|
.registerTypeAdapter(LocalDate.class, new IsoLocalDateTypeAdapter())
|
||||||
.create();
|
.create();
|
||||||
|
public static final Gson gson = gsonWithoutDeserializer.newBuilder()
|
||||||
|
.registerTypeAdapter(Status.class, new Status.StatusDeserializer())
|
||||||
|
.create();
|
||||||
private static WorkerThread thread=new WorkerThread("MastodonAPIController");
|
private static WorkerThread thread=new WorkerThread("MastodonAPIController");
|
||||||
private static OkHttpClient httpClient=new OkHttpClient.Builder().build();
|
private static OkHttpClient httpClient=new OkHttpClient.Builder().build();
|
||||||
|
|
||||||
|
|||||||
@@ -674,8 +674,9 @@ public class ComposeFragment extends MastodonToolbarFragment implements OnBackPr
|
|||||||
moreBtn.setImageDrawable(visibilityIcon);
|
moreBtn.setImageDrawable(visibilityIcon);
|
||||||
moreBtn.setBackground(null);
|
moreBtn.setBackground(null);
|
||||||
TextView timestamp = view.findViewById(R.id.timestamp);
|
TextView timestamp = view.findViewById(R.id.timestamp);
|
||||||
if (status.editedAt==null) timestamp.setText(UiUtils.formatRelativeTimestamp(getContext(), status.createdAt));
|
if (status.editedAt!=null) timestamp.setText(getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(getContext(), status.editedAt)));
|
||||||
else timestamp.setText(getString(R.string.edited_timestamp, UiUtils.formatRelativeTimestamp(getContext(), status.editedAt)));
|
else if (status.createdAt!=null) timestamp.setText(UiUtils.formatRelativeTimestamp(getContext(), status.createdAt));
|
||||||
|
else timestamp.setText("");
|
||||||
if (status.spoilerText != null && !status.spoilerText.isBlank()) {
|
if (status.spoilerText != null && !status.spoilerText.isBlank()) {
|
||||||
view.findViewById(R.id.spoiler_header).setVisibility(View.VISIBLE);
|
view.findViewById(R.id.spoiler_header).setVisibility(View.VISIBLE);
|
||||||
((TextView) view.findViewById(R.id.spoiler_title_inline)).setText(status.spoilerText);
|
((TextView) view.findViewById(R.id.spoiler_title_inline)).setText(status.spoilerText);
|
||||||
|
|||||||
@@ -550,10 +550,12 @@ public class ProfileFragment extends LoaderFragment implements OnBackPressedList
|
|||||||
|
|
||||||
fields.clear();
|
fields.clear();
|
||||||
|
|
||||||
AccountField joined=new AccountField();
|
if (account.createdAt != null) {
|
||||||
joined.parsedName=joined.name=getString(R.string.profile_joined);
|
AccountField joined=new AccountField();
|
||||||
joined.parsedValue=joined.value=DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(LocalDateTime.ofInstant(account.createdAt, ZoneId.systemDefault()));
|
joined.parsedName=joined.name=getString(R.string.profile_joined);
|
||||||
fields.add(joined);
|
joined.parsedValue=joined.value=DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(LocalDateTime.ofInstant(account.createdAt, ZoneId.systemDefault()));
|
||||||
|
fields.add(joined);
|
||||||
|
}
|
||||||
|
|
||||||
for(AccountField field:account.fields){
|
for(AccountField field:account.fields){
|
||||||
field.parsedValue=ssb=HtmlParser.parse(field.value, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
field.parsedValue=ssb=HtmlParser.parse(field.value, account.emojis, Collections.emptyList(), Collections.emptyList(), accountID);
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class Account extends BaseModel implements Searchable{
|
|||||||
/**
|
/**
|
||||||
* The profile's display name.
|
* The profile's display name.
|
||||||
*/
|
*/
|
||||||
@RequiredField
|
// @RequiredField
|
||||||
public String displayName;
|
public String displayName;
|
||||||
/**
|
/**
|
||||||
* The profile's bio / description.
|
* The profile's bio / description.
|
||||||
@@ -86,7 +86,7 @@ public class Account extends BaseModel implements Searchable{
|
|||||||
/**
|
/**
|
||||||
* When the account was created.
|
* When the account was created.
|
||||||
*/
|
*/
|
||||||
@RequiredField
|
// @RequiredField
|
||||||
public Instant createdAt;
|
public Instant createdAt;
|
||||||
/**
|
/**
|
||||||
* When the most recent status was posted.
|
* When the most recent status was posted.
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ public class Poll extends BaseModel{
|
|||||||
public int votersCount;
|
public int votersCount;
|
||||||
public int votesCount;
|
public int votesCount;
|
||||||
public boolean voted;
|
public boolean voted;
|
||||||
@RequiredField
|
// @RequiredField
|
||||||
public List<Integer> ownVotes;
|
public List<Integer> ownVotes;
|
||||||
@RequiredField
|
@RequiredField
|
||||||
public List<Option> options;
|
public List<Option> options;
|
||||||
@RequiredField
|
// @RequiredField
|
||||||
public List<Emoji> emojis;
|
public List<Emoji> emojis;
|
||||||
|
|
||||||
public transient ArrayList<Option> selectedOptions;
|
public transient ArrayList<Option> selectedOptions;
|
||||||
@@ -30,6 +30,8 @@ public class Poll extends BaseModel{
|
|||||||
@Override
|
@Override
|
||||||
public void postprocess() throws ObjectValidationException{
|
public void postprocess() throws ObjectValidationException{
|
||||||
super.postprocess();
|
super.postprocess();
|
||||||
|
if (emojis == null) emojis = List.of();
|
||||||
|
if (ownVotes == null) ownVotes = List.of();
|
||||||
for(Emoji e:emojis)
|
for(Emoji e:emojis)
|
||||||
e.postprocess();
|
e.postprocess();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,14 @@
|
|||||||
package org.joinmastodon.android.model;
|
package org.joinmastodon.android.model;
|
||||||
|
|
||||||
|
import static org.joinmastodon.android.api.MastodonAPIController.gson;
|
||||||
|
import static org.joinmastodon.android.api.MastodonAPIController.gsonWithoutDeserializer;
|
||||||
|
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonDeserializer;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonParseException;
|
||||||
|
|
||||||
import org.joinmastodon.android.GlobalUserPreferences;
|
import org.joinmastodon.android.GlobalUserPreferences;
|
||||||
import org.joinmastodon.android.api.ObjectValidationException;
|
import org.joinmastodon.android.api.ObjectValidationException;
|
||||||
import org.joinmastodon.android.api.RequiredField;
|
import org.joinmastodon.android.api.RequiredField;
|
||||||
@@ -7,6 +16,7 @@ import org.joinmastodon.android.events.StatusCountersUpdatedEvent;
|
|||||||
import org.joinmastodon.android.ui.text.HtmlParser;
|
import org.joinmastodon.android.ui.text.HtmlParser;
|
||||||
import org.parceler.Parcel;
|
import org.parceler.Parcel;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -16,7 +26,7 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
|||||||
public String id;
|
public String id;
|
||||||
@RequiredField
|
@RequiredField
|
||||||
public String uri;
|
public String uri;
|
||||||
@RequiredField
|
// @RequiredField // sometimes null on calckey
|
||||||
public Instant createdAt;
|
public Instant createdAt;
|
||||||
@RequiredField
|
@RequiredField
|
||||||
public Account account;
|
public Account account;
|
||||||
@@ -58,7 +68,7 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
|||||||
public boolean bookmarked;
|
public boolean bookmarked;
|
||||||
public boolean pinned;
|
public boolean pinned;
|
||||||
|
|
||||||
public Status quote;
|
public Status quote; // can be boolean in calckey
|
||||||
|
|
||||||
public transient boolean filterRevealed;
|
public transient boolean filterRevealed;
|
||||||
public transient boolean spoilerRevealed;
|
public transient boolean spoilerRevealed;
|
||||||
@@ -173,4 +183,28 @@ public class Status extends BaseModel implements DisplayItemsParent, Searchable{
|
|||||||
public String getQuery() {
|
public String getQuery() {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class StatusDeserializer implements JsonDeserializer<Status> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Status deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||||
|
JsonObject obj = json.getAsJsonObject();
|
||||||
|
|
||||||
|
Status quote = null;
|
||||||
|
if (obj.has("quote") && obj.get("quote").isJsonObject())
|
||||||
|
quote = gson.fromJson(obj.get("quote"), Status.class);
|
||||||
|
obj.remove("quote");
|
||||||
|
|
||||||
|
Status reblog = null;
|
||||||
|
if (obj.has("reblog"))
|
||||||
|
reblog = gson.fromJson(obj.get("reblog"), Status.class);
|
||||||
|
obj.remove("reblog");
|
||||||
|
|
||||||
|
Status status = gsonWithoutDeserializer.fromJson(json, Status.class);
|
||||||
|
status.quote = quote;
|
||||||
|
status.reblog = reblog;
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -79,10 +79,10 @@ public class ExtendedFooterStatusDisplayItem extends StatusDisplayItem{
|
|||||||
}else{
|
}else{
|
||||||
editHistory.setVisibility(View.GONE);
|
editHistory.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
String timeStr=TIME_FORMATTER.format(item.status.createdAt.atZone(ZoneId.systemDefault()));
|
String timeStr=item.status.createdAt != null ? TIME_FORMATTER.format(item.status.createdAt.atZone(ZoneId.systemDefault())) : null;
|
||||||
|
|
||||||
if (item.status.application!=null && !TextUtils.isEmpty(item.status.application.name)) {
|
if (item.status.application!=null && !TextUtils.isEmpty(item.status.application.name)) {
|
||||||
time.setText(item.parentFragment.getString(R.string.timestamp_via_app, timeStr, ""));
|
time.setText(timeStr != null ? item.parentFragment.getString(R.string.timestamp_via_app, timeStr, "") : "");
|
||||||
applicationName.setText(item.status.application.name);
|
applicationName.setText(item.status.application.name);
|
||||||
if (item.status.application.website != null && item.status.application.website.toLowerCase().startsWith("https://")) {
|
if (item.status.application.website != null && item.status.application.website.toLowerCase().startsWith("https://")) {
|
||||||
applicationName.setOnClickListener(e -> UiUtils.openURL(context, null, item.status.application.website));
|
applicationName.setOnClickListener(e -> UiUtils.openURL(context, null, item.status.application.website));
|
||||||
|
|||||||
Reference in New Issue
Block a user