This repository has been archived by the owner on Dec 15, 2022. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 61
Voting support only for response #265
Open
jcamposz
wants to merge
5
commits into
bleakgrey:master
Choose a base branch
from
jcamposz:issue_259
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
using Gee; | ||
public class Tootle.API.Poll { | ||
public string id { get; set; } | ||
public string expires_at{ get; set; } | ||
public bool expired { get; set; } | ||
public bool multiple { get; set; } | ||
public int64 votes_count { get; set; } | ||
public int64 voters_count { get; set; } | ||
public bool voted { get; set; } | ||
public int64[] own_votes { get; set; } | ||
public PollOption[]? options{ get; set; default = null; } | ||
|
||
public Poll (string _id) { | ||
id = _id; | ||
} | ||
public static Poll from_json (Json.Node node){ | ||
Json.Object obj=node.get_object(); | ||
var id = obj.get_string_member("id"); | ||
var poll = new Poll (id); | ||
|
||
poll.expires_at = obj.get_string_member ("expires_at"); | ||
poll.expired = obj.get_boolean_member ("expired"); | ||
poll.multiple = obj.get_boolean_member ("multiple"); | ||
poll.votes_count = obj.get_int_member ("votes_count"); | ||
poll.voters_count = obj.get_int_member ("voters_count"); | ||
poll.voted = obj.get_boolean_member ("voted"); | ||
|
||
var votes = obj.get_array_member ("own_votes"); | ||
int64[] array_votes={}; | ||
votes.foreach_element((array, i, node) => { | ||
array_votes+=node.get_int(); | ||
}); | ||
poll.own_votes=array_votes; | ||
|
||
PollOption[]? _options = {}; | ||
obj.get_array_member ("options").foreach_element ((array, i, node) => { | ||
var object = node.get_object (); | ||
if (object != null) | ||
_options += API.PollOption.parse (object); | ||
}); | ||
if (_options.length > 0) | ||
poll.options = _options; | ||
return poll; | ||
} | ||
/** | ||
*/ | ||
public static Request vote (InstanceAccount acc,PollOption[] options,ArrayList<string> selection, string id) { | ||
message (@"Voting poll $(id)..."); | ||
//Creating json to send | ||
var builder = new Json.Builder (); | ||
builder.begin_object (); | ||
builder.set_member_name ("choices"); | ||
builder.begin_array (); | ||
var row_number=0; | ||
foreach (API.PollOption p in options){ | ||
foreach (string select in selection){ | ||
if (select == p.title){ | ||
builder.add_string_value (row_number.to_string()); | ||
} | ||
} | ||
row_number++; | ||
} | ||
builder.end_array (); | ||
builder.end_object (); | ||
var generator = new Json.Generator (); | ||
generator.set_root (builder.get_root ()); | ||
var json = generator.to_data (null); | ||
//Send POST MESSAGE | ||
Request voting=new Request.POST (@"/api/v1/polls/$(id)/votes") | ||
.with_account (acc); | ||
voting.set_request("application/json",Soup.MemoryUse.COPY,json.data); | ||
return voting; | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
public class Tootle.API.PollOption { | ||
public string title { get; set; } | ||
public int64 votes_count{ get; set; } | ||
|
||
public static PollOption parse (Json.Object obj) { | ||
var pollOption = new PollOption (); | ||
pollOption.title = obj.get_string_member ("title"); | ||
pollOption.votes_count = obj.get_int_member ("votes_count"); | ||
return pollOption; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
using Gtk; | ||
using Gdk; | ||
using Gee; | ||
using GLib; | ||
|
||
[GtkTemplate (ui = "/com/github/bleakgrey/tootle/ui/widgets/status.ui")] | ||
public class Tootle.Widgets.Status : ListBoxRow { | ||
|
@@ -47,6 +49,7 @@ public class Tootle.Widgets.Status : ListBoxRow { | |
[GtkChild] protected Widgets.RichLabel date_label; | ||
[GtkChild] protected Image pin_indicator; | ||
[GtkChild] protected Image indicator; | ||
[GtkChild] protected Box poll; | ||
|
||
[GtkChild] protected Box content_column; | ||
[GtkChild] protected Stack spoiler_stack; | ||
|
@@ -65,6 +68,8 @@ public class Tootle.Widgets.Status : ListBoxRow { | |
[GtkChild] protected ToggleButton bookmark_button; | ||
[GtkChild] protected Button menu_button; | ||
|
||
protected Button vote_button; | ||
|
||
protected string spoiler_text { | ||
owned get { | ||
var text = status.formal.spoiler_text; | ||
|
@@ -99,6 +104,116 @@ public class Tootle.Widgets.Status : ListBoxRow { | |
return status.formal.account.avatar; | ||
} | ||
} | ||
public void get_poll(){ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It should also use a Glade ui template, just like any other view component in Tootle. |
||
if (status.poll!=null){ | ||
var row_number=0; | ||
Gtk.RadioButton[] radios={}; | ||
Gtk.CheckButton[] checks={}; | ||
ArrayList<string> selectedIndex=new ArrayList<string>(); | ||
if (status.poll.own_votes.length==0 && !status.poll.multiple){ | ||
selectedIndex.add(status.poll.options[0].title); | ||
} | ||
foreach (API.PollOption p in status.poll.options){ | ||
//if it is own poll | ||
if(status.account.id==accounts.active.username){ | ||
// If multiple, Checkbox else radioButton | ||
var option = new Widgets.RichLabel (p.title); | ||
var counts = new Widgets.RichLabel ("Votes: "+p.votes_count.to_string()+" %"); | ||
} | ||
else{ | ||
// If multiple, Checkbox else radioButton | ||
if (status.poll.multiple){ | ||
var button_vote = new Gtk.CheckButton (); | ||
button_vote.set_label(p.title); | ||
button_vote.toggled.connect((radio)=>{ | ||
if (selectedIndex.contains(radio.get_label())){ | ||
selectedIndex.remove(radio.get_label()); | ||
} | ||
else{ | ||
selectedIndex.add(radio.get_label()); | ||
} | ||
}); | ||
foreach (int64 own_vote in status.poll.own_votes){ | ||
if (own_vote==row_number){ | ||
button_vote.set_active(true); | ||
selectedIndex.add(p.title); | ||
} | ||
} | ||
if(status.poll.expired || status.poll.voted){ | ||
button_vote.set_sensitive(false); | ||
} | ||
poll.add(button_vote); | ||
checks+=button_vote; | ||
}else{ | ||
Gtk.RadioButton button_vote = null; | ||
if (radios.length==0){ | ||
button_vote=new Gtk.RadioButton (null); | ||
} | ||
else{ | ||
button_vote=new Gtk.RadioButton (radios[0].get_group()); | ||
} | ||
button_vote.set_label(p.title); | ||
button_vote.toggled.connect((radiobutton)=>{ | ||
if (selectedIndex.contains(radiobutton.get_label())) | ||
{ | ||
selectedIndex.remove(radiobutton.get_label()); | ||
} | ||
else{ | ||
selectedIndex.add(radiobutton.get_label()); | ||
} | ||
}); | ||
|
||
foreach (int64 own_vote in status.poll.own_votes){ | ||
if (own_vote==row_number){ | ||
button_vote.set_active(true); | ||
selectedIndex=new ArrayList<string>(); | ||
selectedIndex.add(p.title); | ||
} | ||
} | ||
if(status.poll.expired || status.poll.voted){ | ||
button_vote.set_sensitive(false); | ||
} | ||
poll.add(button_vote); | ||
radios+=button_vote; | ||
} | ||
} | ||
row_number++; | ||
} | ||
if(row_number>0 && !status.poll.expired && !status.poll.voted && | ||
status.account.id!=accounts.active.id && | ||
status.poll.own_votes.length==0){ | ||
Gtk.Box buttonsPoll=new Box (Orientation.HORIZONTAL, 6); | ||
vote_button = new Gtk.Button(); | ||
vote_button.set_label (_("Vote")); | ||
vote_button.clicked.connect ((button) =>{ | ||
Request voting=API.Poll.vote(accounts.active,status.poll.options,selectedIndex,status.poll.id); | ||
voting.then ((sess, mess) => { | ||
var node = network.parse_node (mess); | ||
status.poll=API.Poll.from_json(node); | ||
message ("OK: Voting correctly"); | ||
GLib.List<weak Gtk.Widget> children=this.poll.get_children(); | ||
foreach (Widget child in children){ | ||
this.poll.remove(child); | ||
} | ||
get_poll(); | ||
}) | ||
.on_error ((code, reason) => { | ||
warning ("Voting invalid!"); | ||
app.error ( | ||
_("Network Error"), | ||
_("The instance has invalidated this session. Please sign in again.\n\n%s").printf (reason) | ||
); | ||
}) | ||
.exec (); | ||
|
||
}); | ||
buttonsPoll.add(vote_button); | ||
buttonsPoll.show_all(); | ||
poll.add(buttonsPoll); | ||
} | ||
} | ||
poll.show_all(); | ||
} | ||
|
||
public signal void open (); | ||
|
||
|
@@ -147,6 +262,10 @@ public class Tootle.Widgets.Status : ListBoxRow { | |
status.formal.bind_property ("pinned", pin_indicator, "visible", BindingFlags.SYNC_CREATE); | ||
status.formal.bind_property ("account", avatar, "account", BindingFlags.SYNC_CREATE); | ||
|
||
// is it a poll? | ||
get_poll(); | ||
|
||
|
||
status.formal.bind_property ("has-spoiler", this, "reveal-spoiler", BindingFlags.SYNC_CREATE, (b, src, ref target) => { | ||
target.set_boolean (!src.get_boolean ()); | ||
return true; | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes me wish there was a way to (de)serialize Vala arrays automatically, just like
Entity.vala
does withGee.ArrayList<Object>
'Maybe we could do something here so that we can omit the boilerplate code for parsing.