Issue #622 - Frontend for scheduled boosts

This commit is contained in:
stom79 2018-12-09 15:47:26 +01:00
parent d4fcb62c53
commit 523e1ecd09
11 changed files with 267 additions and 62 deletions

View File

@ -23,6 +23,8 @@ import android.database.sqlite.SQLiteDatabase;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -45,12 +47,16 @@ import java.util.List;
import es.dmoral.toasty.Toasty; import es.dmoral.toasty.Toasty;
import fr.gouv.etalab.mastodon.R; import fr.gouv.etalab.mastodon.R;
import fr.gouv.etalab.mastodon.activities.MainActivity; import fr.gouv.etalab.mastodon.activities.MainActivity;
import fr.gouv.etalab.mastodon.activities.ShowConversationActivity;
import fr.gouv.etalab.mastodon.activities.TootActivity; import fr.gouv.etalab.mastodon.activities.TootActivity;
import fr.gouv.etalab.mastodon.client.Entities.Status; import fr.gouv.etalab.mastodon.client.Entities.Status;
import fr.gouv.etalab.mastodon.client.Entities.StoredStatus; import fr.gouv.etalab.mastodon.client.Entities.StoredStatus;
import fr.gouv.etalab.mastodon.fragments.DisplayScheduledTootsFragment;
import fr.gouv.etalab.mastodon.helper.Helper; import fr.gouv.etalab.mastodon.helper.Helper;
import fr.gouv.etalab.mastodon.jobs.ApplicationJob; import fr.gouv.etalab.mastodon.jobs.ApplicationJob;
import fr.gouv.etalab.mastodon.jobs.ScheduledBoostsSyncJob;
import fr.gouv.etalab.mastodon.jobs.ScheduledTootsSyncJob; import fr.gouv.etalab.mastodon.jobs.ScheduledTootsSyncJob;
import fr.gouv.etalab.mastodon.sqlite.BoostScheduleDAO;
import fr.gouv.etalab.mastodon.sqlite.Sqlite; import fr.gouv.etalab.mastodon.sqlite.Sqlite;
import fr.gouv.etalab.mastodon.sqlite.StatusStoredDAO; import fr.gouv.etalab.mastodon.sqlite.StatusStoredDAO;
@ -68,13 +74,15 @@ public class ScheduledTootsListAdapter extends BaseAdapter {
private LayoutInflater layoutInflater; private LayoutInflater layoutInflater;
private ScheduledTootsListAdapter scheduledTootsListAdapter; private ScheduledTootsListAdapter scheduledTootsListAdapter;
private RelativeLayout textviewNoAction; private RelativeLayout textviewNoAction;
private DisplayScheduledTootsFragment.typeOfSchedule type;
public ScheduledTootsListAdapter(Context context, List<StoredStatus> storedStatuses, RelativeLayout textviewNoAction){ public ScheduledTootsListAdapter(Context context, DisplayScheduledTootsFragment.typeOfSchedule type, List<StoredStatus> storedStatuses, RelativeLayout textviewNoAction){
this.context = context; this.context = context;
this.storedStatuses = storedStatuses; this.storedStatuses = storedStatuses;
layoutInflater = LayoutInflater.from(this.context); layoutInflater = LayoutInflater.from(this.context);
scheduledTootsListAdapter = this; scheduledTootsListAdapter = this;
this.textviewNoAction = textviewNoAction; this.textviewNoAction = textviewNoAction;
this.type = type;
} }
@ -103,6 +111,7 @@ public class ScheduledTootsListAdapter extends BaseAdapter {
if (convertView == null) { if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.drawer_scheduled_toot, parent, false); convertView = layoutInflater.inflate(R.layout.drawer_scheduled_toot, parent, false);
holder = new ViewHolder(); holder = new ViewHolder();
holder.scheduled_toot_pp= convertView.findViewById(R.id.scheduled_toot_pp);
holder.scheduled_toot_title = convertView.findViewById(R.id.scheduled_toot_title); holder.scheduled_toot_title = convertView.findViewById(R.id.scheduled_toot_title);
holder.scheduled_toot_date_creation = convertView.findViewById(R.id.scheduled_toot_date_creation); holder.scheduled_toot_date_creation = convertView.findViewById(R.id.scheduled_toot_date_creation);
holder.scheduled_toot_media_count = convertView.findViewById(R.id.scheduled_toot_media_count); holder.scheduled_toot_media_count = convertView.findViewById(R.id.scheduled_toot_media_count);
@ -119,18 +128,24 @@ public class ScheduledTootsListAdapter extends BaseAdapter {
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); final int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
if( theme == Helper.THEME_DARK){ if( theme == Helper.THEME_BLACK) {
changeDrawableColor(context, R.drawable.ic_cancel,R.color.dark_text); changeDrawableColor(context, R.drawable.ic_cancel,R.color.action_black);
changeDrawableColor(context, R.drawable.ic_public,R.color.dark_text); changeDrawableColor(context, R.drawable.ic_public,R.color.action_black);
changeDrawableColor(context, R.drawable.ic_lock_open,R.color.dark_text); changeDrawableColor(context, R.drawable.ic_lock_open,R.color.action_black);
changeDrawableColor(context, R.drawable.ic_lock_outline,R.color.dark_text); changeDrawableColor(context, R.drawable.ic_lock_outline,R.color.action_black);
changeDrawableColor(context, R.drawable.ic_mail_outline,R.color.dark_text); changeDrawableColor(context, R.drawable.ic_mail_outline,R.color.action_black);
}else if( theme == Helper.THEME_DARK){
changeDrawableColor(context, R.drawable.ic_cancel,R.color.action_dark);
changeDrawableColor(context, R.drawable.ic_public,R.color.action_dark);
changeDrawableColor(context, R.drawable.ic_lock_open,R.color.action_dark);
changeDrawableColor(context, R.drawable.ic_lock_outline,R.color.action_dark);
changeDrawableColor(context, R.drawable.ic_mail_outline,R.color.action_dark);
}else { }else {
changeDrawableColor(context, R.drawable.ic_cancel,R.color.black); changeDrawableColor(context, R.drawable.ic_cancel,R.color.action_light);
changeDrawableColor(context, R.drawable.ic_public,R.color.black); changeDrawableColor(context, R.drawable.ic_public,R.color.action_light);
changeDrawableColor(context, R.drawable.ic_lock_open,R.color.black); changeDrawableColor(context, R.drawable.ic_lock_open,R.color.action_light);
changeDrawableColor(context, R.drawable.ic_lock_outline,R.color.black); changeDrawableColor(context, R.drawable.ic_lock_outline,R.color.action_light);
changeDrawableColor(context, R.drawable.ic_mail_outline,R.color.black); changeDrawableColor(context, R.drawable.ic_mail_outline,R.color.action_light);
} }
final Status status = storedStatus.getStatus(); final Status status = storedStatus.getStatus();
@ -163,13 +178,28 @@ public class ScheduledTootsListAdapter extends BaseAdapter {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(context, style); AlertDialog.Builder builder = new AlertDialog.Builder(context, style);
builder.setMessage(status.getContent() + '\n' + Helper.dateToString(storedStatus.getCreation_date()));
String message;
if( type == DisplayScheduledTootsFragment.typeOfSchedule.TOOT)
message = status.getContent() + '\n' + Helper.dateToString(storedStatus.getCreation_date());
else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
message = Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_LEGACY).toString();
else
//noinspection deprecation
message = Html.fromHtml(status.getContent()).toString();
message += '\n' + Helper.dateToString(storedStatus.getScheduled_date());
}
builder.setMessage(message);
builder.setIcon(android.R.drawable.ic_dialog_alert) builder.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle(R.string.remove_scheduled) .setTitle(R.string.remove_scheduled)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
new StatusStoredDAO(context, db).remove(storedStatus.getId()); if( type == DisplayScheduledTootsFragment.typeOfSchedule.TOOT)
new StatusStoredDAO(context, db).remove(storedStatus.getId());
else if (type == DisplayScheduledTootsFragment.typeOfSchedule.BOOST)
new BoostScheduleDAO(context, db).remove(storedStatus.getId());
storedStatuses.remove(storedStatus); storedStatuses.remove(storedStatus);
scheduledTootsListAdapter.notifyDataSetChanged(); scheduledTootsListAdapter.notifyDataSetChanged();
if( storedStatuses.size() == 0 && textviewNoAction != null && textviewNoAction.getVisibility() == View.GONE) if( storedStatuses.size() == 0 && textviewNoAction != null && textviewNoAction.getVisibility() == View.GONE)
@ -200,6 +230,14 @@ public class ScheduledTootsListAdapter extends BaseAdapter {
holder.scheduled_toot_media_count.setText(context.getString(R.string.media_count, status.getMedia_attachments().size())); holder.scheduled_toot_media_count.setText(context.getString(R.string.media_count, status.getMedia_attachments().size()));
holder.scheduled_toot_date_creation.setText(Helper.dateToString(storedStatus.getCreation_date())); holder.scheduled_toot_date_creation.setText(Helper.dateToString(storedStatus.getCreation_date()));
holder.scheduled_toot_date.setText(Helper.dateToString(storedStatus.getScheduled_date())); holder.scheduled_toot_date.setText(Helper.dateToString(storedStatus.getScheduled_date()));
if( type == DisplayScheduledTootsFragment.typeOfSchedule.BOOST){
holder.scheduled_toot_media_count.setVisibility(View.GONE);
holder.scheduled_toot_date_creation.setVisibility(View.GONE);
holder.scheduled_toot_privacy.setVisibility(View.GONE);
Helper.loadGiF(context, storedStatus.getStatus().getAccount().getAvatar(), holder.scheduled_toot_pp);
}else {
holder.scheduled_toot_pp.setVisibility(View.GONE);
}
holder.scheduled_toot_date.setOnClickListener(new View.OnClickListener() { holder.scheduled_toot_date.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
@ -208,14 +246,19 @@ public class ScheduledTootsListAdapter extends BaseAdapter {
@SuppressLint("InflateParams") View dialogView = inflater.inflate(R.layout.datetime_picker, null); @SuppressLint("InflateParams") View dialogView = inflater.inflate(R.layout.datetime_picker, null);
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, android.content.Context.MODE_PRIVATE);
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
if( theme == Helper.THEME_DARK){
changeDrawableColor(context, R.drawable.ic_skip_previous,R.color.dark_text); if( theme == Helper.THEME_BLACK){
changeDrawableColor(context, R.drawable.ic_skip_next,R.color.dark_text); changeDrawableColor(context, R.drawable.ic_skip_previous,R.color.action_black);
changeDrawableColor(context, R.drawable.ic_check,R.color.dark_text); changeDrawableColor(context, R.drawable.ic_skip_next,R.color.action_black);
changeDrawableColor(context, R.drawable.ic_check,R.color.action_black);
}else if( theme == Helper.THEME_DARK){
changeDrawableColor(context, R.drawable.ic_skip_previous,R.color.action_dark);
changeDrawableColor(context, R.drawable.ic_skip_next,R.color.action_dark);
changeDrawableColor(context, R.drawable.ic_check,R.color.action_dark);
}else { }else {
changeDrawableColor(context, R.drawable.ic_skip_previous,R.color.black); changeDrawableColor(context, R.drawable.ic_skip_previous,R.color.action_light);
changeDrawableColor(context, R.drawable.ic_skip_next,R.color.black); changeDrawableColor(context, R.drawable.ic_skip_next,R.color.action_light);
changeDrawableColor(context, R.drawable.ic_check,R.color.black); changeDrawableColor(context, R.drawable.ic_check,R.color.action_light);
} }
dialogBuilder.setView(dialogView); dialogBuilder.setView(dialogView);
final AlertDialog alertDialog = dialogBuilder.create(); final AlertDialog alertDialog = dialogBuilder.create();
@ -281,13 +324,23 @@ public class ScheduledTootsListAdapter extends BaseAdapter {
//Removes the job //Removes the job
ApplicationJob.cancelJob(storedStatus.getJobId()); ApplicationJob.cancelJob(storedStatus.getJobId());
//Replace it by the new one //Replace it by the new one
ScheduledTootsSyncJob.schedule(context, storedStatus.getId(), time); StoredStatus storedStatusnew = null;
StoredStatus storedStatusnew = new StatusStoredDAO(context, db).getStatus(storedStatus.getId()); if( type == DisplayScheduledTootsFragment.typeOfSchedule.TOOT) {
ScheduledTootsSyncJob.schedule(context, storedStatus.getId(), time);
storedStatusnew = new StatusStoredDAO(context, db).getStatus(storedStatus.getId());
}else if(type == DisplayScheduledTootsFragment.typeOfSchedule.BOOST){
ScheduledBoostsSyncJob.scheduleUpdate(context, storedStatus.getId(), time);
storedStatusnew = new BoostScheduleDAO(context, db).getStatus(storedStatus.getId());
}
//Date displayed is changed //Date displayed is changed
assert storedStatusnew != null;
storedStatus.setScheduled_date(storedStatusnew.getScheduled_date()); storedStatus.setScheduled_date(storedStatusnew.getScheduled_date());
scheduledTootsListAdapter.notifyDataSetChanged(); scheduledTootsListAdapter.notifyDataSetChanged();
//Notifiy all is ok //Notifiy all is ok
Toasty.success(context,context.getString(R.string.toot_scheduled), Toast.LENGTH_LONG).show(); if( type == DisplayScheduledTootsFragment.typeOfSchedule.TOOT)
Toasty.success(context,context.getString(R.string.toot_scheduled), Toast.LENGTH_LONG).show();
else
Toasty.success(context,context.getString(R.string.boost_scheduled), Toast.LENGTH_LONG).show();
}catch (Exception ignored){} }catch (Exception ignored){}
alertDialog.dismiss(); alertDialog.dismiss();
} }
@ -296,22 +349,43 @@ public class ScheduledTootsListAdapter extends BaseAdapter {
alertDialog.show(); alertDialog.show();
} }
}); });
holder.scheduled_toot_title.setText(status.getContent()); if( type == DisplayScheduledTootsFragment.typeOfSchedule.TOOT)
holder.scheduled_toot_title.setText(status.getContent());
else if( type == DisplayScheduledTootsFragment.typeOfSchedule.BOOST){
Spanned message;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
message = Html.fromHtml(status.getContent(), Html.FROM_HTML_MODE_LEGACY);
else
//noinspection deprecation
message = Html.fromHtml(status.getContent());
holder.scheduled_toot_title.setText(message, TextView.BufferType.SPANNABLE);
}
holder.scheduled_toot_container.setOnClickListener(new View.OnClickListener() { if( type == DisplayScheduledTootsFragment.typeOfSchedule.TOOT)
@Override holder.scheduled_toot_container.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) { @Override
Intent intentToot = new Intent(context, TootActivity.class); public void onClick(View v) {
Bundle b = new Bundle(); Intent intentToot = new Intent(context, TootActivity.class);
b.putLong("restored", storedStatus.getId()); Bundle b = new Bundle();
b.putBoolean("restoredScheduled", true); b.putLong("restored", storedStatus.getId());
intentToot.putExtras(b); b.putBoolean("restoredScheduled", true);
context.startActivity(intentToot); intentToot.putExtras(b);
} context.startActivity(intentToot);
}); }
});
else if( type == DisplayScheduledTootsFragment.typeOfSchedule.BOOST)
holder.scheduled_toot_container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intentToot = new Intent(context, ShowConversationActivity.class);
Bundle b = new Bundle();
b.putParcelable("status", storedStatus.getStatus());
intentToot.putExtras(b);
context.startActivity(intentToot);
}
});
return convertView; return convertView;
} }
@ -323,6 +397,7 @@ public class ScheduledTootsListAdapter extends BaseAdapter {
TextView scheduled_toot_failed; TextView scheduled_toot_failed;
ImageView scheduled_toot_delete; ImageView scheduled_toot_delete;
ImageView scheduled_toot_privacy; ImageView scheduled_toot_privacy;
ImageView scheduled_toot_pp;
Button scheduled_toot_date; Button scheduled_toot_date;
} }

