finalized poll create support

This commit is contained in:
nuclearfog 2023-03-11 21:08:12 +01:00
parent 7c19241787
commit ca38ed95fc
No known key found for this signature in database
GPG Key ID: 03488A185C476379
16 changed files with 612 additions and 81 deletions

View File

@ -586,7 +586,7 @@ public class Mastodon implements Connection {
PollUpdate poll = update.getPoll();
for (String option : poll.getOptions())
params.add("poll[options][]=" + StringTools.encode(option));
params.add("poll[expires_in]=" + poll.getValidity());
params.add("poll[expires_in]=" + poll.getDuration());
params.add("poll[multiple]=" + poll.multipleChoiceEnabled());
params.add("poll[hide_totals]=" + poll.hideTotalVotes());
}

View File

@ -145,9 +145,9 @@ public class MastodonPoll implements Poll {
/**
* @param json mastodon poll json format
*/
private MastodonOption(JSONObject json) throws JSONException {
voteCount = json.getInt("votes_count");
title = json.getString("title");
private MastodonOption(JSONObject json) {
voteCount = json.optInt("votes_count", 0);
title = json.optString("title", "-");
}

View File

@ -13,7 +13,7 @@ import java.util.List;
*/
public class PollUpdate {
private int validity;
private int duration;
private boolean multipleChoice;
private boolean hideTotals;
private List<String> options;
@ -28,8 +28,8 @@ public class PollUpdate {
*
* @return time until the poll is finnished
*/
public int getValidity() {
return validity;
public int getDuration() {
return duration;
}
/**
@ -49,14 +49,37 @@ public class PollUpdate {
/**
* @return an array of vote options
*/
public String[] getOptions() {
return options.toArray(new String[0]);
public List<String> getOptions() {
return options;
}
/**
* @param duration duration in seconds
*/
public void setDuration(int duration) {
this.duration = duration;
}
public void hideVotes(boolean hideTotals) {
this.hideTotals = hideTotals;
}
public void setMultipleChoice(boolean multipleChoice) {
this.multipleChoice = multipleChoice;
}
public void setOptions(List<String> options) {
this.options.clear();
this.options.addAll(options);
}
@NonNull
@Override
public String toString() {
return "valid=" + validity + " multiple=" + multipleChoice + "options=" + options.size();
return "valid=" + duration + " multiple=" + multipleChoice + "options=" + options.size();
}
}

View File

@ -162,8 +162,11 @@ public class StatusUpdate {
*
* @param poll poll information
*/
public void addPoll(@NonNull PollUpdate poll) {
if (attachment == EMPTY) {
public void addPoll(@Nullable PollUpdate poll) {
if (poll == null) {
this.poll = null;
attachment = EMPTY;
} else if (attachment == EMPTY) {
this.poll = poll;
attachment = POLL;
attachmentLimitReached = true;

View File

@ -25,6 +25,7 @@ import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.async.AsyncExecutor.AsyncCallback;
import org.nuclearfog.twidda.backend.async.StatusUpdater;
import org.nuclearfog.twidda.backend.async.StatusUpdater.StatusUpdateResult;
import org.nuclearfog.twidda.backend.helper.PollUpdate;
import org.nuclearfog.twidda.backend.helper.StatusUpdate;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.backend.utils.ErrorHandler;
@ -33,6 +34,8 @@ import org.nuclearfog.twidda.ui.adapter.IconAdapter;
import org.nuclearfog.twidda.ui.adapter.IconAdapter.OnMediaClickListener;
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog;
import org.nuclearfog.twidda.ui.dialogs.ConfirmDialog.OnConfirmListener;
import org.nuclearfog.twidda.ui.dialogs.PollDialog;
import org.nuclearfog.twidda.ui.dialogs.PollDialog.PollUpdateCallback;
import org.nuclearfog.twidda.ui.dialogs.ProgressDialog;
import org.nuclearfog.twidda.ui.dialogs.ProgressDialog.OnProgressStopListener;
@ -42,7 +45,7 @@ import org.nuclearfog.twidda.ui.dialogs.ProgressDialog.OnProgressStopListener;
* @author nuclearfog
*/
public class StatusEditor extends MediaActivity implements OnClickListener, OnProgressStopListener, OnConfirmListener,
OnMediaClickListener, AsyncCallback<StatusUpdateResult>, TextWatcher {
OnMediaClickListener, AsyncCallback<StatusUpdateResult>, TextWatcher, PollUpdateCallback {
/**
* key to add a statusd ID to reply
@ -64,7 +67,9 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
private ConfirmDialog confirmDialog;
private ProgressDialog loadingCircle;
private PollDialog pollDialog;
private IconAdapter adapter;
private StatusUpdate statusUpdate = new StatusUpdate();
@ -82,6 +87,7 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
ImageView background = findViewById(R.id.popup_status_background);
ImageButton statusButton = findViewById(R.id.popup_status_send);
ImageButton closeButton = findViewById(R.id.popup_status_close);
ImageButton addPoll = findViewById(R.id.popup_status_add_poll);
RecyclerView iconList = findViewById(R.id.popup_status_media_icons);
EditText statusText = findViewById(R.id.popup_status_input);
locationBtn = findViewById(R.id.popup_status_add_location);
@ -92,6 +98,7 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
settings = GlobalSettings.getInstance(this);
loadingCircle = new ProgressDialog(this);
confirmDialog = new ConfirmDialog(this);
pollDialog = new PollDialog(this, this);
AppStyles.setEditorTheme(root, background);
if (!settings.getLogin().getConfiguration().locationSupported()) {
@ -109,6 +116,7 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
iconList.setAdapter(adapter);
closeButton.setOnClickListener(this);
addPoll.setOnClickListener(this);
statusButton.setOnClickListener(this);
mediaBtn.setOnClickListener(this);
locationBtn.setOnClickListener(this);
@ -169,6 +177,10 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
else if (v.getId() == R.id.popup_status_close) {
showClosingMsg();
}
// show poll dialog
else if (v.getId() == R.id.popup_status_add_poll) {
pollDialog.show(statusUpdate.getPoll());
}
// Add media to the status
else if (v.getId() == R.id.popup_status_add_media) {
if (statusUpdate.getAttachmentType() == StatusUpdate.EMPTY) {
@ -295,6 +307,12 @@ public class StatusEditor extends MediaActivity implements OnClickListener, OnPr
}
}
@Override
public void onPollUpdate(@Nullable PollUpdate update) {
statusUpdate.addPoll(update);
}
/**
* show confirmation dialog when closing edited status
*/

View File

@ -1,42 +1,139 @@
package org.nuclearfog.twidda.ui.adapter;
import android.content.Context;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView.Adapter;
import org.nuclearfog.twidda.ui.adapter.holder.EditOptionsHolder;
import org.nuclearfog.twidda.ui.adapter.holder.EditOptionsHolder.OnOptionChangedListener;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
* RecyclerView adapter used to show option items
*
* @author nuclearfog
*/
public class EditOptionsAdapter extends Adapter {
public class EditOptionsAdapter extends Adapter<EditOptionsHolder> implements OnOptionChangedListener {
/**
* minimum option count
*/
private static final int MIN_OPTIONS = 2;
public EditOptionsAdapter(Context context) {}
/**
* maximum option count
*/
private static final int MAX_OPTIONS = 4;
private LinkedList<String> options;
/**
*
*/
public EditOptionsAdapter() {
options = new LinkedList<>();
for (int i = 0 ; i < MIN_OPTIONS ; i++)
options.add("");
options.add(null);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return null;
public EditOptionsHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new EditOptionsHolder(parent, this);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
public void onBindViewHolder(@NonNull EditOptionsHolder holder, int position) {
if (position < MIN_OPTIONS) {
holder.setState(position, EditOptionsHolder.STATE_LOCKED);
} else if (options.get(position) != null) {
holder.setState(position, EditOptionsHolder.STATE_ACTIVE);
} else {
holder.setState(position, EditOptionsHolder.STATE_DISABLED);
}
}
@Override
public int getItemCount() {
return 0;
return options.size();
}
public interface OnOptionChangedListener {
@Override
public void onOptionAdd(int position) {
if (options.size() < MAX_OPTIONS) {
// add empty item
options.add(position, "");
notifyItemInserted(position);
// update upper items
notifyItemRangeChanged(position + 1, MAX_OPTIONS - position - 1);
} else {
options.set(position, "");
notifyItemChanged(position);
}
}
@Override
public void onOptionRemove(int position) {
if (position < MAX_OPTIONS - 1) {
// remove item
options.remove(position);
notifyItemRemoved(position);
// update upper items
notifyItemRangeChanged(position, MAX_OPTIONS - position);
// add placeholder item
if (options.peekLast() != null) {
options.add(null);
notifyItemInserted(options.size());
}
} else {
options.set(position, null);
notifyItemChanged(position);
}
}
@Override
public void OnOptionChange(int position, String name) {
options.set(position, name);
}
/**
* set option names
*
* @param newOptions list of option name strings
*/
public void setOptions(List<String> newOptions) {
options.clear();
options.addAll(newOptions);
for (int i = options.size() ; i < MIN_OPTIONS; i++) {
options.add("");
}
options.add(null);
notifyDataSetChanged();
}
/**
* get option names
*
* @return list of option name strings
*/
public List<String> getOptions() {
List<String> result = new ArrayList<>();
for (String option : options) {
if (option != null && !option.trim().isEmpty()) {
result.add(option);
}
}
return result;
}
}

View File

@ -114,40 +114,40 @@ public class IconAdapter extends Adapter<IconHolder> implements OnHolderClickLis
}
/**
* add a single image icon
* append image icon at the end
*/
public void addImageItem() {
if (invert) {
items.add(0, IconHolder.TYPE_IMAGE);
notifyItemInserted(0);
} else {
items.add(IconHolder.TYPE_IMAGE);
notifyItemInserted(items.size() - 1);
}
appendItem(IconHolder.TYPE_IMAGE);
}
/**
* add a single gif item
*/
public void addGifItem() {
if (invert) {
items.add(0, IconHolder.TYPE_GIF);
notifyItemInserted(0);
} else {
items.add(IconHolder.TYPE_GIF);
notifyItemInserted(items.size() - 1);
}
}
/**
* add a single video item
* append video icon at the end
*/
public void addVideoItem() {
appendItem(IconHolder.TYPE_VIDEO);
}
/**
* append GIF icon at the end
*/
public void addGifItem() {
appendItem(IconHolder.TYPE_GIF);
}
/**
* append location icon at the end
*/
public void addLocation() {
appendItem(IconHolder.TYPE_LOCATION);
}
public void appendItem(int itemType) {
if (invert) {
items.add(0, IconHolder.TYPE_VIDEO);
items.add(0, itemType);
notifyItemInserted(0);
} else {
items.add(IconHolder.TYPE_VIDEO);
items.add(itemType);
notifyItemInserted(items.size() - 1);
}
}

View File

@ -0,0 +1,166 @@
package org.nuclearfog.twidda.ui.adapter.holder;
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
import android.text.Editable;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.text.TextWatcher;
import android.widget.ImageButton;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.config.GlobalSettings;
/**
* ViewHolder implementation for {@link org.nuclearfog.twidda.ui.adapter.EditOptionsAdapter}
*
* @author nuclearfog
*/
public class EditOptionsHolder extends ViewHolder implements OnClickListener, TextWatcher {
/**
* indicates that the item is locked and can't be removed
*/
public static final int STATE_LOCKED = 1;
/**
* indicates that the item is activated & removable
*/
public static final int STATE_ACTIVE = 2;
/**
* indicates that the item is disabled (placeholder)
*/
public static final int STATE_DISABLED = 3;
private EditText option_name;
private ImageButton option_button;
private OnOptionChangedListener listener;
private GlobalSettings settings;
private int state = STATE_LOCKED;
/**
*
*/
public EditOptionsHolder(ViewGroup parent, OnOptionChangedListener listener) {
super(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_option_edit, parent, false));
settings = GlobalSettings.getInstance(parent.getContext());
this.listener = listener;
option_name = itemView.findViewById(R.id.item_option_edit_name);
option_button = itemView.findViewById(R.id.item_option_edit_action);
AppStyles.setTheme((ViewGroup) itemView);
option_button.setOnClickListener(this);
option_name.addTextChangedListener(this);
}
@Override
public void onClick(View v) {
int position = getLayoutPosition();
if (position != NO_POSITION) {
if (v.getId() == R.id.item_option_edit_action) {
switch (state) {
case STATE_ACTIVE:
listener.onOptionRemove(position);
option_button.setImageResource(R.drawable.add);
AppStyles.setButtonColor(option_button, settings.getIconColor());
option_name.setEnabled(true);
break;
case STATE_DISABLED:
listener.onOptionAdd(position);
AppStyles.setButtonColor(option_button, settings.getIconColor());
option_name.setEnabled(false);
break;
}
}
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
int position = getLayoutPosition();
if (position != NO_POSITION) {
listener.OnOptionChange(position, s.toString());
}
}
/**
* set option state and option hint
*
* @param position position of the item
* @param state state to set {@link #STATE_LOCKED,#STATE_ACTIVE,#STATE_DISABLED}
*/
public void setState(int position, int state) {
this.state = state;
switch (state) {
case STATE_LOCKED:
option_name.setEnabled(true);
option_button.setImageResource(R.drawable.circle);
break;
case STATE_ACTIVE:
option_name.setEnabled(true);
option_button.setImageResource(R.drawable.cross);
break;
case STATE_DISABLED:
option_name.setEnabled(false);
option_button.setImageResource(R.drawable.add);
break;
}
AppStyles.setButtonColor(option_button, settings.getIconColor());
String hint = option_name.getContext().getString(R.string.dialog_poll_option_edit_hint, position + 1);
option_name.setHint(hint);
}
/**
* listener for option changes
*/
public interface OnOptionChangedListener {
/**
* called when an option is added
*
* @param position position where to insert the new item
*/
void onOptionAdd(int position);
/**
* called when an option is removed
*
* @param position position of the old item
*/
void onOptionRemove(int position);
/**
* called when the option name changes
*
* @param position position of the item
* @param name new option name
*/
void OnOptionChange(int position, String name);
}
}

View File

@ -2,28 +2,118 @@ package org.nuclearfog.twidda.ui.dialogs;
import android.app.Dialog;
import android.content.Context;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.kyleduo.switchbutton.SwitchButton;
import org.nuclearfog.twidda.R;
import org.nuclearfog.twidda.backend.helper.PollUpdate;
import org.nuclearfog.twidda.backend.utils.AppStyles;
import org.nuclearfog.twidda.ui.adapter.EditOptionsAdapter;
/**
* Dialog class used to show poll editor
*
* @author nuclearfog
*/
public class PollDialog extends Dialog {
public class PollDialog extends Dialog implements OnClickListener {
private EditOptionsAdapter optionAdapter;
private SwitchButton multiple_choice, hide_votes;
private Spinner timeUnitSelector;
private EditText durationInput;
private PollUpdateCallback callback;
private PollUpdate poll;
public PollDialog(@NonNull Context context) {
public PollDialog(@NonNull Context context, PollUpdateCallback callback) {
super(context, R.style.PollDialog);
this.callback = callback;
setContentView(R.layout.dialog_poll);
ViewGroup root = findViewById(R.id.dialog_poll_root);
RecyclerView optionsList = findViewById(R.id.dialog_poll_option_list);
Button confirm = findViewById(R.id.dialog_poll_create);
durationInput = findViewById(R.id.dialog_poll_duration_input);
timeUnitSelector = findViewById(R.id.dialog_poll_duration_timeunit);
multiple_choice = findViewById(R.id.dialog_poll_mul_choice);
hide_votes = findViewById(R.id.dialog_poll_hide_total);
ArrayAdapter<String> timeUnitAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_dropdown_item);
timeUnitAdapter.addAll(context.getResources().getStringArray(R.array.timeunits));
timeUnitSelector.setAdapter(timeUnitAdapter);
timeUnitSelector.setSelected(true);
optionAdapter = new EditOptionsAdapter();
optionsList.setAdapter(optionAdapter);
AppStyles.setTheme(root);
confirm.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.dialog_poll_create) {
String durationStr = durationInput.getText().toString();
if (durationStr.matches("\\d{1,3}")) {
int duration = Integer.parseInt(durationStr);
switch (timeUnitSelector.getSelectedItemPosition()) {
// minutes
case 0:
poll.setDuration(duration * 60);
break;
public void show(@NonNull PollUpdate poll) {
// hours
case 1:
poll.setDuration(duration * 3600);
break;
// days
case 2:
poll.setDuration(duration * 86400);
break;
}
} else {
// default 24h
poll.setDuration(86400);
}
poll.setMultipleChoice(multiple_choice.isChecked());
poll.hideVotes(hide_votes.isChecked());
poll.setOptions(optionAdapter.getOptions());
callback.onPollUpdate(poll);
dismiss();
}
}
public void show(@Nullable PollUpdate poll) {
if (!isShowing()) {
if (poll != null) {
optionAdapter.setOptions(poll.getOptions());
multiple_choice.setCheckedImmediately(poll.multipleChoiceEnabled());
hide_votes.setCheckedImmediately(poll.hideTotalVotes());
this.poll = poll;
} else {
this.poll = new PollUpdate();
}
super.show();
}
}
public interface PollUpdateCallback {
void onPollUpdate(@Nullable PollUpdate update);
}
}

View File

@ -77,7 +77,6 @@ public class NotificationFragment extends ListFragment implements OnNotification
if (!adapter.isEmpty())
sinceId = adapter.getItemId(0);
load(sinceId, 0L, 0);
setRefresh(true);
}
@ -86,6 +85,7 @@ public class NotificationFragment extends ListFragment implements OnNotification
adapter = new NotificationAdapter(requireContext(), this);
setAdapter(adapter);
load(0L, 0L, 0);
setRefresh(true);
}

View File

@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/dialog_poll_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
android:layout_height="wrap_content"
android:padding="@dimen/dialog_poll_root_layout_padding">
<TextView
android:id="@+id/dialog_poll_title"
@ -11,6 +13,7 @@
android:layout_marginBottom="@dimen/dialog_poll_layout_margins"
android:text="@string/dialog_poll_title"
android:textSize="@dimen/dialog_poll_title_textsize"
android:lines="1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/dialog_poll_option_list"
@ -19,29 +22,84 @@
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/dialog_poll_option_list"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_height="@dimen/dialog_poll_list_height"
android:layout_marginBottom="@dimen/dialog_poll_layout_margins"
android:orientation="vertical"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/dialog_poll_title"
app:layout_constraintBottom_toTopOf="@id/dialog_poll_list_barrier"
app:layout_constraintBottom_toTopOf="@id/dialog_poll_switch_barrier"
app:layout_constraintEnd_toEndOf="parent" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/dialog_poll_switch_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top"
app:constraint_referenced_ids="dialog_poll_mul_choice, dialog_poll_mul_choice_label, dialog_poll_hide_total, dialog_poll_hide_total_label"/>
<TextView
android:id="@+id/dialog_poll_mul_choice_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/dialog_poll_mc"
android:lines="1"
android:gravity="end"
android:textSize="@dimen/dialog_poll_textsize_small"
android:layout_marginEnd="@dimen/dialog_poll_layout_margins"
app:layout_constraintHorizontal_weight="4"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/dialog_poll_mul_choice"
app:layout_constraintBottom_toBottomOf="@id/dialog_poll_mul_choice"
app:layout_constraintEnd_toStartOf="@id/dialog_poll_mul_choice" />
<com.kyleduo.switchbutton.SwitchButton
android:id="@+id/dialog_poll_mul_choice"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/dialog_poll_mul_choice_label"
app:layout_constraintBottom_toTopOf="@id/dialog_poll_list_barrier"
app:layout_constraintEnd_toStartOf="@id/dialog_poll_hide_total_label"/>
<TextView
android:id="@+id/dialog_poll_hide_total_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/dialog_poll_hide"
android:lines="1"
android:gravity="end"
android:textSize="@dimen/dialog_poll_textsize_small"
android:layout_marginEnd="@dimen/dialog_poll_layout_margins"
app:layout_constraintHorizontal_weight="3"
app:layout_constraintStart_toEndOf="@id/dialog_poll_mul_choice"
app:layout_constraintTop_toTopOf="@id/dialog_poll_hide_total"
app:layout_constraintBottom_toBottomOf="@id/dialog_poll_hide_total"
app:layout_constraintEnd_toStartOf="@id/dialog_poll_hide_total"/>
<com.kyleduo.switchbutton.SwitchButton
android:id="@+id/dialog_poll_hide_total"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/dialog_poll_hide_total_label"
app:layout_constraintBottom_toTopOf="@id/dialog_poll_list_barrier"
app:layout_constraintEnd_toStartOf="@id/dialog_poll_switch_placeholder"/>
<View
android:id="@+id/dialog_poll_switch_placeholder"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@id/dialog_poll_hide_total"
app:layout_constraintTop_toTopOf="@id/dialog_poll_hide_total"
app:layout_constraintBottom_toTopOf="@id/dialog_poll_list_barrier"
app:layout_constraintEnd_toEndOf="parent"/>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/dialog_poll_list_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="top"
app:constraint_referenced_ids="dialog_poll_duration_input,dialog_poll_duration_label,dialog_poll_duration_timeunit"/>
<TextView
android:id="@+id/dialog_poll_duration_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_poll_duration_label"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/dialog_poll_option_list"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/dialog_poll_duration_input"/>
app:constraint_referenced_ids="dialog_poll_duration_input,dialog_poll_duration_timeunit,dialog_poll_create"/>
<EditText
android:id="@+id/dialog_poll_duration_input"
@ -54,8 +112,10 @@
android:hint="@string/dialog_poll_duration_hint"
android:layout_marginStart="@dimen/dialog_poll_layout_margins"
android:layout_marginEnd="@dimen/dialog_poll_layout_margins"
app:layout_constraintStart_toEndOf="@id/dialog_poll_duration_label"
app:layout_constraintTop_toBottomOf="@id/dialog_poll_option_list"
android:lines="1"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/dialog_poll_list_barrier"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/dialog_poll_duration_timeunit" />
@ -63,9 +123,23 @@
android:id="@+id/dialog_poll_duration_timeunit"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_weight="3"
app:layout_constraintStart_toEndOf="@id/dialog_poll_duration_input"
app:layout_constraintTop_toBottomOf="@id/dialog_poll_option_list"
app:layout_constraintTop_toBottomOf="@id/dialog_poll_list_barrier"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
app:layout_constraintEnd_toStartOf="@id/dialog_poll_create" />
<Button
android:id="@+id/dialog_poll_create"
android:layout_width="0dp"
android:layout_height="@dimen/dialog_poll_button_height"
android:text="@string/dialog_poll_button"
android:lines="1"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintStart_toEndOf="@id/dialog_poll_duration_timeunit"
app:layout_constraintTop_toBottomOf="@id/dialog_poll_list_barrier"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
style="@style/FeedbackButton" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="@dimen/item_option_edit_layout_padding">
<ImageButton
android:id="@+id/item_option_edit_action"
android:layout_width="@dimen/item_option_edit_button_size"
android:layout_height="@dimen/item_option_edit_button_size"
android:padding="@dimen/item_option_edit_drawable_padding"
android:src="@drawable/add"
style="@style/FeedbackButton" />
<EditText
android:id="@+id/item_option_edit_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:background="@android:color/transparent"
android:enabled="false"
android:lines="1"
android:layout_marginStart="@dimen/item_option_edit_layout_margin"/>
</LinearLayout>

View File

@ -17,7 +17,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintWidth_percent="0.85"
app:layout_constraintHeight_percent="0.4"
app:layout_constraintHeight_percent="0.5"
tools:ignore="ContentDescription" />
<EditText
@ -65,12 +65,11 @@
android:contentDescription="@string/status_add_image"
android:scaleType="fitCenter"
android:src="@drawable/attachment"
app:layout_constraintStart_toEndOf="@id/popup_status_media_icons"
app:layout_constraintBottom_toBottomOf="@id/popup_status_background"
app:layout_constraintEnd_toStartOf="@id/popup_status_add_location"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintDimensionRatio="1.0"
app:layout_constraintWidth_percent="0.1"
app:layout_constraintWidth_percent="@dimen/popup_status_button_size"
style="@style/RoundButton" />
<ProgressBar
@ -94,12 +93,27 @@
android:contentDescription="@string/send_status"
android:scaleType="fitCenter"
android:src="@drawable/location"
app:layout_constraintStart_toEndOf="@id/popup_status_add_media"
app:layout_constraintBottom_toBottomOf="@id/popup_status_background"
app:layout_constraintEnd_toStartOf="@id/popup_status_add_poll"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintDimensionRatio="1.0"
app:layout_constraintWidth_percent="@dimen/popup_status_button_size"
style="@style/RoundButton" />
<ImageButton
android:id="@+id/popup_status_add_poll"
android:layout_width="0dp"
android:layout_height="0dp"
android:padding="@dimen/popup_status_button_padding"
android:layout_marginBottom="@dimen/popup_status_margin_layout"
android:layout_marginEnd="@dimen/popup_status_button_margin"
android:scaleType="fitCenter"
android:src="@drawable/poll"
app:layout_constraintBottom_toBottomOf="@id/popup_status_background"
app:layout_constraintEnd_toStartOf="@id/popup_status_send"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintDimensionRatio="1.0"
app:layout_constraintWidth_percent="0.1"
app:layout_constraintWidth_percent="@dimen/popup_status_button_size"
style="@style/RoundButton" />
<ImageButton
@ -112,12 +126,11 @@
android:contentDescription="@string/send_status"
android:scaleType="fitCenter"
android:src="@drawable/post"
app:layout_constraintStart_toEndOf="@id/popup_status_add_location"
app:layout_constraintBottom_toBottomOf="@id/popup_status_background"
app:layout_constraintEnd_toStartOf="@id/popup_status_close"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintDimensionRatio="1.0"
app:layout_constraintWidth_percent="0.1"
app:layout_constraintWidth_percent="@dimen/popup_status_button_size"
style="@style/RoundButton" />
<ImageButton
@ -130,12 +143,11 @@
android:contentDescription="@string/status_close"
android:scaleType="fitCenter"
android:src="@drawable/cross"
app:layout_constraintStart_toEndOf="@id/popup_status_send"
app:layout_constraintBottom_toBottomOf="@id/popup_status_background"
app:layout_constraintEnd_toEndOf="@id/popup_status_background"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintDimensionRatio="1.0"
app:layout_constraintWidth_percent="0.1"
app:layout_constraintWidth_percent="@dimen/popup_status_button_size"
style="@style/RoundButton" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -54,4 +54,10 @@
<item>@drawable/follower</item>
</integer-array>
<string-array name="timeunits">
<item>minutes</item>
<item>hours</item>
<item>days</item>
</string-array>
</resources>

View File

@ -161,6 +161,7 @@
<dimen name="popup_status_button_margin">7dp</dimen>
<dimen name="popup_status_icon_list_margin">7dp</dimen>
<dimen name="popup_status_button_padding">7dp</dimen>
<dimen name="popup_status_button_size">0.09</dimen>
<!--dimens of popup_message.xml-->
<dimen name="popup_message_margin_background">10dp</dimen>
@ -241,8 +242,12 @@
<dimen name="dialog_connection_textsizte_normal">13sp</dimen>
<!--dimens of dialog_poll.xml-->
<dimen name="dialog_poll_list_height">200sp</dimen>
<dimen name="dialog_poll_root_layout_padding">5dp</dimen>
<dimen name="dialog_poll_layout_margins">3dp</dimen>
<dimen name="dialog_poll_textsize_small">12sp</dimen>
<dimen name="dialog_poll_title_textsize">18sp</dimen>
<dimen name="dialog_poll_button_height">20sp</dimen>
<!--dimens of tabitem.xml-->
<dimen name="tabitem_icon_size">22sp</dimen>
@ -274,10 +279,16 @@
<!-- dimens of item_icon.xml -->
<dimen name="item_icon_indicator_margin">2dp</dimen>
<!-- dimens of item_option -->
<!-- dimens of item_option.xml -->
<dimen name="item_option_icon_size">20sp</dimen>
<dimen name="item_option_text_size">13sp</dimen>
<dimen name="item_option_layout_padding">5dp</dimen>
<dimen name="item_option_button_margin">10dp</dimen>
<!--dimens of item_option_edit.xml -->
<dimen name="item_option_edit_layout_padding">3dp</dimen>
<dimen name="item_option_edit_button_size">24dp</dimen>
<dimen name="item_option_edit_drawable_padding">2dp</dimen>
<dimen name="item_option_edit_layout_margin">5dp</dimen>
</resources>

View File

@ -222,8 +222,12 @@
<string name="profile_bio">Bio</string>
<string name="connection_discard">discard</string>
<string name="dialog_poll_title">create poll</string>
<string name="dialog_poll_button">create</string>
<string name="dialog_poll_mc">multiple choice</string>
<string name="dialog_poll_hide">hide votes</string>
<string name="dialog_poll_option_edit_hint">Option %1$d</string>
<string name="dialog_poll_duration_label">Duration:</string>
<string name="dialog_poll_duration_hint">count</string>
<string name="dialog_poll_duration_hint">Duration</string>
<string name="confirm_discard">discard changes?</string>
<string name="user_data">User data</string>
<string name="follows_you">follows you</string>