added initial "status schedule" edit support, bug fix

This commit is contained in:
nuclearfog 2023-09-23 20:46:28 +02:00
parent a98a614bc4
commit 101218850e
No known key found for this signature in database
GPG Key ID: 03488A185C476379
8 changed files with 285 additions and 6 deletions

View File

@ -18,6 +18,7 @@ import org.nuclearfog.twidda.model.Instance;
import org.nuclearfog.twidda.model.Notification;
import org.nuclearfog.twidda.model.Poll;
import org.nuclearfog.twidda.model.Relation;
import org.nuclearfog.twidda.model.ScheduledStatus;
import org.nuclearfog.twidda.model.Status;
import org.nuclearfog.twidda.model.Translation;
import org.nuclearfog.twidda.model.Trend;
@ -27,6 +28,7 @@ import org.nuclearfog.twidda.model.WebPush;
import org.nuclearfog.twidda.model.lists.Domains;
import org.nuclearfog.twidda.model.lists.Filters;
import org.nuclearfog.twidda.model.lists.Notifications;
import org.nuclearfog.twidda.model.lists.ScheduledStatuses;
import org.nuclearfog.twidda.model.lists.Statuses;
import org.nuclearfog.twidda.model.lists.Trends;
import org.nuclearfog.twidda.model.lists.UserLists;
@ -448,6 +450,29 @@ public interface Connection {
*/
void deleteStatus(long id) throws ConnectionException;
/**
* get a list of current scheduled status
*
* @param minId minimum ID of the status
* @param maxId maximum ID of the status
*/
ScheduledStatuses getScheduledStatuses(long minId, long maxId) throws ConnectionException;
/**
* update schedule time of a status
*
* @param id scheduled status ID
* @param schedule new schedule time
*/
ScheduledStatus updateScheduledStatus(long id, long schedule) throws ConnectionException;
/**
* remove scheduled status
*
* @param id scheduled status ID
*/
void canselScheduledStatus(long id) throws ConnectionException;
/**
* return a list of domain names the current user has blocked
*

View File

@ -27,6 +27,7 @@ import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonStatus;
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonTranslation;
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonTrend;
import org.nuclearfog.twidda.backend.api.mastodon.impl.MastodonUser;
import org.nuclearfog.twidda.backend.api.mastodon.impl.ScheduledMastodonStatus;
import org.nuclearfog.twidda.backend.helper.ConnectionResult;
import org.nuclearfog.twidda.backend.helper.MediaStatus;
import org.nuclearfog.twidda.backend.helper.update.ConnectionUpdate;
@ -47,6 +48,7 @@ import org.nuclearfog.twidda.model.Instance;
import org.nuclearfog.twidda.model.Notification;
import org.nuclearfog.twidda.model.Poll;
import org.nuclearfog.twidda.model.Relation;
import org.nuclearfog.twidda.model.ScheduledStatus;
import org.nuclearfog.twidda.model.Status;
import org.nuclearfog.twidda.model.Translation;
import org.nuclearfog.twidda.model.Trend;
@ -56,6 +58,7 @@ import org.nuclearfog.twidda.model.WebPush;
import org.nuclearfog.twidda.model.lists.Domains;
import org.nuclearfog.twidda.model.lists.Filters;
import org.nuclearfog.twidda.model.lists.Notifications;
import org.nuclearfog.twidda.model.lists.ScheduledStatuses;
import org.nuclearfog.twidda.model.lists.Statuses;
import org.nuclearfog.twidda.model.lists.Trends;
import org.nuclearfog.twidda.model.lists.UserLists;
@ -148,6 +151,7 @@ public class Mastodon implements Connection {
private static final String ENDPOINT_PUSH_UPDATE = "/api/v1/push/subscription";
private static final String ENDPOINT_FILTER = "/api/v2/filters";
private static final String ENDPOINT_REPORT = "/api/v1/reports";
private static final String ENDPOINT_SCHEDULED_STATUS = "/api/v1/scheduled_statuses";
private static final MediaType TYPE_TEXT = MediaType.parse("text/plain");
private static final MediaType TYPE_STREAM = MediaType.parse("application/octet-stream");
@ -715,6 +719,62 @@ public class Mastodon implements Connection {
}
@Override
public ScheduledStatuses getScheduledStatuses(long minId, long maxId) throws ConnectionException {
try {
List<String> params = new ArrayList<>();
params.add("min_id" + minId);
params.add("max_id" + maxId);
params.add("limit" + settings.getListSize());
Response response = get(ENDPOINT_SCHEDULED_STATUS, params);
ResponseBody body = response.body();
if (response.code() == 200 && body != null) {
JSONArray jsonArray = new JSONArray(body.string());
ScheduledStatuses result = new ScheduledStatuses();
for (int i = 0 ; i < jsonArray.length() ; i++) {
result.add(new ScheduledMastodonStatus(jsonArray.getJSONObject(i)));
}
return result;
}
throw new MastodonException(response);
} catch (JSONException | IOException exception) {
throw new MastodonException(exception);
}
}
@Override
public ScheduledStatus updateScheduledStatus(long id, long schedule) throws ConnectionException {
try {
List<String> params = new ArrayList<>();
String dateFormat = ISODateTimeFormat.dateTimeNoMillis().print(schedule);
params.add("scheduled_at=" + StringUtils.encode(dateFormat));
Response response = put(ENDPOINT_SCHEDULED_STATUS + "/" + id, params);
ResponseBody body = response.body();
if (response.code() == 200 && body != null) {
JSONObject json = new JSONObject(body.string());
return new ScheduledMastodonStatus(json);
}
throw new MastodonException(response);
} catch (IOException | JSONException exception) {
throw new MastodonException(exception);
}
}
@Override
public void canselScheduledStatus(long id) throws ConnectionException {
try {
Response response = delete(ENDPOINT_SCHEDULED_STATUS + "/" + id, new ArrayList<>());
if (response.code() != 200) {
throw new MastodonException(response);
}
} catch (IOException exception) {
throw new MastodonException(exception);
}
}
@Override
public Domains getDomainBlocks(long cursor) throws ConnectionException {
try {

View File

@ -71,6 +71,7 @@ public class MastodonStatus implements Status {
String replyUserIdStr = json.optString("in_reply_to_account_id", "0");
String idStr = json.getString("id");
String visibilityStr = json.getString("visibility");
String language = json.optString("language", "");
author = new MastodonUser(json.getJSONObject("account"), currentUserId);
createdAt = StringUtils.getIsoTime(json.optString("created_at"));
@ -133,11 +134,8 @@ public class MastodonStatus implements Status {
if (cardJson != null) {
cards = new Card[]{new MastodonCard(cardJson)};
}
if (json.has("language") && !json.isNull("language")) {
String language = json.getString("language");
if (!language.equals(Locale.getDefault().getLanguage())) {
this.language = language;
}
if (!language.isEmpty() && !language.equals("null") && !language.equals(Locale.getDefault().getLanguage())) {
this.language = language;
}
switch (visibilityStr) {
case "public":

View File

@ -0,0 +1,131 @@
package org.nuclearfog.twidda.backend.api.mastodon.impl;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.nuclearfog.twidda.backend.utils.StringUtils;
import org.nuclearfog.twidda.model.Media;
import org.nuclearfog.twidda.model.Poll;
import org.nuclearfog.twidda.model.ScheduledStatus;
import org.nuclearfog.twidda.model.Status;
/**
* Mastodon implementation of a scheduled status
*
* @author nuclearfog
*/
public class ScheduledMastodonStatus implements ScheduledStatus {
private static final long serialVersionUID = -1340937182294786469L;
private long id;
private String text;
private String language = "";
private int visibility;
private boolean sensitive;
private boolean spoiler;
private Media[] medias = {};
private Poll poll;
/**
*
*/
public ScheduledMastodonStatus(JSONObject json) throws JSONException {
JSONObject params = json.getJSONObject("params");
JSONObject pollJson = params.optJSONObject("poll");
JSONArray mediaArray = json.optJSONArray("media_attachments");
String idStr = json.getString("id");
String visibilityStr = json.getString("visibility");
text = StringUtils.extractText(json.optString("text", ""));
sensitive = params.optBoolean("sensitive", false);
spoiler = params.optBoolean("spoiler_text", false);
if (!params.isNull("language")) {
language = params.optString("language");
}
if (pollJson != null) {
poll = new MastodonPoll(pollJson);
}
if (mediaArray != null && mediaArray.length() > 0) {
medias = new Media[mediaArray.length()];
for (int i = 0; i < mediaArray.length(); i++) {
JSONObject mediaItem = mediaArray.getJSONObject(i);
medias[i] = new MastodonMedia(mediaItem);
}
}
switch (visibilityStr) {
case "public":
visibility = Status.VISIBLE_PUBLIC;
break;
case "private":
visibility = Status.VISIBLE_PRIVATE;
break;
case "direct":
visibility = Status.VISIBLE_DIRECT;
break;
case "unlisted":
visibility = Status.VISIBLE_UNLISTED;
break;
default:
visibility = Status.VISIBLE_DEFAULT;
break;
}
try {
id = Long.parseLong(idStr);
} catch (NumberFormatException exception) {
throw new JSONException("Bad ID: " + idStr);
}
}
@Override
public long getId() {
return id;
}
@Override
public String getText() {
return text;
}
@Override
public String getLanguage() {
return language;
}
@Override
public Media[] getMedia() {
return medias;
}
@Override
public Poll getPoll() {
return poll;
}
@Override
public int getVisibility() {
return visibility;
}
@Override
public boolean isSensitive() {
return sensitive;
}
@Override
public boolean isSpoiler() {
return spoiler;
}
}

View File

@ -358,7 +358,7 @@ public class StatusUpdate implements Serializable, Closeable {
/**
* get visibility states
*
* @return visibility states {@link Status#VISIBLE_PUBLIC,Status#VISIBLE_DIRECT,Status#VISIBLE_PRIVATE,Status#VISIBLE_UNLISTED}
* @return visibility of the status {@link Status#VISIBLE_PUBLIC,Status#VISIBLE_DIRECT,Status#VISIBLE_PRIVATE,Status#VISIBLE_UNLISTED}
*/
public int getVisibility() {
return visibility;

View File

@ -0,0 +1,51 @@
package org.nuclearfog.twidda.model;
import java.io.Serializable;
/**
* Represents a scheduled status to post in the future
*
* @author nuclearfog
*/
public interface ScheduledStatus extends Serializable {
/**
* @return ID of the scheduled status
*/
long getId();
/**
* @return status text
*/
String getText();
/**
* @return language of the text if any
*/
String getLanguage();
/**
* @return attached media
*/
Media[] getMedia();
/**
* @return attached poll
*/
Poll getPoll();
/**
* @return visibility of the status {@link Status#VISIBLE_PUBLIC,Status#VISIBLE_DIRECT,Status#VISIBLE_PRIVATE,Status#VISIBLE_UNLISTED}
*/
int getVisibility();
/**
* @return true if status contains sensitive information
*/
boolean isSensitive();
/**
* @return true if status contains spoiler information
*/
boolean isSpoiler();
}

View File

@ -0,0 +1,10 @@
package org.nuclearfog.twidda.model.lists;
import org.nuclearfog.twidda.model.ScheduledStatus;
import java.util.LinkedList;
public class ScheduledStatuses extends LinkedList<ScheduledStatus> {
private static final long serialVersionUID = 9015646013535818699L;
}

View File

@ -3,6 +3,7 @@ package org.nuclearfog.twidda.ui.dialogs;
import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.text.format.DateFormat;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
@ -15,6 +16,7 @@ import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.config.GlobalSettings;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
@ -51,6 +53,8 @@ public class TimePickerDialog extends Dialog implements OnClickListener {
GlobalSettings settings = GlobalSettings.get(getContext());
AppStyles.setTheme(root, settings.getPopupColor());
timePicker.setIs24HourView(DateFormat.is24HourFormat(getContext()));
datePicker.setFirstDayOfWeek(Calendar.getInstance().getFirstDayOfWeek());
confirm.setOnClickListener(this);
cancel.setOnClickListener(this);