View File

@ -114,6 +114,7 @@ import fr.gouv.etalab.mastodon.interfaces.OnRetrieveCardInterface;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveEmojiInterface; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveEmojiInterface;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveFeedsInterface;
import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRepliesInterface; import fr.gouv.etalab.mastodon.interfaces.OnRetrieveRepliesInterface;
import fr.gouv.etalab.mastodon.jobs.ScheduledBoostsSyncJob;
import fr.gouv.etalab.mastodon.sqlite.AccountDAO; import fr.gouv.etalab.mastodon.sqlite.AccountDAO;
import fr.gouv.etalab.mastodon.sqlite.Sqlite; import fr.gouv.etalab.mastodon.sqlite.Sqlite;
import fr.gouv.etalab.mastodon.sqlite.StatusCacheDAO; import fr.gouv.etalab.mastodon.sqlite.StatusCacheDAO;
@ -1600,6 +1601,8 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
else else
popup.getMenu().findItem(R.id.action_bookmark).setTitle(R.string.bookmark_add); popup.getMenu().findItem(R.id.action_bookmark).setTitle(R.string.bookmark_add);
final String[] stringArrayConf; final String[] stringArrayConf;
if( status.getVisibility().equals("direct") || (status.getVisibility().equals("private") && !isOwner))
popup.getMenu().findItem(R.id.action_schedule_boost).setVisible(false);
if( isOwner) { if( isOwner) {
popup.getMenu().findItem(R.id.action_block).setVisible(false); popup.getMenu().findItem(R.id.action_block).setVisible(false);
popup.getMenu().findItem(R.id.action_mute).setVisible(false); popup.getMenu().findItem(R.id.action_mute).setVisible(false);
@ -1644,6 +1647,81 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
//noinspection deprecation //noinspection deprecation
builderInner.setMessage(Html.fromHtml(status.getContent())); builderInner.setMessage(Html.fromHtml(status.getContent()));
break; break;
case R.id.action_schedule_boost:
AlertDialog.Builder dialogBuilderBoost = new AlertDialog.Builder(context, style);
LayoutInflater inflaterBoost = ((Activity)context).getLayoutInflater();
@SuppressLint("InflateParams") View dialogViewBoost = inflaterBoost.inflate(R.layout.datetime_picker, null);
dialogBuilderBoost.setView(dialogViewBoost);
final AlertDialog alertDialogBoost = dialogBuilderBoost.create();
final DatePicker datePickerBoost = dialogViewBoost.findViewById(R.id.date_picker);
final TimePicker timePickerBoost = dialogViewBoost.findViewById(R.id.time_picker);
timePickerBoost.setIs24HourView(true);
Button date_time_cancelBoost = dialogViewBoost.findViewById(R.id.date_time_cancel);
final ImageButton date_time_previousBoost = dialogViewBoost.findViewById(R.id.date_time_previous);
final ImageButton date_time_nextBoost = dialogViewBoost.findViewById(R.id.date_time_next);
final ImageButton date_time_setBoost = dialogViewBoost.findViewById(R.id.date_time_set);
//Buttons management
date_time_cancelBoost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
alertDialogBoost.dismiss();
}
});
date_time_nextBoost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
datePickerBoost.setVisibility(View.GONE);
timePickerBoost.setVisibility(View.VISIBLE);
date_time_previousBoost.setVisibility(View.VISIBLE);
date_time_nextBoost.setVisibility(View.GONE);
date_time_setBoost.setVisibility(View.VISIBLE);
}
});
date_time_previousBoost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
datePickerBoost.setVisibility(View.VISIBLE);
timePickerBoost.setVisibility(View.GONE);
date_time_previousBoost.setVisibility(View.GONE);
date_time_nextBoost.setVisibility(View.VISIBLE);
date_time_setBoost.setVisibility(View.GONE);
}
});
date_time_setBoost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
int hour, minute;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
hour = timePickerBoost.getHour();
minute = timePickerBoost.getMinute();
}else {
//noinspection deprecation
hour = timePickerBoost.getCurrentHour();
//noinspection deprecation
minute = timePickerBoost.getCurrentMinute();
}
Calendar calendar = new GregorianCalendar(datePickerBoost.getYear(),
datePickerBoost.getMonth(),
datePickerBoost.getDayOfMonth(),
hour,
minute);
long time = calendar.getTimeInMillis();
if( (time - new Date().getTime()) < 60000 ){
Toasty.warning(context, context.getString(R.string.toot_scheduled_date), Toast.LENGTH_LONG).show();
}else {
//Schedules the toot
ScheduledBoostsSyncJob.schedule(context,status, time);
//Clear content
Toasty.info(context, context.getString(R.string.boost_scheduled), Toast.LENGTH_LONG).show();
alertDialogBoost.dismiss();
}
}
});
alertDialogBoost.show();
return true;
case R.id.action_info: case R.id.action_info:
Intent intent = new Intent(context, TootInfoActivity.class); Intent intent = new Intent(context, TootInfoActivity.class);
Bundle b = new Bundle(); Bundle b = new Bundle();

