mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-11-18 04:37:30 +00:00
answering polls in stories
This commit is contained in:
parent
e1c07c23a7
commit
71402cd164
@ -34,6 +34,7 @@ Not compatible with pre-16.6 versions (including alpha).
|
||||
Remember to read the [wiki](https://github.com/austinhuang0131/instagrabber/wiki) for more info!
|
||||
|
||||
[![Open Source Love svg3](https://badges.frapsoft.com/os/v3/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/)
|
||||
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](http://makeapullrequest.com)
|
||||
[![GPLv3 license](https://img.shields.io/badge/License-GPLv3-blue.svg)](./LICENSE)
|
||||
[![Snyk Vulnerabilities](https://img.shields.io/snyk/vulnerabilities/github/austinhuang0131/instagrabber)](https://snyk.io/test/github/austinhuang0131/instagrabber)
|
||||
[![LGTM Alerts](https://img.shields.io/lgtm/alerts/github/austinhuang0131/instagrabber)](https://lgtm.com/projects/g/austinhuang0131/instagrabber)
|
||||
|
@ -15,10 +15,12 @@ import android.util.Pair;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.GestureDetectorCompat;
|
||||
@ -36,8 +38,11 @@ import com.google.android.exoplayer2.source.MediaSourceEventListener;
|
||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource;
|
||||
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.R;
|
||||
@ -47,6 +52,7 @@ import awais.instagrabber.customviews.helpers.SwipeGestureListener;
|
||||
import awais.instagrabber.databinding.ActivityStoryViewerBinding;
|
||||
import awais.instagrabber.interfaces.SwipeEvent;
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.models.PollModel;
|
||||
import awais.instagrabber.models.PostModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
@ -79,6 +85,7 @@ public final class StoryViewer extends BaseLanguageActivity {
|
||||
private SimpleExoPlayer player;
|
||||
private SwipeEvent swipeEvent;
|
||||
private MenuItem menuDownload;
|
||||
private PollModel poll;
|
||||
private StoryModel currentStory;
|
||||
private String url, username;
|
||||
private int slidePos = 0, lastSlidePos = 0;
|
||||
@ -121,8 +128,6 @@ public final class StoryViewer extends BaseLanguageActivity {
|
||||
|
||||
@Override
|
||||
public void onSwipe(final boolean isRightSwipe) {
|
||||
Log.d("austin_debug", "swipe: "+(isRightSwipe ? "backward " : "forward ") + slidePos + "/" + storiesLen + " "
|
||||
+ (slidePos == storiesLen - 1 && isRightSwipe == false) + " " + intent.hasExtra(Constants.FEED));
|
||||
if (storyModels != null && storiesLen > 0) {
|
||||
if (((slidePos + 1 >= storiesLen && isRightSwipe == false) || (slidePos == 0 && isRightSwipe == true))
|
||||
&& intent.hasExtra(Constants.FEED)) {
|
||||
@ -195,6 +200,30 @@ public final class StoryViewer extends BaseLanguageActivity {
|
||||
.putExtra(Constants.EXTRAS_POST, new PostModel(tag.toString())));
|
||||
});
|
||||
|
||||
storyViewerBinding.interactStory.setOnClickListener(v -> {
|
||||
final Object tag = v.getTag();
|
||||
if (tag instanceof PollModel) {
|
||||
poll = (PollModel) tag;
|
||||
if (poll.getMyChoice() > -1)
|
||||
new AlertDialog.Builder(this).setTitle(R.string.voted_story_poll)
|
||||
.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new String[]{
|
||||
(poll.getMyChoice() == 0 ? "√ " : "") + poll.getLeftChoice() + " (" + poll.getLeftCount() + ")",
|
||||
(poll.getMyChoice() == 1 ? "√ " : "") + poll.getRightChoice() + " (" + poll.getRightCount() + ")"
|
||||
}), null)
|
||||
.setPositiveButton(R.string.ok, null)
|
||||
.show();
|
||||
else new AlertDialog.Builder(this).setTitle(poll.getQuestion())
|
||||
.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, new String[]{
|
||||
poll.getLeftChoice() + " (" + poll.getLeftCount() + ")",
|
||||
poll.getRightChoice() + " (" + poll.getRightCount() + ")"
|
||||
}), (d, w) -> {
|
||||
new VoteAction().execute(w);
|
||||
})
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
|
||||
storiesAdapter.setData(storyModels);
|
||||
if (storyModels.length > 1) storyViewerBinding.storiesList.setVisibility(View.VISIBLE);
|
||||
|
||||
@ -368,9 +397,14 @@ public final class StoryViewer extends BaseLanguageActivity {
|
||||
storyViewerBinding.viewStoryPost.setVisibility(shortCode != null ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.viewStoryPost.setTag(shortCode);
|
||||
|
||||
final PollModel poll = currentStory.getPoll();
|
||||
storyViewerBinding.interactStory.setVisibility(poll != null ? View.VISIBLE : View.GONE);
|
||||
storyViewerBinding.interactStory.setText(R.string.vote_story_poll);
|
||||
storyViewerBinding.interactStory.setTag(poll);
|
||||
|
||||
releasePlayer();
|
||||
final Intent intent = getIntent();
|
||||
if (intent.hasExtra(Constants.EXTRAS_HASHTAG)) {
|
||||
if (intent.getBooleanExtra(Constants.EXTRAS_HASHTAG, false)) {
|
||||
storyViewerBinding.toolbar.toolbar.setTitle(currentStory.getUsername() + " (" + intent.getStringExtra(Constants.EXTRAS_USERNAME) + ")");
|
||||
storyViewerBinding.toolbar.toolbar.setOnClickListener(v -> {
|
||||
searchUsername(currentStory.getUsername());
|
||||
@ -408,4 +442,46 @@ public final class StoryViewer extends BaseLanguageActivity {
|
||||
}
|
||||
return returnvalue;
|
||||
}
|
||||
|
||||
class VoteAction extends AsyncTask<Integer, Void, Void> {
|
||||
int ok = -1;
|
||||
String action;
|
||||
|
||||
protected Void doInBackground(Integer... rawchoice) {
|
||||
int choice = rawchoice[0];
|
||||
final String url = "https://www.instagram.com/media/"+currentStory.getStoryMediaId()+"/"+poll.getId()+"/story_poll_vote/";
|
||||
try {
|
||||
final HttpURLConnection urlConnection = (HttpURLConnection) new URL(url).openConnection();
|
||||
urlConnection.setRequestMethod("POST");
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.setRequestProperty("User-Agent", Constants.USER_AGENT);
|
||||
urlConnection.setRequestProperty("x-csrftoken",
|
||||
settingsHelper.getString(Constants.COOKIE).split("csrftoken=")[1].split(";")[0]);
|
||||
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
|
||||
urlConnection.setRequestProperty("Content-Length", "6");
|
||||
urlConnection.setDoOutput(true);
|
||||
DataOutputStream wr = new DataOutputStream(urlConnection.getOutputStream());
|
||||
wr.writeBytes("vote="+choice);
|
||||
wr.flush();
|
||||
wr.close();
|
||||
urlConnection.connect();
|
||||
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
|
||||
ok = choice;
|
||||
}
|
||||
else Toast.makeText(getApplicationContext(), R.string.downloader_unknown_error, Toast.LENGTH_SHORT).show();
|
||||
urlConnection.disconnect();
|
||||
} catch (Throwable ex) {
|
||||
Log.e("austin_debug", "vote: " + ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
if (ok > -1) {
|
||||
poll.setMyChoice(ok);
|
||||
Toast.makeText(getApplicationContext(), R.string.votef_story_poll, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -425,8 +425,6 @@ public final class FeedAdapter extends RecyclerView.Adapter<FeedItemViewHolder>
|
||||
if (btnMute != null) btnMute.setVisibility(View.VISIBLE);
|
||||
final PlayerView playerView = new PlayerView(context);
|
||||
|
||||
Log.d("austin_debug","1");
|
||||
|
||||
player = new SimpleExoPlayer.Builder(context).build();
|
||||
playerView.setPlayer(player);
|
||||
|
||||
|
@ -177,7 +177,7 @@ public final class DiscoverFetcher extends AsyncTask<Void, Void, DiscoverItemMod
|
||||
Utils.getThumbnailUrl(media, mediaType));
|
||||
|
||||
Utils.checkExistence(downloadDir, customDir, username,
|
||||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER, -1, model);
|
||||
mediaType == MediaItemType.MEDIA_TYPE_SLIDER, model);
|
||||
|
||||
return model;
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ public final class LocationFetcher extends AsyncTask<Void, Void, LocationModel>
|
||||
private final String idSlug;
|
||||
|
||||
public LocationFetcher(String idSlug, FetchListener<LocationModel> fetchListener) {
|
||||
Log.d("austin_debug", idSlug);
|
||||
// idSlug = id + "/" + slug
|
||||
this.idSlug = idSlug;
|
||||
this.fetchListener = fetchListener;
|
||||
|
@ -95,7 +95,7 @@ public final class PostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
|
||||
postModel.setCommentsCount(commentsCount);
|
||||
postModel.setCommentsEndCursor(endCursor);
|
||||
|
||||
Utils.checkExistence(downloadDir, customDir, username, false, -1, postModel);
|
||||
Utils.checkExistence(downloadDir, customDir, username, false, postModel);
|
||||
|
||||
result = new ViewerPostModel[]{postModel};
|
||||
|
||||
@ -119,7 +119,7 @@ public final class PostFetcher extends AsyncTask<Void, Void, ViewerPostModel[]>
|
||||
media.optJSONObject("location"));
|
||||
postModels[i].setSliderDisplayUrl(node.getString("display_url"));
|
||||
|
||||
Utils.checkExistence(downloadDir, customDir, username, true, i, postModels[i]);
|
||||
Utils.checkExistence(downloadDir, customDir, username, true, postModels[i]);
|
||||
}
|
||||
|
||||
postModels[0].setCommentsCount(commentsCount);
|
||||
|
@ -115,7 +115,7 @@ public final class PostsFetcher extends AsyncTask<Void, Void, PostModel[]> {
|
||||
mediaNode.getLong("taken_at_timestamp"), mediaNode.optBoolean("viewer_has_liked"),
|
||||
mediaNode.optBoolean("viewer_has_saved"), mediaNode.getJSONObject("edge_liked_by").getLong("count"));
|
||||
|
||||
Utils.checkExistence(downloadDir, customDir, username, isSlider, -1, models[i]);
|
||||
Utils.checkExistence(downloadDir, customDir, username, isSlider, models[i]);
|
||||
}
|
||||
|
||||
if (models[models.length - 1] != null)
|
||||
|
@ -12,6 +12,7 @@ import java.net.URL;
|
||||
import awais.instagrabber.BuildConfig;
|
||||
import awais.instagrabber.interfaces.FetchListener;
|
||||
import awais.instagrabber.models.enums.MediaItemType;
|
||||
import awais.instagrabber.models.PollModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.utils.Constants;
|
||||
import awais.instagrabber.utils.Utils;
|
||||
@ -34,8 +35,8 @@ public final class StoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[]
|
||||
@Override
|
||||
protected StoryModel[] doInBackground(final Void... voids) {
|
||||
StoryModel[] result = null;
|
||||
final String url = "https://www.instagram.com/graphql/query/?query_hash=52a36e788a02a3c612742ed5146f1676&variables=" +
|
||||
"{\"precomposed_overlay\":false,"
|
||||
final String url = "https://www.instagram.com/graphql/query/?query_hash=90709b530ea0969f002c86a89b4f2b8d&variables=" +
|
||||
"{\"precomposed_overlay\":false,\"show_story_viewer_list\":false,\"stories_video_dash_manifest\":false,"
|
||||
+(!Utils.isEmpty(hashtag) ? ("\"tag_names\":\""+hashtag+"\"}") : (
|
||||
location ? "\"location_ids\":[\""+id.split("/")[0]+"\"]}" : "\"reel_ids\":[\"" + id + "\"]}"));
|
||||
|
||||
@ -76,9 +77,19 @@ public final class StoryStatusFetcher extends AsyncTask<Void, Void, StoryModel[]
|
||||
for (int j = 0; j < tappableLength; ++j) {
|
||||
JSONObject tappableObject = tappableObjects.getJSONObject(j);
|
||||
if (tappableObject.optString("__typename").equals("GraphTappableFeedMedia")) {
|
||||
tappableObject = tappableObject.getJSONObject("media");
|
||||
models[i].setTappableShortCode(tappableObject.getString(Constants.EXTRAS_SHORTCODE));
|
||||
break;
|
||||
models[i].setTappableShortCode(tappableObject.getJSONObject("media").getString(Constants.EXTRAS_SHORTCODE));
|
||||
}
|
||||
else if (tappableObject.optString("__typename").equals("GraphTappableStoryPoll")) {
|
||||
Log.d("austin_debug", "poll: "+url+" "+tappableObject);
|
||||
models[i].setPoll(new PollModel(
|
||||
tappableObject.getString("id"),
|
||||
tappableObject.getString("question"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(0).getString("text"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(0).getInt("count"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(1).getString("text"),
|
||||
tappableObject.getJSONArray("tallies").getJSONObject(1).getInt("count"),
|
||||
tappableObject.optInt("viewer_vote", -1)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
52
app/src/main/java/awais/instagrabber/models/PollModel.java
Executable file
52
app/src/main/java/awais/instagrabber/models/PollModel.java
Executable file
@ -0,0 +1,52 @@
|
||||
package awais.instagrabber.models;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public final class PollModel implements Serializable {
|
||||
private int leftcount, rightcount, mychoice;
|
||||
private final String id, question, leftchoice, rightchoice;
|
||||
|
||||
public PollModel(final String id, final String question, final String leftchoice, final int leftcount,
|
||||
final String rightchoice, final int rightcount, final int mychoice) {
|
||||
this.id = id; // only the poll id
|
||||
this.question = question;
|
||||
this.leftchoice = leftchoice;
|
||||
this.leftcount = leftcount;
|
||||
this.rightchoice = rightchoice;
|
||||
this.rightcount = rightcount;
|
||||
this.mychoice = mychoice;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getQuestion() {
|
||||
return question;
|
||||
}
|
||||
|
||||
public String getLeftChoice() {
|
||||
return leftchoice;
|
||||
}
|
||||
|
||||
public int getLeftCount() {
|
||||
return leftcount;
|
||||
}
|
||||
|
||||
public String getRightChoice() {
|
||||
return rightchoice;
|
||||
}
|
||||
|
||||
public int getRightCount() {
|
||||
return rightcount;
|
||||
}
|
||||
|
||||
public int getMyChoice() { return mychoice; }
|
||||
|
||||
public int setMyChoice(final int choice) {
|
||||
this.mychoice = choice;
|
||||
if (choice == 0) this.leftcount += 1;
|
||||
else if (choice == 1) this.rightcount += 1;
|
||||
return choice;
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ public final class StoryModel implements Serializable {
|
||||
private final MediaItemType itemType;
|
||||
private final long timestamp;
|
||||
private String videoUrl, tappableShortCode;
|
||||
private PollModel poll;
|
||||
private int position;
|
||||
private boolean isCurrentSlide = false;
|
||||
|
||||
@ -44,6 +45,10 @@ public final class StoryModel implements Serializable {
|
||||
return tappableShortCode;
|
||||
}
|
||||
|
||||
public PollModel getPoll() {
|
||||
return poll;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
@ -56,6 +61,10 @@ public final class StoryModel implements Serializable {
|
||||
this.tappableShortCode = tappableShortCode;
|
||||
}
|
||||
|
||||
public void setPoll(final PollModel poll) {
|
||||
this.poll = poll;
|
||||
}
|
||||
|
||||
public void setPosition(final int position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
@ -70,6 +70,7 @@ import awais.instagrabber.models.BasePostModel;
|
||||
import awais.instagrabber.models.FeedStoryModel;
|
||||
import awais.instagrabber.models.HighlightModel;
|
||||
import awais.instagrabber.models.IntentModel;
|
||||
import awais.instagrabber.models.PollModel;
|
||||
import awais.instagrabber.models.ProfileModel;
|
||||
import awais.instagrabber.models.StoryModel;
|
||||
import awais.instagrabber.models.direct_messages.DirectItemModel;
|
||||
@ -972,17 +973,17 @@ public final class Utils {
|
||||
}
|
||||
|
||||
public static void checkExistence(final File downloadDir, final File customDir, final String username, final boolean isSlider,
|
||||
final int sliderIndex, @NonNull final BasePostModel model) {
|
||||
@NonNull final BasePostModel model) {
|
||||
boolean exists = false;
|
||||
|
||||
try {
|
||||
final String displayUrl = model.getDisplayUrl();
|
||||
final int index = displayUrl.indexOf('?');
|
||||
|
||||
final String fileName = model.getPostId() + '_' + model.getPosition();
|
||||
final String fileName = model.getPostId() + '_';
|
||||
final String extension = displayUrl.substring(index - 4, index);
|
||||
|
||||
final String fileWithoutPrefix = fileName + extension;
|
||||
final String fileWithoutPrefix = fileName + '0' + extension;
|
||||
exists = new File(downloadDir, fileWithoutPrefix).exists();
|
||||
if (!exists) {
|
||||
if (customDir != null) exists = new File(customDir, fileWithoutPrefix).exists();
|
||||
@ -993,8 +994,8 @@ public final class Utils {
|
||||
exists = new File(new File(customDir, username), fileWithoutPrefix).exists();
|
||||
}
|
||||
|
||||
if (!exists && isSlider && sliderIndex != -1) {
|
||||
final String fileWithPrefix = fileName + "_slide_[\\d]+" + extension;
|
||||
if (!exists && isSlider) {
|
||||
final String fileWithPrefix = fileName + "[\\d]+_slide_[\\d]+" + extension;
|
||||
final FilenameFilter filenameFilter = (dir, name) -> Pattern.matches(fileWithPrefix, name);
|
||||
|
||||
File[] files = downloadDir.listFiles(filenameFilter);
|
||||
@ -1007,7 +1008,6 @@ public final class Utils {
|
||||
if (logCollector != null)
|
||||
logCollector.appendException(e, LogCollector.LogFile.UTILS, "checkExistence",
|
||||
new Pair<>("isSlider", isSlider),
|
||||
new Pair<>("sliderIndex", sliderIndex),
|
||||
new Pair<>("model", model));
|
||||
if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e);
|
||||
}
|
||||
@ -1167,9 +1167,18 @@ public final class Utils {
|
||||
for (int k = 0; k < tappableLength; ++k) {
|
||||
JSONObject jsonObject = tappableObjects.getJSONObject(k);
|
||||
if (jsonObject.getString("__typename").equals("GraphTappableFeedMedia") && jsonObject.has("media")) {
|
||||
jsonObject = jsonObject.getJSONObject("media");
|
||||
storyModels[j].setTappableShortCode(jsonObject.getString(Constants.EXTRAS_SHORTCODE));
|
||||
break;
|
||||
storyModels[j].setTappableShortCode(jsonObject.getJSONObject("media").getString(Constants.EXTRAS_SHORTCODE));
|
||||
}
|
||||
else if (jsonObject.optString("__typename").equals("GraphTappableStoryPoll")) {
|
||||
storyModels[j].setPoll(new PollModel(
|
||||
jsonObject.getString("id"),
|
||||
jsonObject.getString("question"),
|
||||
jsonObject.getJSONArray("tallies").getJSONObject(0).getString("text"),
|
||||
jsonObject.getJSONArray("tallies").getJSONObject(0).getInt("count"),
|
||||
jsonObject.getJSONArray("tallies").getJSONObject(1).getString("text"),
|
||||
jsonObject.getJSONArray("tallies").getJSONObject(1).getInt("count"),
|
||||
jsonObject.optInt("viewer_vote", -1)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,15 +38,33 @@
|
||||
android:layout_gravity="center"
|
||||
android:visibility="gone" />
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/postActions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.3"
|
||||
android:background="#0000"
|
||||
android:weightSum="2"
|
||||
android:layout_gravity="bottom">
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/viewStoryPost"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/view_story_post"
|
||||
android:textColor="@color/btn_green_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_green_background" />
|
||||
<androidx.appcompat.widget.AppCompatButton
|
||||
android:id="@+id/interactStory"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="@string/view_story_post"
|
||||
android:textColor="@color/btn_blue_text_color"
|
||||
android:visibility="gone"
|
||||
app:backgroundTint="@color/btn_blue_background" />
|
||||
</androidx.appcompat.widget.LinearLayoutCompat>
|
||||
</FrameLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -60,6 +60,9 @@
|
||||
<string name="show_stories">Show stories</string>
|
||||
<string name="no_more_stories">No more stories!</string>
|
||||
<string name="view_story_post">View Story Post</string>
|
||||
<string name="vote_story_poll">Vote</string>
|
||||
<string name="votef_story_poll">Vote successful!</string>
|
||||
<string name="voted_story_poll">You have already voted!</string>
|
||||
<string name="priv_acc">This Account is Private</string>
|
||||
<string name="empty_acc">This Account has No Posts</string>
|
||||
<string name="curr_version">Current version: v%s</string>
|
||||
|
Loading…
Reference in New Issue
Block a user