Manage votes
This commit is contained in:
parent
c0f6352604
commit
4c54271a70
|
@ -94,5 +94,6 @@ dependencies {
|
||||||
implementation 'com.github.mabbas007:TagsEditText:1.0.5'
|
implementation 'com.github.mabbas007:TagsEditText:1.0.5'
|
||||||
implementation 'com.jaredrummler:material-spinner:1.3.1'
|
implementation 'com.jaredrummler:material-spinner:1.3.1'
|
||||||
implementation "com.tonyodev.fetch2:fetch2:2.3.6"
|
implementation "com.tonyodev.fetch2:fetch2:2.3.6"
|
||||||
|
implementation 'com.github.stom79:horizontalbargraph:1.3'
|
||||||
playstoreImplementation "io.github.kobakei:ratethisapp:$ratethisappLibraryVersion"
|
playstoreImplementation "io.github.kobakei:ratethisapp:$ratethisappLibraryVersion"
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@ import android.widget.ListView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.TimePicker;
|
import android.widget.TimePicker;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
@ -124,6 +125,8 @@ import fr.gouv.etalab.mastodon.client.Entities.Emojis;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Error;
|
import fr.gouv.etalab.mastodon.client.Entities.Error;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Mention;
|
import fr.gouv.etalab.mastodon.client.Entities.Mention;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Poll;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.PollOptions;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Results;
|
import fr.gouv.etalab.mastodon.client.Entities.Results;
|
||||||
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;
|
||||||
|
@ -217,6 +220,7 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
|
||||||
private String contentType;
|
private String contentType;
|
||||||
private int max_media_count;
|
private int max_media_count;
|
||||||
public static HashMap<String, Uri> filesMap;
|
public static HashMap<String, Uri> filesMap;
|
||||||
|
private Poll poll;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
@ -1050,29 +1054,152 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
|
||||||
case R.id.action_poll:
|
case R.id.action_poll:
|
||||||
AlertDialog.Builder alertPoll = new AlertDialog.Builder(TootActivity.this, style);
|
AlertDialog.Builder alertPoll = new AlertDialog.Builder(TootActivity.this, style);
|
||||||
alertPoll.setTitle(R.string.create_poll);
|
alertPoll.setTitle(R.string.create_poll);
|
||||||
|
View view = getLayoutInflater().inflate(R.layout.popup_poll, null);
|
||||||
|
alertPoll.setView(view);
|
||||||
|
Spinner poll_choice = view.findViewById(R.id.poll_choice);
|
||||||
|
Spinner poll_duration = view.findViewById(R.id.poll_duration);
|
||||||
|
EditText choice_1 = view.findViewById(R.id.choice_1);
|
||||||
|
EditText choice_2 = view.findViewById(R.id.choice_2);
|
||||||
|
EditText choice_3 = view.findViewById(R.id.choice_3);
|
||||||
|
EditText choice_4 = view.findViewById(R.id.choice_4);
|
||||||
|
ArrayAdapter<CharSequence> pollduration = ArrayAdapter.createFromResource(TootActivity.this,
|
||||||
|
R.array.poll_duration, android.R.layout.simple_spinner_item);
|
||||||
|
|
||||||
alert.setView(input);
|
ArrayAdapter<CharSequence> pollchoice = ArrayAdapter.createFromResource(TootActivity.this,
|
||||||
String content = tootReply.getContent();
|
R.array.poll_choice_type, android.R.layout.simple_spinner_item);
|
||||||
if(tootReply.getReblog() != null)
|
poll_choice.setAdapter(pollchoice);
|
||||||
content = tootReply.getReblog().getContent();
|
poll_duration.setAdapter(pollduration);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
poll_duration.setSelection(4);
|
||||||
input.setText(Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY));
|
poll_choice.setSelection(0);
|
||||||
else
|
if( poll != null){
|
||||||
//noinspection deprecation
|
int i = 1;
|
||||||
input.setText(Html.fromHtml(content));
|
for(PollOptions pollOptions: poll.getOptionsList()){
|
||||||
alert.setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
|
switch (i){
|
||||||
|
case 1:
|
||||||
|
if( pollOptions.getTitle() != null)
|
||||||
|
choice_1.setText(pollOptions.getTitle());
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if( pollOptions.getTitle() != null)
|
||||||
|
choice_2.setText(pollOptions.getTitle());
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if( pollOptions.getTitle() != null)
|
||||||
|
choice_3.setText(pollOptions.getTitle());
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if( pollOptions.getTitle() != null)
|
||||||
|
choice_4.setText(pollOptions.getTitle());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
switch (poll.getExpires_in()){
|
||||||
|
case 300:
|
||||||
|
poll_duration.setSelection(0);
|
||||||
|
break;
|
||||||
|
case 1800:
|
||||||
|
poll_duration.setSelection(1);
|
||||||
|
break;
|
||||||
|
case 3600:
|
||||||
|
poll_duration.setSelection(2);
|
||||||
|
break;
|
||||||
|
case 21600:
|
||||||
|
poll_duration.setSelection(3);
|
||||||
|
break;
|
||||||
|
case 86400:
|
||||||
|
poll_duration.setSelection(4);
|
||||||
|
break;
|
||||||
|
case 259200:
|
||||||
|
poll_duration.setSelection(5);
|
||||||
|
break;
|
||||||
|
case 604800:
|
||||||
|
poll_duration.setSelection(6);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if( poll.isMultiple())
|
||||||
|
poll_choice.setSelection(1);
|
||||||
|
else
|
||||||
|
poll_choice.setSelection(0);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
alertPoll.setNeutralButton(R.string.delete, new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
|
if( poll != null)
|
||||||
|
poll = null;
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
alert.setNegativeButton(R.string.accounts, new DialogInterface.OnClickListener() {
|
|
||||||
|
alertPoll.setPositiveButton(R.string.done, new DialogInterface.OnClickListener() {
|
||||||
public void onClick(DialogInterface dialog, int whichButton) {
|
public void onClick(DialogInterface dialog, int whichButton) {
|
||||||
new RetrieveAccountsForReplyAsyncTask(getApplicationContext(), tootReply.getReblog() != null?tootReply.getReblog():tootReply, TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
int poll_duration_pos = poll_duration.getSelectedItemPosition();
|
||||||
dialog.dismiss();
|
|
||||||
|
int poll_choice_pos = poll_choice.getSelectedItemPosition();
|
||||||
|
String choice1 = choice_1.getText().toString().trim();
|
||||||
|
String choice2 = choice_2.getText().toString().trim();
|
||||||
|
String choice3 = choice_3.getText().toString().trim();
|
||||||
|
String choice4 = choice_4.getText().toString().trim();
|
||||||
|
|
||||||
|
if( choice1.isEmpty() && choice2.isEmpty()){
|
||||||
|
Toasty.error(getApplicationContext(), getString(R.string.poll_invalid_choices), Toast.LENGTH_SHORT).show();
|
||||||
|
}else{
|
||||||
|
poll = new Poll();
|
||||||
|
poll.setMultiple(poll_choice_pos != 0);
|
||||||
|
int expire = 0;
|
||||||
|
switch (poll_duration_pos){
|
||||||
|
case 0:
|
||||||
|
expire = 300;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
expire = 1800;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
expire = 3600;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
expire = 21600;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
expire = 86400;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
expire = 259200;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
expire = 604800;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
expire = 864000;
|
||||||
|
}
|
||||||
|
poll.setExpires_in(expire);
|
||||||
|
|
||||||
|
List<PollOptions> pollOptions = new ArrayList<>();
|
||||||
|
PollOptions pollOption1 = new PollOptions();
|
||||||
|
pollOption1.setTitle(choice1);
|
||||||
|
pollOptions.add(pollOption1);
|
||||||
|
|
||||||
|
PollOptions pollOption2 = new PollOptions();
|
||||||
|
pollOption2.setTitle(choice2);
|
||||||
|
pollOptions.add(pollOption2);
|
||||||
|
|
||||||
|
PollOptions pollOption3 = new PollOptions();
|
||||||
|
pollOption3.setTitle(choice3);
|
||||||
|
pollOptions.add(pollOption3);
|
||||||
|
|
||||||
|
PollOptions pollOption4 = new PollOptions();
|
||||||
|
pollOption4.setTitle(choice4);
|
||||||
|
pollOptions.add(pollOption4);
|
||||||
|
poll.setOptionsList(pollOptions);
|
||||||
|
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
alert.show();
|
alertPoll.show();
|
||||||
return true;
|
return false;
|
||||||
case R.id.action_translate:
|
case R.id.action_translate:
|
||||||
final CountryPicker picker = CountryPicker.newInstance(getString(R.string.which_language)); // dialog title
|
final CountryPicker picker = CountryPicker.newInstance(getString(R.string.which_language)); // dialog title
|
||||||
if( theme == Helper.THEME_LIGHT){
|
if( theme == Helper.THEME_LIGHT){
|
||||||
|
@ -1548,6 +1675,8 @@ public class TootActivity extends BaseActivity implements OnPostActionInterface,
|
||||||
if( tootReply != null)
|
if( tootReply != null)
|
||||||
toot.setIn_reply_to_id(tootReply.getId());
|
toot.setIn_reply_to_id(tootReply.getId());
|
||||||
toot.setContent(tootContent);
|
toot.setContent(tootContent);
|
||||||
|
if( poll != null)
|
||||||
|
toot.setPoll(poll);
|
||||||
if( timestamp == null)
|
if( timestamp == null)
|
||||||
if( scheduledstatus == null)
|
if( scheduledstatus == null)
|
||||||
new PostStatusAsyncTask(getApplicationContext(), accountReply, toot, TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
new PostStatusAsyncTask(getApplicationContext(), accountReply, toot, TootActivity.this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||||
|
|
|
@ -20,6 +20,10 @@ import android.content.SharedPreferences;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v4.content.LocalBroadcastManager;
|
import android.support.v4.content.LocalBroadcastManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
@ -31,6 +35,7 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.security.KeyManagementException;
|
import java.security.KeyManagementException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.text.Format;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -61,6 +66,8 @@ import fr.gouv.etalab.mastodon.client.Entities.Mention;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.NodeInfo;
|
import fr.gouv.etalab.mastodon.client.Entities.NodeInfo;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Peertube;
|
import fr.gouv.etalab.mastodon.client.Entities.Peertube;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Poll;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.PollOptions;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Relationship;
|
import fr.gouv.etalab.mastodon.client.Entities.Relationship;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Results;
|
import fr.gouv.etalab.mastodon.client.Entities.Results;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Schedule;
|
import fr.gouv.etalab.mastodon.client.Entities.Schedule;
|
||||||
|
@ -436,6 +443,7 @@ public class API {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a relationship between the authenticated account and an account
|
* Returns a relationship between the authenticated account and an account
|
||||||
* @param accounts ArrayList<Account> accounts fetched
|
* @param accounts ArrayList<Account> accounts fetched
|
||||||
|
@ -2088,6 +2096,38 @@ public class API {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Public api call to submit a vote
|
||||||
|
* @param pollId
|
||||||
|
* @param choices
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Poll submiteVote(String pollId, int[] choices){
|
||||||
|
JsonObject jsonObject = new JsonObject();
|
||||||
|
JsonArray jchoices = new JsonArray();
|
||||||
|
for(int choice : choices){
|
||||||
|
jchoices.add(choice);
|
||||||
|
}
|
||||||
|
jsonObject.add("choices",jchoices);
|
||||||
|
try {
|
||||||
|
HttpsConnection httpsConnection = new HttpsConnection(context);
|
||||||
|
String response = httpsConnection.postJson(getAbsoluteUrl(String.format("/polls/%s/votes", pollId)), 60, jsonObject, prefKeyOauthTokenT);
|
||||||
|
return parsePoll(context, new JSONObject(response));
|
||||||
|
} catch (HttpsConnection.HttpsConnectionException e) {
|
||||||
|
setError(e.getStatusCode(), e);
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (KeyManagementException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posts a status
|
* Posts a status
|
||||||
|
@ -2096,38 +2136,41 @@ public class API {
|
||||||
*/
|
*/
|
||||||
public APIResponse postStatusAction(Status status){
|
public APIResponse postStatusAction(Status status){
|
||||||
|
|
||||||
HashMap<String, String> params = new HashMap<>();
|
JsonObject jsonObject = new JsonObject();
|
||||||
try {
|
jsonObject.addProperty("status", status.getContent());
|
||||||
params.put("status", URLEncoder.encode(status.getContent(), "UTF-8"));
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
params.put("status", status.getContent());
|
|
||||||
}
|
|
||||||
if( status.getContentType() != null)
|
if( status.getContentType() != null)
|
||||||
params.put("content_type", status.getContentType());
|
jsonObject.addProperty("content_type", status.getContentType());
|
||||||
if( status.getIn_reply_to_id() != null)
|
if( status.getIn_reply_to_id() != null)
|
||||||
params.put("in_reply_to_id", status.getIn_reply_to_id());
|
jsonObject.addProperty("in_reply_to_id", status.getIn_reply_to_id());
|
||||||
if( status.getMedia_attachments() != null && status.getMedia_attachments().size() > 0 ) {
|
if( status.getMedia_attachments() != null && status.getMedia_attachments().size() > 0 ) {
|
||||||
StringBuilder parameters = new StringBuilder();
|
JsonArray mediaArray = new JsonArray();
|
||||||
for(Attachment attachment: status.getMedia_attachments())
|
for(Attachment attachment: status.getMedia_attachments())
|
||||||
parameters.append("media_ids[]=").append(attachment.getId()).append("&");
|
mediaArray.add(attachment.getId());
|
||||||
parameters = new StringBuilder(parameters.substring(0, parameters.length() - 1).substring(12));
|
jsonObject.add("media_ids", mediaArray);
|
||||||
params.put("media_ids[]", parameters.toString());
|
|
||||||
}
|
}
|
||||||
if( status.getScheduled_at() != null)
|
if( status.getScheduled_at() != null)
|
||||||
params.put("scheduled_at", status.getScheduled_at());
|
jsonObject.addProperty("scheduled_at", status.getScheduled_at());
|
||||||
if( status.isSensitive())
|
if( status.isSensitive())
|
||||||
params.put("sensitive", Boolean.toString(status.isSensitive()));
|
jsonObject.addProperty("sensitive", Boolean.toString(status.isSensitive()));
|
||||||
if( status.getSpoiler_text() != null)
|
if( status.getSpoiler_text() != null)
|
||||||
try {
|
jsonObject.addProperty("spoiler_text", status.getSpoiler_text());
|
||||||
params.put("spoiler_text", URLEncoder.encode(status.getSpoiler_text(), "UTF-8"));
|
if( status.getPoll() != null){
|
||||||
} catch (UnsupportedEncodingException e) {
|
JsonObject poll = new JsonObject();
|
||||||
params.put("spoiler_text", status.getSpoiler_text());
|
JsonArray options = new JsonArray();
|
||||||
|
for(PollOptions option: status.getPoll().getOptionsList()){
|
||||||
|
if( !option.getTitle().isEmpty())
|
||||||
|
options.add(option.getTitle());
|
||||||
}
|
}
|
||||||
params.put("visibility", status.getVisibility());
|
poll.add("options",options);
|
||||||
|
poll.addProperty("expires_in",status.getPoll().getExpires_in());
|
||||||
|
poll.addProperty("multiple",status.getPoll().isMultiple());
|
||||||
|
jsonObject.add("poll", poll);
|
||||||
|
}
|
||||||
|
jsonObject.addProperty("visibility", status.getVisibility());
|
||||||
statuses = new ArrayList<>();
|
statuses = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
HttpsConnection httpsConnection = new HttpsConnection(context);
|
HttpsConnection httpsConnection = new HttpsConnection(context);
|
||||||
String response = httpsConnection.post(getAbsoluteUrl("/statuses"), 60, params, prefKeyOauthTokenT);
|
String response = httpsConnection.postJson(getAbsoluteUrl("/statuses"), 60, jsonObject, prefKeyOauthTokenT);
|
||||||
apiResponse.setSince_id(httpsConnection.getSince_id());
|
apiResponse.setSince_id(httpsConnection.getSince_id());
|
||||||
apiResponse.setMax_id(httpsConnection.getMax_id());
|
apiResponse.setMax_id(httpsConnection.getMax_id());
|
||||||
Status statusreturned = parseStatuses(context, new JSONObject(response));
|
Status statusreturned = parseStatuses(context, new JSONObject(response));
|
||||||
|
@ -3502,6 +3545,40 @@ public class API {
|
||||||
return statuses;
|
return statuses;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a poll
|
||||||
|
* @param context
|
||||||
|
* @param resobj
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static Poll parsePoll(Context context, JSONObject resobj){
|
||||||
|
Poll poll = new Poll();
|
||||||
|
try {
|
||||||
|
poll.setId(resobj.getString("id"));
|
||||||
|
poll.setExpires_at(Helper.mstStringToDate(context, resobj.getString("expires_at")));
|
||||||
|
poll.setExpired(resobj.getBoolean("expired"));
|
||||||
|
poll.setMultiple(resobj.getBoolean("multiple"));
|
||||||
|
poll.setVotes_count(resobj.getInt("votes_count"));
|
||||||
|
poll.setVoted(resobj.getBoolean("voted"));
|
||||||
|
JSONArray options = resobj.getJSONArray("options");
|
||||||
|
List<PollOptions> pollOptions = new ArrayList<>();
|
||||||
|
for(int i = 0; i < options.length() ; i++){
|
||||||
|
JSONObject option = options.getJSONObject(i);
|
||||||
|
PollOptions pollOption = new PollOptions();
|
||||||
|
pollOption.setTitle(option.getString("title"));
|
||||||
|
pollOption.setVotes_count(option.getInt("votes_count"));
|
||||||
|
pollOptions.add(pollOption);
|
||||||
|
}
|
||||||
|
poll.setOptionsList(pollOptions);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return poll;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse json response for unique status
|
* Parse json response for unique status
|
||||||
* @param resobj JSONObject
|
* @param resobj JSONObject
|
||||||
|
@ -3544,6 +3621,26 @@ public class API {
|
||||||
attachments.add(attachment);
|
attachments.add(attachment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if( resobj.has("poll") && !resobj.isNull("poll")){
|
||||||
|
Poll poll = new Poll();
|
||||||
|
poll.setId(resobj.getJSONObject("poll").getString("id"));
|
||||||
|
poll.setExpires_at(Helper.mstStringToDate(context, resobj.getJSONObject("poll").getString("expires_at")));
|
||||||
|
poll.setExpired(resobj.getJSONObject("poll").getBoolean("expired"));
|
||||||
|
poll.setMultiple(resobj.getJSONObject("poll").getBoolean("multiple"));
|
||||||
|
poll.setVotes_count(resobj.getJSONObject("poll").getInt("votes_count"));
|
||||||
|
poll.setVoted(resobj.getJSONObject("poll").getBoolean("voted"));
|
||||||
|
JSONArray options = resobj.getJSONObject("poll").getJSONArray("options");
|
||||||
|
List<PollOptions> pollOptions = new ArrayList<>();
|
||||||
|
for(int i = 0; i < options.length() ; i++){
|
||||||
|
JSONObject option = options.getJSONObject(i);
|
||||||
|
PollOptions pollOption = new PollOptions();
|
||||||
|
pollOption.setTitle(option.getString("title"));
|
||||||
|
pollOption.setVotes_count(option.getInt("votes_count"));
|
||||||
|
pollOptions.add(pollOption);
|
||||||
|
}
|
||||||
|
poll.setOptionsList(pollOptions);
|
||||||
|
status.setPoll(poll);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
status.setCard(parseCardResponse(resobj.getJSONObject("card")));
|
status.setCard(parseCardResponse(resobj.getJSONObject("card")));
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
* see <http://www.gnu.org/licenses>. */
|
* see <http://www.gnu.org/licenses>. */
|
||||||
package fr.gouv.etalab.mastodon.client.Entities;
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
|
||||||
|
|
||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -25,12 +25,24 @@ public class Poll implements Parcelable {
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private Date expires_at;
|
private Date expires_at;
|
||||||
|
private int expires_in;
|
||||||
private boolean expired;
|
private boolean expired;
|
||||||
private boolean multiple;
|
private boolean multiple;
|
||||||
private int votes_count;
|
private int votes_count;
|
||||||
private boolean voted;
|
private boolean voted;
|
||||||
private List<PollOptions> optionsList;
|
private List<PollOptions> optionsList;
|
||||||
|
|
||||||
|
public Poll() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
public Date getExpires_at() {
|
public Date getExpires_at() {
|
||||||
return expires_at;
|
return expires_at;
|
||||||
}
|
}
|
||||||
|
@ -79,28 +91,15 @@ public class Poll implements Parcelable {
|
||||||
this.optionsList = optionsList;
|
this.optionsList = optionsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getExpires_in() {
|
||||||
private class PollOptions{
|
return expires_in;
|
||||||
private String title;
|
|
||||||
private String votes_count;
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVotes_count() {
|
|
||||||
return votes_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVotes_count(String votes_count) {
|
|
||||||
this.votes_count = votes_count;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setExpires_in(int expires_in) {
|
||||||
|
this.expires_in = expires_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -110,26 +109,24 @@ public class Poll implements Parcelable {
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeString(this.id);
|
dest.writeString(this.id);
|
||||||
dest.writeLong(this.expires_at != null ? this.expires_at.getTime() : -1);
|
dest.writeLong(this.expires_at != null ? this.expires_at.getTime() : -1);
|
||||||
|
dest.writeInt(this.expires_in);
|
||||||
dest.writeByte(this.expired ? (byte) 1 : (byte) 0);
|
dest.writeByte(this.expired ? (byte) 1 : (byte) 0);
|
||||||
dest.writeByte(this.multiple ? (byte) 1 : (byte) 0);
|
dest.writeByte(this.multiple ? (byte) 1 : (byte) 0);
|
||||||
dest.writeInt(this.votes_count);
|
dest.writeInt(this.votes_count);
|
||||||
dest.writeByte(this.voted ? (byte) 1 : (byte) 0);
|
dest.writeByte(this.voted ? (byte) 1 : (byte) 0);
|
||||||
dest.writeList(this.optionsList);
|
dest.writeTypedList(this.optionsList);
|
||||||
}
|
|
||||||
|
|
||||||
public Poll() {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Poll(Parcel in) {
|
protected Poll(Parcel in) {
|
||||||
this.id = in.readString();
|
this.id = in.readString();
|
||||||
long tmpExpires_at = in.readLong();
|
long tmpExpires_at = in.readLong();
|
||||||
this.expires_at = tmpExpires_at == -1 ? null : new Date(tmpExpires_at);
|
this.expires_at = tmpExpires_at == -1 ? null : new Date(tmpExpires_at);
|
||||||
|
this.expires_in = in.readInt();
|
||||||
this.expired = in.readByte() != 0;
|
this.expired = in.readByte() != 0;
|
||||||
this.multiple = in.readByte() != 0;
|
this.multiple = in.readByte() != 0;
|
||||||
this.votes_count = in.readInt();
|
this.votes_count = in.readInt();
|
||||||
this.voted = in.readByte() != 0;
|
this.voted = in.readByte() != 0;
|
||||||
this.optionsList = new ArrayList<PollOptions>();
|
this.optionsList = in.createTypedArrayList(PollOptions.CREATOR);
|
||||||
in.readList(this.optionsList, PollOptions.class.getClassLoader());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Parcelable.Creator<Poll> CREATOR = new Parcelable.Creator<Poll>() {
|
public static final Parcelable.Creator<Poll> CREATOR = new Parcelable.Creator<Poll>() {
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
package fr.gouv.etalab.mastodon.client.Entities;
|
||||||
|
/* Copyright 2019 Thomas Schneider
|
||||||
|
*
|
||||||
|
* This file is a part of Mastalab
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Mastalab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Mastalab; if not,
|
||||||
|
* see <http://www.gnu.org/licenses>. */
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
|
||||||
|
public class PollOptions implements Parcelable {
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVotes_count() {
|
||||||
|
return votes_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVotes_count(int votes_count) {
|
||||||
|
this.votes_count = votes_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
private int votes_count;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
dest.writeString(this.title);
|
||||||
|
dest.writeInt(this.votes_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PollOptions() {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PollOptions(Parcel in) {
|
||||||
|
this.title = in.readString();
|
||||||
|
this.votes_count = in.readInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final Creator<PollOptions> CREATOR = new Creator<PollOptions>() {
|
||||||
|
@Override
|
||||||
|
public PollOptions createFromParcel(Parcel source) {
|
||||||
|
return new PollOptions(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PollOptions[] newArray(int size) {
|
||||||
|
return new PollOptions[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
|
@ -132,6 +132,7 @@ public class Status implements Parcelable{
|
||||||
private String scheduled_at;
|
private String scheduled_at;
|
||||||
private String contentType;
|
private String contentType;
|
||||||
private boolean isNotice = false;
|
private boolean isNotice = false;
|
||||||
|
private Poll poll = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
|
@ -188,6 +189,7 @@ public class Status implements Parcelable{
|
||||||
dest.writeString(this.contentType);
|
dest.writeString(this.contentType);
|
||||||
dest.writeByte(this.showSpoiler ? (byte) 1 : (byte) 0);
|
dest.writeByte(this.showSpoiler ? (byte) 1 : (byte) 0);
|
||||||
dest.writeByte(this.isNotice ? (byte) 1 : (byte) 0);
|
dest.writeByte(this.isNotice ? (byte) 1 : (byte) 0);
|
||||||
|
dest.writeParcelable(this.poll, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Status(Parcel in) {
|
protected Status(Parcel in) {
|
||||||
|
@ -246,6 +248,7 @@ public class Status implements Parcelable{
|
||||||
this.contentType = in.readString();
|
this.contentType = in.readString();
|
||||||
this.showSpoiler = in.readByte() != 0;
|
this.showSpoiler = in.readByte() != 0;
|
||||||
this.isNotice = in.readByte() != 0;
|
this.isNotice = in.readByte() != 0;
|
||||||
|
this.poll = in.readParcelable(Poll.class.getClassLoader());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Creator<Status> CREATOR = new Creator<Status>() {
|
public static final Creator<Status> CREATOR = new Creator<Status>() {
|
||||||
|
@ -1331,4 +1334,12 @@ public class Status implements Parcelable{
|
||||||
public void setNotice(boolean notice) {
|
public void setNotice(boolean notice) {
|
||||||
isNotice = notice;
|
isNotice = notice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Poll getPoll() {
|
||||||
|
return poll;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPoll(Poll poll) {
|
||||||
|
this.poll = poll;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,10 @@ import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.SpannableString;
|
import android.text.SpannableString;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
@ -42,6 +44,7 @@ import java.net.InetSocketAddress;
|
||||||
import java.net.PasswordAuthentication;
|
import java.net.PasswordAuthentication;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.KeyManagementException;
|
import java.security.KeyManagementException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -325,7 +328,7 @@ public class HttpsConnection {
|
||||||
postData.append(String.valueOf(param.getValue()));
|
postData.append(String.valueOf(param.getValue()));
|
||||||
}
|
}
|
||||||
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
|
byte[] postDataBytes = postData.toString().getBytes("UTF-8");
|
||||||
|
Log.v(Helper.TAG,"postData! " + postData);
|
||||||
if (proxy != null)
|
if (proxy != null)
|
||||||
httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy);
|
httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy);
|
||||||
else
|
else
|
||||||
|
@ -426,6 +429,99 @@ public class HttpsConnection {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String postJson(String urlConnection, int timeout, JsonObject jsonObject, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException {
|
||||||
|
if( urlConnection.startsWith("https://")) {
|
||||||
|
URL url = new URL(urlConnection);
|
||||||
|
Log.v(Helper.TAG,"--> " +jsonObject);
|
||||||
|
byte[] postDataBytes = new byte[0];
|
||||||
|
postDataBytes = jsonObject.toString().getBytes("UTF-8");
|
||||||
|
if (proxy != null)
|
||||||
|
httpsURLConnection = (HttpsURLConnection) url.openConnection(proxy);
|
||||||
|
else
|
||||||
|
httpsURLConnection = (HttpsURLConnection) url.openConnection();
|
||||||
|
httpsURLConnection.setRequestProperty("User-Agent", Helper.USER_AGENT);
|
||||||
|
httpsURLConnection.setConnectTimeout(timeout * 1000);
|
||||||
|
httpsURLConnection.setDoOutput(true);
|
||||||
|
httpsURLConnection.setSSLSocketFactory(new TLSSocketFactory());
|
||||||
|
httpsURLConnection.setRequestProperty("Content-Type", "application/json");
|
||||||
|
httpsURLConnection.setRequestProperty("Accept", "application/json");
|
||||||
|
httpsURLConnection.setRequestMethod("POST");
|
||||||
|
if (token != null && !token.startsWith("Basic "))
|
||||||
|
httpsURLConnection.setRequestProperty("Authorization", "Bearer " + token);
|
||||||
|
else if( token != null && token.startsWith("Basic "))
|
||||||
|
httpsURLConnection.setRequestProperty("Authorization", token);
|
||||||
|
httpsURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
|
||||||
|
|
||||||
|
|
||||||
|
httpsURLConnection.getOutputStream().write(postDataBytes);
|
||||||
|
String response;
|
||||||
|
if (httpsURLConnection.getResponseCode() >= 200 && httpsURLConnection.getResponseCode() < 400) {
|
||||||
|
getSinceMaxId();
|
||||||
|
response = converToString(httpsURLConnection.getInputStream());
|
||||||
|
} else {
|
||||||
|
String error = null;
|
||||||
|
if( httpsURLConnection.getErrorStream() != null) {
|
||||||
|
InputStream stream = httpsURLConnection.getErrorStream();
|
||||||
|
if (stream == null) {
|
||||||
|
stream = httpsURLConnection.getInputStream();
|
||||||
|
}
|
||||||
|
try (Scanner scanner = new Scanner(stream)) {
|
||||||
|
scanner.useDelimiter("\\Z");
|
||||||
|
error = scanner.next();
|
||||||
|
}catch (Exception e){e.printStackTrace();}
|
||||||
|
}
|
||||||
|
int responseCode = httpsURLConnection.getResponseCode();
|
||||||
|
throw new HttpsConnectionException(responseCode, error);
|
||||||
|
}
|
||||||
|
getSinceMaxId();
|
||||||
|
httpsURLConnection.getInputStream().close();
|
||||||
|
return response;
|
||||||
|
}else {
|
||||||
|
URL url = new URL(urlConnection);
|
||||||
|
byte[] postDataBytes = jsonObject.toString().getBytes("UTF-8");
|
||||||
|
|
||||||
|
if (proxy != null)
|
||||||
|
httpURLConnection = (HttpURLConnection) url.openConnection(proxy);
|
||||||
|
else
|
||||||
|
httpURLConnection = (HttpURLConnection) url.openConnection();
|
||||||
|
httpURLConnection.setRequestProperty("User-Agent", Helper.USER_AGENT);
|
||||||
|
httpURLConnection.setConnectTimeout(timeout * 1000);
|
||||||
|
httpURLConnection.setDoOutput(true);
|
||||||
|
httpURLConnection.setRequestMethod("POST");
|
||||||
|
if (token != null && !token.startsWith("Basic "))
|
||||||
|
httpURLConnection.setRequestProperty("Authorization", "Bearer " + token);
|
||||||
|
else if( token != null && token.startsWith("Basic "))
|
||||||
|
httpURLConnection.setRequestProperty("Authorization", token);
|
||||||
|
httpURLConnection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
|
||||||
|
|
||||||
|
httpURLConnection.getOutputStream().write(postDataBytes);
|
||||||
|
String response;
|
||||||
|
if (httpURLConnection.getResponseCode() >= 200 && httpURLConnection.getResponseCode() < 400) {
|
||||||
|
getSinceMaxId();
|
||||||
|
response = converToString(httpURLConnection.getInputStream());
|
||||||
|
} else {
|
||||||
|
String error = null;
|
||||||
|
if( httpURLConnection.getErrorStream() != null) {
|
||||||
|
InputStream stream = httpURLConnection.getErrorStream();
|
||||||
|
if (stream == null) {
|
||||||
|
stream = httpURLConnection.getInputStream();
|
||||||
|
}
|
||||||
|
try (Scanner scanner = new Scanner(stream)) {
|
||||||
|
scanner.useDelimiter("\\Z");
|
||||||
|
error = scanner.next();
|
||||||
|
}catch (Exception e){e.printStackTrace();}
|
||||||
|
}
|
||||||
|
int responseCode = httpURLConnection.getResponseCode();
|
||||||
|
throw new HttpsConnectionException(responseCode, error);
|
||||||
|
}
|
||||||
|
getSinceMaxId();
|
||||||
|
httpURLConnection.getInputStream().close();
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public String postMisskey(String urlConnection, int timeout, JSONObject paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException {
|
public String postMisskey(String urlConnection, int timeout, JSONObject paramaters, String token) throws IOException, NoSuchAlgorithmException, KeyManagementException, HttpsConnectionException {
|
||||||
URL url = new URL(urlConnection);
|
URL url = new URL(urlConnection);
|
||||||
byte[] postDataBytes = paramaters.toString().getBytes("UTF-8");
|
byte[] postDataBytes = paramaters.toString().getBytes("UTF-8");
|
||||||
|
|
|
@ -24,6 +24,7 @@ import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
@ -46,6 +47,7 @@ import android.text.method.LinkMovementMethod;
|
||||||
import android.text.style.ClickableSpan;
|
import android.text.style.ClickableSpan;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.text.style.URLSpan;
|
import android.text.style.URLSpan;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
@ -55,12 +57,15 @@ import android.view.ViewGroup;
|
||||||
import android.webkit.WebView;
|
import android.webkit.WebView;
|
||||||
import android.webkit.WebViewClient;
|
import android.webkit.WebViewClient;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.CheckBox;
|
||||||
import android.widget.DatePicker;
|
import android.widget.DatePicker;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.FrameLayout;
|
import android.widget.FrameLayout;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
import android.widget.RadioGroup;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.TimePicker;
|
import android.widget.TimePicker;
|
||||||
|
@ -90,6 +95,8 @@ import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import br.com.felix.horizontalbargraph.HorizontalBar;
|
||||||
|
import br.com.felix.horizontalbargraph.model.BarItem;
|
||||||
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.BaseMainActivity;
|
import fr.gouv.etalab.mastodon.activities.BaseMainActivity;
|
||||||
|
@ -113,6 +120,8 @@ import fr.gouv.etalab.mastodon.client.Entities.Card;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Emojis;
|
import fr.gouv.etalab.mastodon.client.Entities.Emojis;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Error;
|
import fr.gouv.etalab.mastodon.client.Entities.Error;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
import fr.gouv.etalab.mastodon.client.Entities.Notification;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.Poll;
|
||||||
|
import fr.gouv.etalab.mastodon.client.Entities.PollOptions;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
import fr.gouv.etalab.mastodon.client.Entities.Status;
|
||||||
import fr.gouv.etalab.mastodon.client.Entities.TagTimeline;
|
import fr.gouv.etalab.mastodon.client.Entities.TagTimeline;
|
||||||
import fr.gouv.etalab.mastodon.fragments.DisplayStatusFragment;
|
import fr.gouv.etalab.mastodon.fragments.DisplayStatusFragment;
|
||||||
|
@ -328,6 +337,16 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
||||||
LinearLayout status_peertube_container;
|
LinearLayout status_peertube_container;
|
||||||
TextView status_peertube_reply, status_peertube_delete;
|
TextView status_peertube_reply, status_peertube_delete;
|
||||||
|
|
||||||
|
|
||||||
|
//Poll
|
||||||
|
LinearLayout poll_container, single_choice, multiple_choice, rated;
|
||||||
|
RadioGroup radio_group;
|
||||||
|
RadioButton r_choice_1, r_choice_2, r_choice_3, r_choice_4;
|
||||||
|
CheckBox c_choice_1, c_choice_2, c_choice_3, c_choice_4;
|
||||||
|
HorizontalBar choices;
|
||||||
|
TextView number_votes, remaining_time;
|
||||||
|
Button submit_vote;
|
||||||
|
|
||||||
public View getView(){
|
public View getView(){
|
||||||
return itemView;
|
return itemView;
|
||||||
}
|
}
|
||||||
|
@ -416,6 +435,23 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
||||||
status_peertube_reply = itemView.findViewById(R.id.status_peertube_reply);
|
status_peertube_reply = itemView.findViewById(R.id.status_peertube_reply);
|
||||||
status_peertube_delete = itemView.findViewById(R.id.status_peertube_delete);
|
status_peertube_delete = itemView.findViewById(R.id.status_peertube_delete);
|
||||||
|
|
||||||
|
poll_container = itemView.findViewById(R.id.poll_container);
|
||||||
|
single_choice = itemView.findViewById(R.id.single_choice);
|
||||||
|
multiple_choice = itemView.findViewById(R.id.multiple_choice);
|
||||||
|
rated = itemView.findViewById(R.id.rated);
|
||||||
|
radio_group = itemView.findViewById(R.id.radio_group);
|
||||||
|
r_choice_1 = itemView.findViewById(R.id.r_choice_1);
|
||||||
|
r_choice_2 = itemView.findViewById(R.id.r_choice_2);
|
||||||
|
r_choice_3 = itemView.findViewById(R.id.r_choice_3);
|
||||||
|
r_choice_4 = itemView.findViewById(R.id.r_choice_4);
|
||||||
|
c_choice_1 = itemView.findViewById(R.id.c_choice_1);
|
||||||
|
c_choice_2 = itemView.findViewById(R.id.c_choice_2);
|
||||||
|
c_choice_3 = itemView.findViewById(R.id.c_choice_3);
|
||||||
|
c_choice_4 = itemView.findViewById(R.id.c_choice_4);
|
||||||
|
choices = itemView.findViewById(R.id.choices);
|
||||||
|
number_votes = itemView.findViewById(R.id.number_votes);
|
||||||
|
remaining_time = itemView.findViewById(R.id.remaining_time);
|
||||||
|
submit_vote = itemView.findViewById(R.id.submit_vote);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,7 +542,91 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
|
||||||
|
|
||||||
holder.status_reply.setText("");
|
holder.status_reply.setText("");
|
||||||
//Display a preview for accounts that have replied *if enabled and only for home timeline*
|
//Display a preview for accounts that have replied *if enabled and only for home timeline*
|
||||||
|
if (social == UpdateAccountInfoAsyncTask.SOCIAL.MASTODON) {
|
||||||
|
holder.rated.setVisibility(View.GONE);
|
||||||
|
holder.multiple_choice.setVisibility(View.GONE);
|
||||||
|
holder.single_choice.setVisibility(View.GONE);
|
||||||
|
holder.submit_vote.setVisibility(View.GONE);
|
||||||
|
if( status.getPoll() != null){
|
||||||
|
Poll poll = status.getPoll();
|
||||||
|
int choiceCount = status.getPoll().getOptionsList().size();
|
||||||
|
if( poll.isVoted()){
|
||||||
|
holder.rated.setVisibility(View.VISIBLE);
|
||||||
|
List<BarItem> items = new ArrayList<>();
|
||||||
|
int greaterValue = 0;
|
||||||
|
for(PollOptions pollOption: status.getPoll().getOptionsList()){
|
||||||
|
if( pollOption.getVotes_count() > greaterValue)
|
||||||
|
greaterValue = pollOption.getVotes_count();
|
||||||
|
}
|
||||||
|
for(PollOptions pollOption: status.getPoll().getOptionsList()){
|
||||||
|
double value = ((double)(pollOption.getVotes_count()* 100) / (double)poll.getVotes_count()) ;
|
||||||
|
if( pollOption.getVotes_count() == greaterValue) {
|
||||||
|
BarItem bar = new BarItem(pollOption.getTitle(), value, "%", ContextCompat.getColor(context, R.color.mastodonC4), Color.WHITE);
|
||||||
|
bar.setRounded(true);
|
||||||
|
bar.setHeight1(30);
|
||||||
|
items.add(bar);
|
||||||
|
}else {
|
||||||
|
BarItem bar = new BarItem(pollOption.getTitle(), value, "%", ContextCompat.getColor(context, R.color.mastodonC2), Color.WHITE);
|
||||||
|
bar.setRounded(true);
|
||||||
|
bar.setHeight1(30);
|
||||||
|
items.add(bar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
holder.choices.init(context).hasAnimation(true).addAll(items).build();
|
||||||
|
}else {
|
||||||
|
if( poll.isMultiple()){
|
||||||
|
Log.v(Helper.TAG,"count: " + choiceCount);
|
||||||
|
holder.multiple_choice.setVisibility(View.VISIBLE);
|
||||||
|
holder.c_choice_3.setVisibility(View.GONE);
|
||||||
|
holder.c_choice_4.setVisibility(View.GONE);
|
||||||
|
if( choiceCount > 2)
|
||||||
|
holder.c_choice_3.setVisibility(View.VISIBLE);
|
||||||
|
if( choiceCount > 3)
|
||||||
|
holder.c_choice_4.setVisibility(View.VISIBLE);
|
||||||
|
int j = 1;
|
||||||
|
for(PollOptions pollOption: status.getPoll().getOptionsList()){
|
||||||
|
if( j == 1 )
|
||||||
|
holder.c_choice_1.setText(pollOption.getTitle());
|
||||||
|
else if( j == 2 )
|
||||||
|
holder.c_choice_2.setText(pollOption.getTitle());
|
||||||
|
else if( j == 3 )
|
||||||
|
holder.c_choice_3.setText(pollOption.getTitle());
|
||||||
|
else if( j == 4 )
|
||||||
|
holder.c_choice_4.setText(pollOption.getTitle());
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}else {
|
||||||
|
Log.v(Helper.TAG,"count: " + choiceCount);
|
||||||
|
holder.single_choice.setVisibility(View.VISIBLE);
|
||||||
|
holder.r_choice_3.setVisibility(View.GONE);
|
||||||
|
holder.r_choice_4.setVisibility(View.GONE);
|
||||||
|
if( choiceCount > 2)
|
||||||
|
holder.r_choice_3.setVisibility(View.VISIBLE);
|
||||||
|
if( choiceCount > 3)
|
||||||
|
holder.r_choice_4.setVisibility(View.VISIBLE);
|
||||||
|
int j = 1;
|
||||||
|
for(PollOptions pollOption: status.getPoll().getOptionsList()){
|
||||||
|
if( j == 1 )
|
||||||
|
holder.r_choice_1.setText(pollOption.getTitle());
|
||||||
|
else if( j == 2 )
|
||||||
|
holder.r_choice_2.setText(pollOption.getTitle());
|
||||||
|
else if( j == 3 )
|
||||||
|
holder.r_choice_3.setText(pollOption.getTitle());
|
||||||
|
else if( j == 4 )
|
||||||
|
holder.r_choice_4.setText(pollOption.getTitle());
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
holder.submit_vote.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
holder.poll_container.setVisibility(View.VISIBLE);
|
||||||
|
holder.number_votes.setText(context.getResources().getQuantityString(R.plurals.number_of_vote,status.getPoll().getVotes_count(),status.getPoll().getVotes_count()));
|
||||||
|
holder.remaining_time.setText(context.getString(R.string.poll_finish_at, Helper.dateToStringPoll(poll.getExpires_at())));
|
||||||
|
}else {
|
||||||
|
holder.poll_container.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) {
|
if (social == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE) {
|
||||||
holder.status_action_container.setVisibility(View.GONE);
|
holder.status_action_container.setVisibility(View.GONE);
|
||||||
|
|
|
@ -665,6 +665,18 @@ public class Helper {
|
||||||
return dateFormat.format(date);
|
return dateFormat.format(date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
|
||||||
|
* @param date Date
|
||||||
|
* @return String
|
||||||
|
*/
|
||||||
|
public static String dateToStringPoll(Date date) {
|
||||||
|
if( date == null)
|
||||||
|
return null;
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm",Locale.getDefault());
|
||||||
|
return dateFormat.format(date);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
|
* Convert a date in String -> format yyyy-MM-dd HH:mm:ss
|
||||||
* @param date Date
|
* @param date Date
|
||||||
|
|
|
@ -725,7 +725,11 @@
|
||||||
android:id="@+id/status_peertube_delete"
|
android:id="@+id/status_peertube_delete"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</LinearLayout>/
|
</LinearLayout>
|
||||||
|
<include
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
layout="@layout/layout_poll" />
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_marginStart="60dp"
|
android:layout_marginStart="60dp"
|
||||||
android:layout_marginLeft="60dp"
|
android:layout_marginLeft="60dp"
|
||||||
|
|
|
@ -656,7 +656,10 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
<include
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
layout="@layout/layout_poll" />
|
||||||
<TextView
|
<TextView
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
|
|
|
@ -657,7 +657,10 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
<include
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
layout="@layout/layout_poll" />
|
||||||
<TextView
|
<TextView
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
|
|
|
@ -584,6 +584,12 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
layout="@layout/layout_poll" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/status_toot_app"
|
android:id="@+id/status_toot_app"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
Copyright 2019 Thomas Schneider
|
||||||
|
|
||||||
|
This file is a part of Mastalab
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||||
|
GNU General Public License as published by the Free Software Foundation; either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Mastalab is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with Mastalab; if not,
|
||||||
|
see <http://www.gnu.org/licenses>.
|
||||||
|
-->
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:layout_marginLeft="20dp"
|
||||||
|
android:layout_marginRight="20dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:id="@+id/poll_container"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
>
|
||||||
|
<LinearLayout
|
||||||
|
android:visibility="gone"
|
||||||
|
android:id="@+id/single_choice"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/radio_group"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:ignore="UselessParent">
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/r_choice_1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
/>
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/r_choice_2"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
/>
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/r_choice_3"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
/>
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/r_choice_4"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:checked="false"
|
||||||
|
/>
|
||||||
|
</RadioGroup>
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:visibility="gone"
|
||||||
|
android:id="@+id/multiple_choice"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/c_choice_1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/c_choice_2"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/c_choice_3"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/c_choice_4"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</LinearLayout>
|
||||||
|
<Button
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:id="@+id/submit_vote"
|
||||||
|
style="@style/Base.Widget.AppCompat.Button.Colored"
|
||||||
|
android:text="@string/vote"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:visibility="gone"
|
||||||
|
android:id="@+id/rated"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<br.com.felix.horizontalbargraph.HorizontalBar
|
||||||
|
android:id="@+id/choices"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
</LinearLayout>
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/number_votes"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<TextView
|
||||||
|
android:text=" - "
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/remaining_time"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/refresh_poll"
|
||||||
|
android:textColor="?colorAccent"
|
||||||
|
android:text="@string/refresh_poll"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
|
@ -58,7 +58,14 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
<Spinner
|
<Spinner
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/poll_choice"
|
||||||
android:layout_height="wrap_content"></Spinner>
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/poll_duration"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_height="wrap_content"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -901,15 +901,39 @@
|
||||||
<string name="featured_hashtags">Featured hashtags</string>
|
<string name="featured_hashtags">Featured hashtags</string>
|
||||||
<string name="filter_timeline_with_a_tag">Filter timeline with tags</string>
|
<string name="filter_timeline_with_a_tag">Filter timeline with tags</string>
|
||||||
<string name="no_tags">No tags</string>
|
<string name="no_tags">No tags</string>
|
||||||
|
|
||||||
|
<!-- end languages -->
|
||||||
|
|
||||||
<string name="poll">Poll</string>
|
<string name="poll">Poll</string>
|
||||||
<string name="create_poll">Create a poll</string>
|
<string name="create_poll">Create a poll</string>
|
||||||
<string name="poll_choice_1">Choice 1</string>
|
<string name="poll_choice_1">Choice 1</string>
|
||||||
<string name="poll_choice_2">Choice 2</string>
|
<string name="poll_choice_2">Choice 2</string>
|
||||||
<string name="poll_choice_3">Choice 3</string>
|
<string name="poll_choice_3">Choice 3</string>
|
||||||
<string name="poll_choice_4">Choice 4</string>
|
<string name="poll_choice_4">Choice 4</string>
|
||||||
<!-- end languages -->
|
<string name="poll_invalid_choices">You need two choices at least for the poll!</string>
|
||||||
|
<string name="done">Done</string>
|
||||||
|
<string name="poll_finish_at">end at %s</string>
|
||||||
|
<string name="refresh_poll">Refresh poll</string>
|
||||||
|
<string name="vote">Vote</string>
|
||||||
|
|
||||||
|
<plurals name="number_of_vote">
|
||||||
|
<item quantity="one">%d vote</item>
|
||||||
|
<item quantity="other">%d votes</item>
|
||||||
|
</plurals>
|
||||||
|
|
||||||
|
<string-array name="poll_choice_type">
|
||||||
|
<item>Single choice</item>
|
||||||
|
<item>Multiple choices</item>
|
||||||
|
</string-array>
|
||||||
|
<string-array name="poll_duration">
|
||||||
|
<item>5 minutes</item>
|
||||||
|
<item>30 minutes</item>
|
||||||
|
<item>1 hour</item>
|
||||||
|
<item>6 hours</item>
|
||||||
|
<item>1 day</item>
|
||||||
|
<item>3 days</item>
|
||||||
|
<item>7 days</item>
|
||||||
|
</string-array >
|
||||||
|
|
||||||
<string-array name="settings_video_mode">
|
<string-array name="settings_video_mode">
|
||||||
<item>Webview</item>
|
<item>Webview</item>
|
||||||
|
|
Loading…
Reference in New Issue