View File

@ -28,6 +28,8 @@ import android.os.PowerManager;
import android.provider.Settings; import android.provider.Settings;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.text.Html;
import android.text.Spanned;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@ -75,7 +77,8 @@ public class DisplayScheduledTootsFragment extends Fragment implements OnRetriev
View rootView = inflater.inflate(R.layout.fragment_scheduled_toots, container, false); View rootView = inflater.inflate(R.layout.fragment_scheduled_toots, container, false);
context = getContext(); context = getContext();
Bundle bundle = new Bundle(); Bundle bundle = this.getArguments();
assert bundle != null;
type = (typeOfSchedule) bundle.get("type"); type = (typeOfSchedule) bundle.get("type");
if( type == null) if( type == null)
type = typeOfSchedule.TOOT; type = typeOfSchedule.TOOT;
@ -177,11 +180,24 @@ public class DisplayScheduledTootsFragment extends Fragment implements OnRetriev
mainLoader.setVisibility(View.GONE); mainLoader.setVisibility(View.GONE);
if( storedStatuses != null && storedStatuses.size() > 0 ){ if( storedStatuses != null && storedStatuses.size() > 0 ){
ScheduledTootsListAdapter scheduledTootsListAdapter = new ScheduledTootsListAdapter(context, storedStatuses, textviewNoAction); ScheduledTootsListAdapter scheduledTootsListAdapter = new ScheduledTootsListAdapter(context, type, storedStatuses, textviewNoAction);
lv_scheduled_toots.setAdapter(scheduledTootsListAdapter); lv_scheduled_toots.setAdapter(scheduledTootsListAdapter);
textviewNoAction.setVisibility(View.GONE); textviewNoAction.setVisibility(View.GONE);
}else { }else {
textviewNoAction.setVisibility(View.VISIBLE); textviewNoAction.setVisibility(View.VISIBLE);
if( type == typeOfSchedule.BOOST) {
TextView no_action_text = textviewNoAction.findViewById(R.id.no_action_text);
TextView no_action_text_subtitle = textviewNoAction.findViewById(R.id.no_action_text_subtitle);
no_action_text.setText(context.getString(R.string.no_scheduled_boosts));
Spanned message;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
message = Html.fromHtml(context.getString(R.string.no_scheduled_boosts_indications), Html.FROM_HTML_MODE_LEGACY);
else
//noinspection deprecation
message = Html.fromHtml(context.getString(R.string.no_scheduled_boosts_indications));
no_action_text_subtitle.setText(message, TextView.BufferType.SPANNABLE);
}
} }
} }
} }

View File

@ -95,6 +95,7 @@ public class TabLayoutScheduleFragment extends Fragment {
bundle = new Bundle(); bundle = new Bundle();
bundle.putSerializable("type", DisplayScheduledTootsFragment.typeOfSchedule.BOOST); bundle.putSerializable("type", DisplayScheduledTootsFragment.typeOfSchedule.BOOST);
displayScheduledTootsFragment.setArguments(bundle); displayScheduledTootsFragment.setArguments(bundle);
return displayScheduledTootsFragment;
default: default:
displayScheduledTootsFragment = new DisplayScheduledTootsFragment(); displayScheduledTootsFragment = new DisplayScheduledTootsFragment();
bundle = new Bundle(); bundle = new Bundle();

View File

@ -34,6 +34,8 @@ public class ApplicationJob implements JobCreator {
return new HomeTimelineSyncJob(); return new HomeTimelineSyncJob();
case ScheduledTootsSyncJob.SCHEDULED_TOOT: case ScheduledTootsSyncJob.SCHEDULED_TOOT:
return new ScheduledTootsSyncJob(); return new ScheduledTootsSyncJob();
case ScheduledBoostsSyncJob.SCHEDULED_BOOST:
return new ScheduledBoostsSyncJob();
default: default:
return null; return null;
} }

View File

@ -63,7 +63,8 @@ public class ScheduledBoostsSyncJob extends Job {
//Retrieves the linked status to toot //Retrieves the linked status to toot
Status status = storedStatus.getStatus(); Status status = storedStatus.getStatus();
if( status != null){ if( status != null){
int statusCode = new API(getContext(), account.getInstance(), account.getToken()).statusAction(status); int statusCode = new API(getContext(), account.getInstance(), account.getToken()).postAction( API.StatusAction.REBLOG, status.getId());
//Toot was sent //Toot was sent
if( statusCode == 200){ if( statusCode == 200){
new BoostScheduleDAO(getContext(), db).updateScheduledDone(jobId, new Date()); new BoostScheduleDAO(getContext(), db).updateScheduledDone(jobId, new Date());
@ -76,7 +77,7 @@ public class ScheduledBoostsSyncJob extends Job {
} }
public static int schedule(Context context, Status status, long id, long timestampScheduling){ public static int schedule(Context context, Status status, long timestampScheduling){
long startMs = (timestampScheduling - new Date().getTime()); long startMs = (timestampScheduling - new Date().getTime());
long endMs = startMs + TimeUnit.MINUTES.toMillis(5); long endMs = startMs + TimeUnit.MINUTES.toMillis(5);
@ -89,7 +90,25 @@ public class ScheduledBoostsSyncJob extends Job {
.setRequirementsEnforced(false) .setRequirementsEnforced(false)
.build() .build()
.schedule(); .schedule();
new BoostScheduleDAO(context, db).insert(status, id, jobId, new Date(timestampScheduling)); new BoostScheduleDAO(context, db).insert(status, jobId, new Date(timestampScheduling));
return jobId;
}
public static int scheduleUpdate(Context context, int tootStoredId, long timestampScheduling){
long startMs = (timestampScheduling - new Date().getTime());
long endMs = startMs + TimeUnit.MINUTES.toMillis(5);
SQLiteDatabase db = Sqlite.getInstance(context, Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open();
int jobId = new JobRequest.Builder(ScheduledTootsSyncJob.SCHEDULED_TOOT)
.setExecutionWindow(startMs, endMs)
.setUpdateCurrent(false)
.setRequiredNetworkType(JobRequest.NetworkType.METERED)
.setRequirementsEnforced(false)
.build()
.schedule();
new BoostScheduleDAO(context, db).updateScheduledDate(tootStoredId, jobId, new Date(timestampScheduling));
return jobId; return jobId;
} }

View File

@ -51,11 +51,11 @@ public class BoostScheduleDAO {
/** /**
* Insert a status in database * Insert a status in database
* @param status Status * @param status Status
* @param id long
* @param jobId int * @param jobId int
* @return boolean * @return boolean
*/ */
public long insert(Status status, long id, int jobId, Date date_scheduled ) { public long insert(Status status, int jobId, Date date_scheduled ) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
String serializedStatus = Helper.statusToStringStorage(status); String serializedStatus = Helper.statusToStringStorage(status);
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
@ -64,7 +64,6 @@ public class BoostScheduleDAO {
if( userId == null || instance == null) if( userId == null || instance == null)
return -1; return -1;
values.put(Sqlite.COL_STATUS_SERIALIZED, serializedStatus); values.put(Sqlite.COL_STATUS_SERIALIZED, serializedStatus);
values.put(Sqlite.COL_DATE_CREATION, Helper.dateToString(new Date()));
values.put(Sqlite.COL_INSTANCE, instance); values.put(Sqlite.COL_INSTANCE, instance);
values.put(Sqlite.COL_USER_ID, userId); values.put(Sqlite.COL_USER_ID, userId);
values.put(Sqlite.COL_SENT, 0); values.put(Sqlite.COL_SENT, 0);
@ -75,6 +74,7 @@ public class BoostScheduleDAO {
try{ try{
last_id = db.insert(Sqlite.TABLE_BOOST_SCHEDULE, null, values); last_id = db.insert(Sqlite.TABLE_BOOST_SCHEDULE, null, values);
}catch (Exception e) { }catch (Exception e) {
e.printStackTrace();
last_id = -1; last_id = -1;
} }
return last_id; return last_id;
@ -100,12 +100,12 @@ public class BoostScheduleDAO {
* @param scheduled_date Date * @param scheduled_date Date
* @return boolean * @return boolean
*/ */
public int updateScheduledDate(int jobid, Date scheduled_date) { public int updateScheduledDate(int statusStoredId, int jobid, Date scheduled_date) {
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put(Sqlite.COL_DATE_SCHEDULED, Helper.dateToString(scheduled_date)); values.put(Sqlite.COL_DATE_SCHEDULED, Helper.dateToString(scheduled_date));
return db.update(Sqlite.TABLE_BOOST_SCHEDULE, return db.update(Sqlite.TABLE_BOOST_SCHEDULE,
values, Sqlite.COL_IS_SCHEDULED + " = ? ", values, Sqlite.COL_IS_SCHEDULED + " = ? AND " + Sqlite.COL_ID + " = ?",
new String[]{String.valueOf(jobid)}); new String[]{String.valueOf(jobid), String.valueOf(statusStoredId)});
} }
/** /**
@ -152,6 +152,7 @@ public class BoostScheduleDAO {
Cursor c = db.query(Sqlite.TABLE_BOOST_SCHEDULE, null, Sqlite.COL_USER_ID + " = '" + userId+ "' AND " + Sqlite.COL_INSTANCE + " = '" + instance+ "' AND " + Sqlite.COL_IS_SCHEDULED + " != 0 AND " + Sqlite.COL_SENT + " = 0", null, null, null, Sqlite.COL_DATE_SCHEDULED + " ASC", null); Cursor c = db.query(Sqlite.TABLE_BOOST_SCHEDULE, null, Sqlite.COL_USER_ID + " = '" + userId+ "' AND " + Sqlite.COL_INSTANCE + " = '" + instance+ "' AND " + Sqlite.COL_IS_SCHEDULED + " != 0 AND " + Sqlite.COL_SENT + " = 0", null, null, null, Sqlite.COL_DATE_SCHEDULED + " ASC", null);
return cursorToListStatuses(c); return cursorToListStatuses(c);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
return null; return null;
} }
} }
@ -164,7 +165,7 @@ public class BoostScheduleDAO {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = Helper.getLiveInstance(context); String instance = Helper.getLiveInstance(context);
Cursor c = db.query(Sqlite.TABLE_BOOST_SCHEDULE, null, Sqlite.COL_USER_ID + " = '" + userId+ "' AND " + Sqlite.COL_INSTANCE + " = '" + instance+ "' AND " +Sqlite.COL_IS_SCHEDULED + " != 0 AND " + Sqlite.COL_SENT + " = 0", null, null, null, Sqlite.COL_DATE_CREATION + " DESC", null); Cursor c = db.query(Sqlite.TABLE_BOOST_SCHEDULE, null, Sqlite.COL_USER_ID + " = '" + userId+ "' AND " + Sqlite.COL_INSTANCE + " = '" + instance+ "' AND " +Sqlite.COL_IS_SCHEDULED + " != 0 AND " + Sqlite.COL_SENT + " = 0", null, null, null, Sqlite.COL_DATE_SCHEDULED + " DESC", null);
return cursorToListStatuses(c); return cursorToListStatuses(c);
} catch (Exception e) { } catch (Exception e) {
return null; return null;
@ -180,7 +181,7 @@ public class BoostScheduleDAO {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null);
String instance = Helper.getLiveInstance(context); String instance = Helper.getLiveInstance(context);
Cursor c = db.query(Sqlite.TABLE_BOOST_SCHEDULE, null, Sqlite.COL_USER_ID + " = '" + userId+ "' AND " + Sqlite.COL_INSTANCE + " = '" + instance+ "' AND " +Sqlite.COL_IS_SCHEDULED + " != 0 AND " + Sqlite.COL_SENT + " = 1", null, null, null, Sqlite.COL_DATE_CREATION + " DESC", null); Cursor c = db.query(Sqlite.TABLE_BOOST_SCHEDULE, null, Sqlite.COL_USER_ID + " = '" + userId+ "' AND " + Sqlite.COL_INSTANCE + " = '" + instance+ "' AND " +Sqlite.COL_IS_SCHEDULED + " != 0 AND " + Sqlite.COL_SENT + " = 1", null, null, null, Sqlite.COL_DATE_SCHEDULED + " DESC", null);
return cursorToListStatuses(c); return cursorToListStatuses(c);
} catch (Exception e) { } catch (Exception e) {
return null; return null;
@ -237,7 +238,6 @@ public class BoostScheduleDAO {
storedStatus.setStatusReply(null); storedStatus.setStatusReply(null);
storedStatus.setSent(c.getInt(c.getColumnIndex(Sqlite.COL_SENT)) == 1); storedStatus.setSent(c.getInt(c.getColumnIndex(Sqlite.COL_SENT)) == 1);
storedStatus.setJobId(c.getInt(c.getColumnIndex(Sqlite.COL_IS_SCHEDULED))); storedStatus.setJobId(c.getInt(c.getColumnIndex(Sqlite.COL_IS_SCHEDULED)));
storedStatus.setCreation_date(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_DATE_CREATION))));
storedStatus.setScheduled_date(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_DATE_SCHEDULED)))); storedStatus.setScheduled_date(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_DATE_SCHEDULED))));
storedStatus.setSent_date(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_DATE_SENT)))); storedStatus.setSent_date(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_DATE_SENT))));
storedStatus.setUserId(c.getString(c.getColumnIndex(Sqlite.COL_USER_ID))); storedStatus.setUserId(c.getString(c.getColumnIndex(Sqlite.COL_USER_ID)));
@ -268,11 +268,9 @@ public class BoostScheduleDAO {
continue; continue;
} }
storedStatus.setStatus(status); storedStatus.setStatus(status);
Status statusReply = Helper.restoreStatusFromString(c.getString(c.getColumnIndex(Sqlite.COL_STATUS_REPLY_SERIALIZED))); storedStatus.setStatusReply(null);
storedStatus.setStatusReply(statusReply);
storedStatus.setSent(c.getInt(c.getColumnIndex(Sqlite.COL_SENT)) == 1); storedStatus.setSent(c.getInt(c.getColumnIndex(Sqlite.COL_SENT)) == 1);
storedStatus.setJobId(c.getInt(c.getColumnIndex(Sqlite.COL_IS_SCHEDULED)) ); storedStatus.setJobId(c.getInt(c.getColumnIndex(Sqlite.COL_IS_SCHEDULED)) );
storedStatus.setCreation_date(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_DATE_CREATION))));
storedStatus.setScheduled_date(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_DATE_SCHEDULED)))); storedStatus.setScheduled_date(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_DATE_SCHEDULED))));
storedStatus.setSent_date(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_DATE_SENT)))); storedStatus.setSent_date(Helper.stringToDate(context, c.getString(c.getColumnIndex(Sqlite.COL_DATE_SENT))));
storedStatus.setUserId(c.getString(c.getColumnIndex(Sqlite.COL_USER_ID))); storedStatus.setUserId(c.getString(c.getColumnIndex(Sqlite.COL_USER_ID)));

View File

@ -22,6 +22,14 @@
android:orientation="horizontal" android:orientation="horizontal"
android:id="@+id/scheduled_toot_container" android:id="@+id/scheduled_toot_container"
> >
<ImageView
android:id="@+id/scheduled_toot_pp"
android:layout_gravity="center_vertical|top"
android:gravity="center_vertical|top"
android:layout_width="50dp"
android:layout_marginTop="5dp"
android:layout_height="50dp"
tools:ignore="ContentDescription" />
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1" android:layout_weight="1"
@ -31,7 +39,6 @@
android:orientation="vertical"> android:orientation="vertical">
<TextView <TextView
android:id="@+id/scheduled_toot_title" android:id="@+id/scheduled_toot_title"
android:textStyle="bold"
android:maxLines="3" android:maxLines="3"
android:layout_marginLeft="10dp" android:layout_marginLeft="10dp"
android:layout_marginStart="10dp" android:layout_marginStart="10dp"

View File

@ -72,6 +72,7 @@
android:layout_height="wrap_content" /> android:layout_height="wrap_content" />
<TextView <TextView
android:padding="10dp" android:padding="10dp"
android:id="@+id/no_action_text_subtitle"
android:layout_below="@+id/no_action_text" android:layout_below="@+id/no_action_text"
android:layout_marginTop="10dp" android:layout_marginTop="10dp"
android:gravity="center" android:gravity="center"

View File

@ -19,13 +19,21 @@
android:title="@string/action_open_in_web" android:title="@string/action_open_in_web"
app:showAsAction="never"/> app:showAsAction="never"/>
<item <item
android:id="@+id/action_mute" android:id="@+id/action_share"
android:title="@string/more_action_1" android:title="@string/more_action_6"
app:showAsAction="never" /> app:showAsAction="never" />
<item <item
android:id="@+id/action_timed_mute" android:id="@+id/action_timed_mute"
android:title="@string/more_action_8" android:title="@string/more_action_8"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/action_schedule_boost"
android:title="@string/schedule_boost"
app:showAsAction="never" />
<item
android:id="@+id/action_mute"
android:title="@string/more_action_1"
app:showAsAction="never" />
<item <item
android:id="@+id/action_block" android:id="@+id/action_block"
android:title="@string/more_action_2" android:title="@string/more_action_2"
@ -50,10 +58,6 @@
android:id="@+id/action_copy" android:id="@+id/action_copy"
android:title="@string/more_action_5" android:title="@string/more_action_5"
app:showAsAction="never" /> app:showAsAction="never" />
<item
android:id="@+id/action_share"
android:title="@string/more_action_6"
app:showAsAction="never" />
<item <item
android:id="@+id/action_mention" android:id="@+id/action_mention"
android:title="@string/more_action_7" android:title="@string/more_action_7"

View File

@ -219,7 +219,7 @@
<!-- Scheduled toots --> <!-- Scheduled toots -->
<string name="no_scheduled_toots">No scheduled toot to display!</string> <string name="no_scheduled_toots">No scheduled toots to display!</string>
<string name="no_scheduled_toots_indications">Write a toot and then choose <b>Schedule</b> from the top menu.</string> <string name="no_scheduled_toots_indications">Write a toot and then choose <b>Schedule</b> from the top menu.</string>
<string name="remove_scheduled">Delete scheduled toot?</string> <string name="remove_scheduled">Delete scheduled toot?</string>
<string name="media_count">Media: %d</string> <string name="media_count">Media: %d</string>
@ -686,6 +686,10 @@
<string name="tags_renamed">The tag has been changed!</string> <string name="tags_renamed">The tag has been changed!</string>
<string name="tags_deleted">The tag has been deleted!</string> <string name="tags_deleted">The tag has been deleted!</string>
<string name="set_display_art">Display Art timeline</string> <string name="set_display_art">Display Art timeline</string>
<string name="schedule_boost">Schedule boost</string>
<string name="boost_scheduled">The boost is scheduled!</string>
<string name="no_scheduled_boosts">No scheduled boost to display!</string>
<string name="no_scheduled_boosts_indications"><![CDATA[Open the menu of a toot and then choose <b>Schedule boost</b>.]]></string>
<string-array name="filter_expire"> <string-array name="filter_expire">
<item>Never</item> <item>Never</item>