();
52 |
53 | Crashlytics.start(this);
54 |
55 | mGaInstance = GoogleAnalytics.getInstance(this);
56 |
57 | mGaTracker = mGaInstance.getTracker("UA-5653857-3");
58 |
59 | mApp = this;
60 | }
61 |
62 | public Tracker getTracker() {
63 | return mGaTracker;
64 | }
65 |
66 | public static Context context() {
67 | return mApp.getApplicationContext();
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/CommentListActivity.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app;
2 |
3 | import ie.broadsheet.app.adapters.CommentAdapter;
4 | import ie.broadsheet.app.dialog.MakeCommentDialog;
5 | import ie.broadsheet.app.model.json.Comment;
6 | import ie.broadsheet.app.model.json.Post;
7 | import android.os.Bundle;
8 | import android.text.Html;
9 | import android.util.Log;
10 | import android.widget.ListView;
11 |
12 | import com.actionbarsherlock.view.Menu;
13 | import com.actionbarsherlock.view.MenuItem;
14 | import com.nostra13.universalimageloader.core.ImageLoader;
15 | import com.nostra13.universalimageloader.core.assist.PauseOnScrollListener;
16 |
17 | public class CommentListActivity extends BaseFragmentActivity implements MakeCommentDialog.CommentMadeListener,
18 | CommentAdapter.ReplyCommentListener {
19 | private static final String TAG = "CommentListActivity";
20 |
21 | public static final String CURRENT_POST = "current_post";
22 |
23 | private Post mPost;
24 |
25 | private CommentAdapter comments;
26 |
27 | @Override
28 | protected void onCreate(Bundle savedInstanceState) {
29 | super.onCreate(savedInstanceState);
30 | setContentView(R.layout.activity_comment_list);
31 |
32 | if (savedInstanceState != null) {
33 | Log.d(TAG, "saved instance");
34 | mPost = (Post) savedInstanceState.getSerializable(CURRENT_POST);
35 | } else {
36 | Bundle extras = getIntent().getExtras();
37 |
38 | if (extras != null) {
39 | BroadsheetApplication app = (BroadsheetApplication) getApplication();
40 |
41 | if (app.getPosts().size() > 0) {
42 | mPost = app.getPosts().get(extras.getInt("item_id"));
43 | }
44 | }
45 | }
46 |
47 | ListView list = (ListView) findViewById(android.R.id.list);
48 |
49 | comments = new CommentAdapter(this, R.layout.comment_list_item, mPost.getSortedComments());
50 | comments.setReplyCommentListener(this);
51 |
52 | list.setAdapter(comments);
53 |
54 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
55 |
56 | boolean pauseOnScroll = false;
57 | boolean pauseOnFling = true;
58 | PauseOnScrollListener listener = new PauseOnScrollListener(ImageLoader.getInstance(), pauseOnScroll,
59 | pauseOnFling);
60 | list.setOnScrollListener(listener);
61 |
62 | setTitle(getResources().getString(R.string.comment));
63 | }
64 |
65 | @Override
66 | public void onStart() {
67 | super.onStart();
68 |
69 | ((BroadsheetApplication) getApplication()).getTracker().sendView(
70 | "Comment List: " + Html.fromHtml(mPost.getTitle_plain()) + " " + Integer.toString(mPost.getId()));
71 | }
72 |
73 | @Override
74 | public void onStop() {
75 | super.onStop();
76 | }
77 |
78 | @Override
79 | public boolean onCreateOptionsMenu(Menu menu) {
80 | // Inflate the menu; this adds items to the action bar if it is present.
81 | if (mPost.getComment_status().equals("open")) {
82 | getSupportMenuInflater().inflate(R.menu.comment_list, menu);
83 | }
84 | return true;
85 | }
86 |
87 | @Override
88 | public boolean onOptionsItemSelected(MenuItem item) {
89 | if (item.getItemId() == android.R.id.home) {
90 | super.onBackPressed();
91 | return true;
92 | } else if (item.getItemId() == R.id.menu_make_comment) {
93 | onReply(0);
94 | }
95 | return super.onOptionsItemSelected(item);
96 | }
97 |
98 | @Override
99 | public void onCommentMade(Comment comment) {
100 | mPost.addComment(comment);
101 |
102 | comments.clear();
103 | // comments.addAll(mPost.getSortedComments());
104 | for (Comment addcomment : mPost.getSortedComments()) {
105 | comments.add(addcomment);
106 | }
107 | comments.notifyDataSetChanged();
108 | }
109 |
110 | @Override
111 | public void onReply(int commentId) {
112 | MakeCommentDialog dialog = new MakeCommentDialog();
113 | dialog.setPostId(mPost.getId());
114 | dialog.setCommentMadeListener(this);
115 | dialog.setCommentId(commentId);
116 | dialog.show(this.getSupportFragmentManager(), "MakeCommentDialog");
117 | }
118 |
119 | @Override
120 | public void onSaveInstanceState(Bundle savedInstanceState) {
121 | Log.d(TAG, "saving instance");
122 |
123 | super.onSaveInstanceState(savedInstanceState);
124 |
125 | savedInstanceState.putSerializable(CURRENT_POST, mPost);
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/PostDetailActivity.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app;
2 |
3 | import ie.broadsheet.app.fragments.PostDetailFragment;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.support.v4.app.NavUtils;
7 |
8 | /**
9 | * An activity representing a single Post detail screen. This activity is only used on handset devices. On tablet-size
10 | * devices, item details are presented side-by-side with a list of items in a {@link PostListActivity}.
11 | *
12 | * This activity is mostly just a 'shell' activity containing nothing more than a {@link PostDetailFragment}.
13 | */
14 | public class PostDetailActivity extends BaseFragmentActivity {
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.activity_post_detail);
20 |
21 | // Show the Up button in the action bar.
22 | getSupportActionBar().setDisplayHomeAsUpEnabled(true);
23 |
24 | // savedInstanceState is non-null when there is fragment state
25 | // saved from previous configurations of this activity
26 | // (e.g. when rotating the screen from portrait to landscape).
27 | // In this case, the fragment will automatically be re-added
28 | // to its container so we don't need to manually add it.
29 | // For more information, see the Fragments API guide at:
30 | //
31 | // http://developer.android.com/guide/components/fragments.html
32 | //
33 | if (savedInstanceState == null) {
34 | // Create the detail fragment and add it to the activity
35 | // using a fragment transaction.
36 | Bundle arguments = new Bundle();
37 | arguments
38 | .putInt(PostDetailFragment.ARG_ITEM_ID, getIntent().getIntExtra(PostDetailFragment.ARG_ITEM_ID, 0));
39 | arguments.putString(PostDetailFragment.ARG_ITEM_URL,
40 | getIntent().getStringExtra(PostDetailFragment.ARG_ITEM_URL));
41 | PostDetailFragment fragment = new PostDetailFragment();
42 | fragment.setArguments(arguments);
43 | getSupportFragmentManager().beginTransaction().add(R.id.post_detail_container, fragment).commit();
44 | }
45 | }
46 |
47 | @Override
48 | public boolean onOptionsItemSelected(com.actionbarsherlock.view.MenuItem item) {
49 | switch (item.getItemId()) {
50 | case android.R.id.home:
51 | // This ID represents the Home or Up button. In the case of this
52 | // activity, the Up button is shown. Use NavUtils to allow users
53 | // to navigate up one level in the application structure. For
54 | // more details, see the Navigation pattern on Android Design:
55 | //
56 | // http://developer.android.com/design/patterns/navigation.html#up-vs-back
57 | //
58 | NavUtils.navigateUpTo(this, new Intent(this, PostListActivity.class));
59 | return true;
60 | }
61 | return super.onOptionsItemSelected(item);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/PostListActivity.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app;
2 |
3 | import ie.broadsheet.app.fragments.PostDetailFragment;
4 | import ie.broadsheet.app.fragments.PostListFragment;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.util.Log;
8 |
9 | /**
10 | * An activity representing a list of Posts. This activity has different presentations for handset and tablet-size
11 | * devices. On handsets, the activity presents a list of items, which when touched, lead to a {@link PostDetailActivity}
12 | * representing item details. On tablets, the activity presents the list of items and item details side-by-side using
13 | * two vertical panes.
14 | *
15 | * The activity makes heavy use of fragments. The list of items is a {@link PostListFragment} and the item details (if
16 | * present) is a {@link PostDetailFragment}.
17 | *
18 | * This activity also implements the required {@link PostListFragment.Callbacks} interface to listen for item
19 | * selections.
20 | */
21 | public class PostListActivity extends BaseFragmentActivity implements PostListFragment.Callbacks {
22 | private static final String TAG = "PostListActivity";
23 |
24 | /**
25 | * Whether or not the activity is in two-pane mode, i.e. running on a tablet device.
26 | */
27 | private boolean mTwoPane;
28 |
29 | @Override
30 | protected void onCreate(Bundle savedInstanceState) {
31 | super.onCreate(savedInstanceState);
32 |
33 | setContentView(R.layout.activity_post_list);
34 |
35 | if (findViewById(R.id.post_detail_container) != null) {
36 | Log.d(TAG, "Dual screen");
37 | // The detail container view will be present only in the
38 | // large-screen layouts (res/values-large and
39 | // res/values-sw600dp). If this view is present, then the
40 | // activity should be in two-pane mode.
41 | mTwoPane = true;
42 |
43 | // In two-pane mode, list items should be given the
44 | // 'activated' state when touched.
45 | ((PostListFragment) getSupportFragmentManager().findFragmentById(R.id.post_list))
46 | .setActivateOnItemClick(true);
47 | }
48 |
49 | // TODO: If exposing deep links into your app, handle intents here.
50 | }
51 |
52 | /**
53 | * Callback method from {@link PostListFragment.Callbacks} indicating that the item with the given ID was selected.
54 | */
55 | @Override
56 | public void onItemSelected(int id) {
57 | // Since we're using a pull to refresh, the posts are off by 1
58 | id--;
59 | if (mTwoPane) {
60 | Log.d(TAG, "updating a fragment");
61 | // In two-pane mode, show the detail view in this activity by
62 | // adding or replacing the detail fragment using a
63 | // fragment transaction.
64 | Bundle arguments = new Bundle();
65 | arguments.putInt(PostDetailFragment.ARG_ITEM_ID, id);
66 | PostDetailFragment fragment = new PostDetailFragment();
67 | fragment.setArguments(arguments);
68 | getSupportFragmentManager().beginTransaction().replace(R.id.post_detail_container, fragment).commit();
69 |
70 | } else {
71 | Log.d(TAG, "starting an activity for post at position: " + Integer.toString(id));
72 | // In single-pane mode, simply start the detail activity
73 | // for the selected item ID.
74 | Intent detailIntent = new Intent(this, PostDetailActivity.class);
75 | detailIntent.putExtra(PostDetailFragment.ARG_ITEM_ID, id);
76 | startActivity(detailIntent);
77 | }
78 | }
79 |
80 | public boolean isDualScreen() {
81 | return mTwoPane;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/adapters/CommentAdapter.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.adapters;
2 |
3 | import ie.broadsheet.app.R;
4 | import ie.broadsheet.app.model.json.Comment;
5 |
6 | import java.util.List;
7 |
8 | import android.app.Activity;
9 | import android.content.Context;
10 | import android.text.Html;
11 | import android.view.LayoutInflater;
12 | import android.view.View;
13 | import android.view.ViewGroup;
14 | import android.widget.ArrayAdapter;
15 | import android.widget.Button;
16 | import android.widget.ImageView;
17 | import android.widget.TextView;
18 |
19 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
20 | import com.nostra13.universalimageloader.core.ImageLoader;
21 |
22 | public class CommentAdapter extends ArrayAdapter implements View.OnClickListener {
23 | public interface ReplyCommentListener {
24 | public void onReply(int commentId);
25 | }
26 |
27 | ReplyCommentListener mListener;
28 |
29 | public static class ViewHolder {
30 | public ImageView commentAvatar;
31 |
32 | public TextView commentUser;
33 |
34 | public TextView commentDate;
35 |
36 | public TextView commentBody;
37 |
38 | public Button replyButton;
39 | }
40 |
41 | public void setReplyCommentListener(ReplyCommentListener mListener) {
42 | this.mListener = mListener;
43 | }
44 |
45 | public CommentAdapter(Context context, int textViewResourceId, List comments) {
46 | super(context, textViewResourceId, comments);
47 |
48 | }
49 |
50 | @Override
51 | public View getView(int position, View convertView, ViewGroup parent) {
52 | View v = convertView;
53 |
54 | Activity activity = (Activity) getContext();
55 |
56 | ViewHolder holder;
57 | if (v == null) {
58 |
59 | LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
60 | v = vi.inflate(R.layout.comment_list_item, parent, false);
61 | holder = new ViewHolder();
62 | holder.commentAvatar = (ImageView) v.findViewById(R.id.commentAvatar);
63 | holder.commentUser = (TextView) v.findViewById(R.id.commentUser);
64 | holder.commentDate = (TextView) v.findViewById(R.id.commentDate);
65 | holder.commentBody = (TextView) v.findViewById(R.id.commentBody);
66 | holder.replyButton = (Button) v.findViewById(R.id.commentReply);
67 | v.setTag(holder);
68 | } else {
69 | holder = (ViewHolder) v.getTag();
70 |
71 | holder.commentAvatar.setImageDrawable(activity.getResources().getDrawable(R.drawable.default_user));
72 | }
73 |
74 | int standardMargin = activity.getResources().getDimensionPixelSize(R.dimen.standard_margin);
75 |
76 | final Comment comment = getItem(position);
77 |
78 | int newMargin = (standardMargin * 2 * comment.getChildLevel());
79 | v.setPadding(newMargin, v.getPaddingTop(), v.getPaddingRight(), v.getPaddingBottom());
80 |
81 | if (comment != null) {
82 | String avatar = comment.getAvatar();
83 |
84 | if ((avatar != null) && (avatar.length() > 0)) {
85 | DisplayImageOptions options = new DisplayImageOptions.Builder().cacheInMemory().cacheOnDisc()
86 | /*
87 | * .displayer( new RoundedBitmapDisplayer(activity.getResources ().getDimensionPixelSize(
88 | * R.dimen.standard_corner_radius)))
89 | */
90 | .build();
91 |
92 | ImageLoader.getInstance().displayImage(avatar, holder.commentAvatar, options);
93 | }
94 |
95 | holder.commentUser.setText(comment.getName());
96 | holder.commentDate.setText(comment.getRelativeTime());
97 | holder.commentBody.setText(Html.fromHtml(comment.getContent()));
98 |
99 | holder.replyButton.setTag(position);
100 | holder.replyButton.setOnClickListener(this);
101 | }
102 |
103 | return v;
104 | }
105 |
106 | @Override
107 | public void onClick(View v) {
108 | int position = (Integer) v.getTag();
109 |
110 | final Comment comment = getItem(position);
111 |
112 | mListener.onReply(comment.getId());
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/adapters/PostListAdapter.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.adapters;
2 |
3 | import ie.broadsheet.app.R;
4 | import ie.broadsheet.app.model.json.Post;
5 | import android.app.Activity;
6 | import android.content.Context;
7 | import android.text.Html;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.ArrayAdapter;
12 | import android.widget.ImageView;
13 | import android.widget.TextView;
14 |
15 | import com.nostra13.universalimageloader.core.DisplayImageOptions;
16 | import com.nostra13.universalimageloader.core.ImageLoader;
17 |
18 | public class PostListAdapter extends ArrayAdapter {
19 | // private static final String TAG = "PostListAdapter";
20 |
21 | public static class ViewHolder {
22 | public TextView titleView;
23 |
24 | public TextView dateView;
25 |
26 | public TextView commentCountView;
27 |
28 | public ImageView featuredImage;
29 | }
30 |
31 | public PostListAdapter(Context context) {
32 | super(context, R.layout.activity_post_list);
33 | }
34 |
35 | @Override
36 | public View getView(int position, View convertView, ViewGroup parent) {
37 | View v = convertView;
38 |
39 | ViewHolder holder;
40 | Activity activity = (Activity) getContext();
41 | if (v == null) {
42 | LayoutInflater vi = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
43 | v = vi.inflate(R.layout.post_list_item, null);
44 | holder = new ViewHolder();
45 | holder.titleView = (TextView) v.findViewById(R.id.post_title);
46 | holder.dateView = (TextView) v.findViewById(R.id.post_date);
47 | holder.commentCountView = (TextView) v.findViewById(R.id.comment_count);
48 | holder.featuredImage = (ImageView) v.findViewById(R.id.featuredImage);
49 | v.setTag(holder);
50 | } else {
51 | holder = (ViewHolder) v.getTag();
52 | holder.featuredImage.setImageDrawable(activity.getResources().getDrawable(R.drawable.default_post_image));
53 | }
54 |
55 | final Post post = getItem(position);
56 | if (post != null) {
57 |
58 | holder.titleView.setText(Html.fromHtml(post.getTitle_plain()));
59 | holder.dateView.setText(post.getRelativeTime());
60 | holder.commentCountView.setText(post.getCommentCountString());
61 |
62 | String featuredImage = post.getFeaturedImage();
63 |
64 | if ((featuredImage != null) && (featuredImage.length() > 0)) {
65 | DisplayImageOptions options = new DisplayImageOptions.Builder().cacheInMemory().cacheOnDisc()
66 | /*
67 | * .displayer( new RoundedBitmapDisplayer(activity.getResources().getDimensionPixelSize(
68 | * R.dimen.standard_corner_radius)))
69 | */
70 | .build();
71 | ImageLoader.getInstance().displayImage(featuredImage, holder.featuredImage, options);
72 |
73 | }
74 | }
75 |
76 | return v;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/adapters/PostListEndlessAdapter.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.adapters;
2 |
3 | import ie.broadsheet.app.BaseFragmentActivity;
4 | import ie.broadsheet.app.BroadsheetApplication;
5 | import ie.broadsheet.app.R;
6 | import ie.broadsheet.app.model.json.Post;
7 | import ie.broadsheet.app.model.json.PostList;
8 | import ie.broadsheet.app.requests.PostListRequest;
9 | import android.content.Context;
10 | import android.util.Log;
11 |
12 | import com.commonsware.cwac.endless.EndlessAdapter;
13 | import com.octo.android.robospice.persistence.DurationInMillis;
14 | import com.octo.android.robospice.persistence.exception.SpiceException;
15 | import com.octo.android.robospice.request.listener.RequestListener;
16 |
17 | public class PostListEndlessAdapter extends EndlessAdapter {
18 | public interface PostListLoadedListener {
19 | public void onPostListLoaded();
20 | }
21 |
22 | private PostListLoadedListener postListLoadedListener;
23 |
24 | private static final String TAG = "PostListEndlessAdapter";
25 |
26 | private boolean hasMore = true;
27 |
28 | private boolean loaded = false;
29 |
30 | private int currentPage = 0;
31 |
32 | private String searchTerm;
33 |
34 | private PostListRequest postListRequest;
35 |
36 | public PostListEndlessAdapter(Context context) {
37 | super(context, new PostListAdapter(context), R.layout.post_list_load_more);
38 |
39 | setRunInBackground(false);
40 | }
41 |
42 | @Override
43 | protected boolean cacheInBackground() throws Exception {
44 | if (hasMore) {
45 | currentPage++;
46 | fetchPosts();
47 | }
48 |
49 | return hasMore;
50 | }
51 |
52 | @Override
53 | protected void appendCachedData() {
54 |
55 | }
56 |
57 | public boolean isLoaded() {
58 | return loaded;
59 | }
60 |
61 | public void setLoaded(boolean loaded) {
62 | this.loaded = loaded;
63 | }
64 |
65 | public String getSearchTerm() {
66 | return searchTerm;
67 | }
68 |
69 | public void setSearchTerm(String searchTerm) {
70 | this.searchTerm = searchTerm;
71 | }
72 |
73 | public int getCurrentPage() {
74 | return currentPage;
75 | }
76 |
77 | public PostListLoadedListener getPostListLoadedListener() {
78 | return postListLoadedListener;
79 | }
80 |
81 | public void setPostListLoadedListener(PostListLoadedListener mListener) {
82 | this.postListLoadedListener = mListener;
83 | }
84 |
85 | public void reset() {
86 | loaded = false;
87 | hasMore = true;
88 | searchTerm = null;
89 | currentPage = 1;
90 | }
91 |
92 | public void fetchPosts() {
93 | if (postListRequest == null) {
94 | postListRequest = new PostListRequest();
95 |
96 | postListRequest.setPage(currentPage);
97 | postListRequest.setSearchTerm(searchTerm);
98 |
99 | BaseFragmentActivity activity = (BaseFragmentActivity) getContext();
100 |
101 | activity.getSpiceManager().execute(postListRequest, postListRequest.generateUrl(),
102 | DurationInMillis.ONE_MINUTE, new PostListListener());
103 | }
104 | }
105 |
106 | // ============================================================================================
107 | // INNER CLASSES
108 | // ============================================================================================
109 |
110 | public final class PostListListener implements RequestListener {
111 |
112 | @Override
113 | public void onRequestFailure(SpiceException spiceException) {
114 | Log.d(TAG, "Failed to get results");
115 |
116 | BaseFragmentActivity activity = (BaseFragmentActivity) getContext();
117 |
118 | hasMore = false;
119 | onDataReady();
120 |
121 | activity.showError(activity.getString(R.string.post_list_load_problem));
122 | }
123 |
124 | @Override
125 | public void onRequestSuccess(final PostList result) {
126 | Log.d(TAG, "we got results");
127 |
128 | loaded = true;
129 |
130 | hasMore = (result.getCount_total() > result.getCount());
131 |
132 | BroadsheetApplication app = (BroadsheetApplication) PostListEndlessAdapter.this.getContext()
133 | .getApplicationContext();
134 | if (PostListEndlessAdapter.this.currentPage == 1) {
135 | app.setPosts(null);
136 | ((PostListAdapter) getWrappedAdapter()).clear();
137 | }
138 | app.setPosts(result.getPosts());
139 |
140 | // ((PostListAdapter) getWrappedAdapter()).addAll(result.getPosts());
141 | PostListAdapter adapter = (PostListAdapter) getWrappedAdapter();
142 |
143 | for (Post post : result.getPosts()) {
144 | adapter.add(post);
145 | }
146 |
147 | onDataReady();
148 |
149 | postListRequest = null;
150 |
151 | PostListEndlessAdapter.this.postListLoadedListener.onPostListLoaded();
152 |
153 | app.getTracker().sendView("Post List Page" + Integer.toString(PostListEndlessAdapter.this.currentPage));
154 |
155 | if (result.getCount_total() == 0) {
156 | BaseFragmentActivity activity = (BaseFragmentActivity) getContext();
157 | activity.showError(activity.getString(R.string.post_list_no_matching_posts));
158 | }
159 | }
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/client/http/MultipartFormDataContent.java:
--------------------------------------------------------------------------------
1 | /**
2 | * via http://stackoverflow.com/a/16000382/806442
3 | */
4 | /*
5 | * Copyright (c) 2013 Google Inc.
6 | *
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
8 | * the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
13 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
14 | * specific language governing permissions and limitations under the License.
15 | */
16 | /**
17 | * This is a modification of com.google.api.client.http.MultipartContent from Google HTTP Client library to support
18 | * multipart/form-data requests.
19 | *
20 | * The original author is Yaniv Inbar.
21 | */
22 | package ie.broadsheet.app.client.http;
23 |
24 | import java.io.IOException;
25 | import java.io.OutputStream;
26 | import java.io.OutputStreamWriter;
27 | import java.io.Writer;
28 | import java.util.ArrayList;
29 |
30 | import com.google.api.client.http.AbstractHttpContent;
31 | import com.google.api.client.http.HttpContent;
32 | import com.google.api.client.http.HttpEncoding;
33 | import com.google.api.client.http.HttpEncodingStreamingContent;
34 | import com.google.api.client.http.HttpHeaders;
35 | import com.google.api.client.http.HttpMediaType;
36 | import com.google.api.client.http.UrlEncodedContent;
37 | import com.google.api.client.util.GenericData;
38 | import com.google.api.client.util.Preconditions;
39 | import com.google.api.client.util.StreamingContent;
40 |
41 | public class MultipartFormDataContent extends AbstractHttpContent {
42 |
43 | private static final String NEWLINE = "\r\n";
44 |
45 | private static final String TWO_DASHES = "--";
46 |
47 | private ArrayList parts = new ArrayList();
48 |
49 | public MultipartFormDataContent() {
50 | super(new HttpMediaType("multipart/form-data").setParameter("boundary", "__END_OF_PART__"));
51 | }
52 |
53 | @Override
54 | public void writeTo(OutputStream out) throws IOException {
55 |
56 | Writer writer = new OutputStreamWriter(out, getCharset());
57 | String boundary = getBoundary();
58 |
59 | for (Part part : parts) {
60 | HttpHeaders headers = new HttpHeaders().setAcceptEncoding(null);
61 | if (part.headers != null) {
62 | headers.fromHttpHeaders(part.headers);
63 | }
64 | headers.setContentEncoding(null).setUserAgent(null).setContentType(null).setContentLength(null);
65 | // analyze the content
66 | HttpContent content = part.content;
67 | StreamingContent streamingContent = null;
68 | String contentDisposition = String.format("form-data; name=\"%s\"", part.name);
69 | if (part.filename != null) {
70 | headers.setContentType(content.getType());
71 | contentDisposition += String.format("; filename=\"%s\"", part.filename);
72 | }
73 | headers.set("Content-Disposition", contentDisposition);
74 | HttpEncoding encoding = part.encoding;
75 | if (encoding == null) {
76 | streamingContent = content;
77 | } else {
78 | headers.setContentEncoding(encoding.getName());
79 | streamingContent = new HttpEncodingStreamingContent(content, encoding);
80 | }
81 | // write separator
82 | writer.write(TWO_DASHES);
83 | writer.write(boundary);
84 | writer.write(NEWLINE);
85 | // write headers
86 | HttpHeaders.serializeHeadersForMultipartRequests(headers, null, null, writer);
87 | // write content
88 | if (streamingContent != null) {
89 | writer.write(NEWLINE);
90 | writer.flush();
91 | streamingContent.writeTo(out);
92 | writer.write(NEWLINE);
93 | }
94 | }
95 | // write end separator
96 | writer.write(TWO_DASHES);
97 | writer.write(boundary);
98 | writer.write(TWO_DASHES);
99 | writer.write(NEWLINE);
100 | writer.flush();
101 | }
102 |
103 | @Override
104 | public boolean retrySupported() {
105 | for (Part part : parts) {
106 | if (!part.content.retrySupported()) {
107 | return false;
108 | }
109 | }
110 | return true;
111 | }
112 |
113 | @Override
114 | public MultipartFormDataContent setMediaType(HttpMediaType mediaType) {
115 | super.setMediaType(mediaType);
116 | return this;
117 | }
118 |
119 | /**
120 | * Adds an HTTP multipart part.
121 | *
122 | *
123 | * Overriding is only supported for the purpose of calling the super implementation and changing the return type,
124 | * but nothing else.
125 | *
126 | */
127 | public MultipartFormDataContent addPart(Part part) {
128 | parts.add(Preconditions.checkNotNull(part));
129 | return this;
130 | }
131 |
132 | public MultipartFormDataContent addUrlEncodedContent(String name, String value) {
133 | GenericData data = new GenericData();
134 | data.put(value, "");
135 |
136 | Part part = new Part();
137 | part.setContent(new UrlEncodedContent(data));
138 | part.setName(name);
139 |
140 | this.addPart(part);
141 |
142 | return this;
143 | }
144 |
145 | /** Returns the boundary string to use. */
146 | public final String getBoundary() {
147 | return getMediaType().getParameter("boundary");
148 | }
149 |
150 | /**
151 | * Sets the boundary string to use.
152 | *
153 | *
154 | * Defaults to {@code "END_OF_PART"}.
155 | *
156 | *
157 | *
158 | * Overriding is only supported for the purpose of calling the super implementation and changing the return type,
159 | * but nothing else.
160 | *
161 | */
162 | public MultipartFormDataContent setBoundary(String boundary) {
163 | getMediaType().setParameter("boundary", Preconditions.checkNotNull(boundary));
164 | return this;
165 | }
166 |
167 | /**
168 | * Single part of a multi-part request.
169 | *
170 | *
171 | * Implementation is not thread-safe.
172 | *
173 | */
174 | public static final class Part {
175 | private String name;
176 |
177 | private String filename;
178 |
179 | private HttpContent content;
180 |
181 | private HttpHeaders headers;
182 |
183 | private HttpEncoding encoding;
184 |
185 | public Part setContent(HttpContent content) {
186 | this.content = content;
187 | return this;
188 | }
189 |
190 | public Part setHeaders(HttpHeaders headers) {
191 | this.headers = headers;
192 | return this;
193 | }
194 |
195 | public Part setEncoding(HttpEncoding encoding) {
196 | this.encoding = encoding;
197 | return this;
198 | }
199 |
200 | public Part setName(String name) {
201 | this.name = name;
202 | return this;
203 | }
204 |
205 | public Part setFilename(String filename) {
206 | this.filename = filename;
207 | return this;
208 | }
209 | }
210 |
211 | }
212 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/dialog/AboutDialog.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.dialog;
2 |
3 | import ie.broadsheet.app.BroadsheetApplication;
4 | import ie.broadsheet.app.R;
5 | import android.app.AlertDialog;
6 | import android.app.Dialog;
7 | import android.content.ActivityNotFoundException;
8 | import android.content.Context;
9 | import android.content.DialogInterface;
10 | import android.content.DialogInterface.OnClickListener;
11 | import android.content.Intent;
12 | import android.content.pm.PackageManager.NameNotFoundException;
13 | import android.net.Uri;
14 | import android.os.Bundle;
15 | import android.support.v4.app.DialogFragment;
16 | import android.widget.Toast;
17 |
18 | public class AboutDialog extends DialogFragment implements OnClickListener {
19 | @Override
20 | public Dialog onCreateDialog(Bundle savedInstanceState) {
21 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
22 |
23 | builder.setTitle(R.string.about_title).setItems(R.array.about_array, this)
24 | .setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
25 | @Override
26 | public void onClick(DialogInterface dialog, int id) {
27 | dialog.dismiss();
28 | }
29 | });
30 |
31 | return builder.create();
32 | }
33 |
34 | @Override
35 | public void onStart() {
36 | super.onStart();
37 |
38 | ((BroadsheetApplication) getActivity().getApplication()).getTracker().sendView("About");
39 | }
40 |
41 | @Override
42 | public void onClick(DialogInterface dialog, int which) {
43 | Context context = ((Dialog) dialog).getContext();
44 |
45 | switch (which) {
46 | case 0:
47 | WebViewDialog aboutDialog = WebViewDialog.newInstance("about");
48 | aboutDialog.show(getActivity().getSupportFragmentManager(), "AboutDialog");
49 | break;
50 | case 1:
51 | Uri uri = Uri.parse("market://details?id=" + context.getPackageName());
52 | Intent goToMarket = new Intent(Intent.ACTION_VIEW, uri);
53 | try {
54 | startActivity(goToMarket);
55 | } catch (ActivityNotFoundException e) {
56 | Toast.makeText(context, "Couldn't launch the market", Toast.LENGTH_LONG).show();
57 | }
58 | break;
59 | case 2:
60 | Uri developeruri = Uri.parse("http://karlmonaghan.com/about");
61 | Intent goToDeveloper = new Intent(Intent.ACTION_VIEW, developeruri);
62 | startActivity(goToDeveloper);
63 | break;
64 | case 3:
65 | WebViewDialog webViewDialog = WebViewDialog.newInstance("libraries");
66 | webViewDialog.show(getActivity().getSupportFragmentManager(), "AboutDialog");
67 | break;
68 | case 4:
69 | /* Create the Intent */
70 | final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
71 |
72 | String body = "";
73 | String versionString;
74 | try {
75 | versionString = getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0).versionName;
76 | body = String.format(getResources().getString(R.string.app_feedback_body), versionString,
77 | android.os.Build.VERSION.RELEASE);
78 | } catch (NameNotFoundException e) {
79 | // TODO Auto-generated catch block
80 | e.printStackTrace();
81 | }
82 |
83 | /* Fill it with Data */
84 | emailIntent.setType("plain/text");
85 | emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,
86 | new String[] { "feedback@crayonsandbrownpaper.com" });
87 | emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Feedback for Broadsheet.ie");
88 | emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, body);
89 |
90 | /* Send it off to the Activity-Chooser */
91 | context.startActivity(Intent.createChooser(emailIntent, "Send mail..."));
92 | break;
93 | }
94 |
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/dialog/MakeCommentDialog.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.dialog;
2 |
3 | import ie.broadsheet.app.BaseFragmentActivity;
4 | import ie.broadsheet.app.BroadsheetApplication;
5 | import ie.broadsheet.app.R;
6 | import ie.broadsheet.app.model.json.Comment;
7 | import ie.broadsheet.app.requests.MakeCommentRequest;
8 | import ie.broadsheet.app.services.BroadsheetServices;
9 | import android.app.AlertDialog;
10 | import android.app.Dialog;
11 | import android.content.Context;
12 | import android.content.DialogInterface;
13 | import android.content.SharedPreferences;
14 | import android.os.Bundle;
15 | import android.util.Log;
16 | import android.view.LayoutInflater;
17 | import android.view.View;
18 | import android.view.View.OnClickListener;
19 | import android.view.WindowManager;
20 | import android.view.inputmethod.InputMethodManager;
21 | import android.widget.Button;
22 | import android.widget.EditText;
23 |
24 | import com.actionbarsherlock.app.SherlockDialogFragment;
25 | import com.octo.android.robospice.SpiceManager;
26 | import com.octo.android.robospice.persistence.exception.SpiceException;
27 | import com.octo.android.robospice.request.listener.RequestListener;
28 |
29 | public class MakeCommentDialog extends SherlockDialogFragment implements OnClickListener {
30 |
31 | public interface CommentMadeListener {
32 | public void onCommentMade(Comment comment);
33 | }
34 |
35 | private CommentMadeListener mListener;
36 |
37 | private static final String TAG = "MakeCommentDialog";
38 |
39 | private SpiceManager spiceManager = new SpiceManager(BroadsheetServices.class);
40 |
41 | private int postId;
42 |
43 | private int commentId = 0;
44 |
45 | private EditText email;
46 |
47 | private EditText commenterName;
48 |
49 | private EditText commenterUrl;
50 |
51 | private EditText commentBody;
52 |
53 | private Dialog dialog;
54 |
55 | public int getPostId() {
56 | return postId;
57 | }
58 |
59 | public void setPostId(int postId) {
60 | this.postId = postId;
61 | }
62 |
63 | public int getCommentId() {
64 | return commentId;
65 | }
66 |
67 | public void setCommentId(int commentId) {
68 | this.commentId = commentId;
69 | }
70 |
71 | public void setCommentMadeListener(CommentMadeListener mListener) {
72 | this.mListener = mListener;
73 | }
74 |
75 | @Override
76 | public Dialog onCreateDialog(Bundle savedInstanceState) {
77 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
78 | // Get the layout inflater
79 | LayoutInflater inflater = getActivity().getLayoutInflater();
80 |
81 | View view = inflater.inflate(R.layout.dialog_make_comment, null);
82 |
83 | commenterName = (EditText) view.findViewById(R.id.commenterName);
84 | email = (EditText) view.findViewById(R.id.commenterEmail);
85 | commenterUrl = (EditText) view.findViewById(R.id.commenterUrl);
86 | commentBody = (EditText) view.findViewById(R.id.commentBody);
87 |
88 | SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
89 |
90 | email.setText(sharedPref.getString("email", ""));
91 | commenterName.setText(sharedPref.getString("commenterName", ""));
92 | commenterUrl.setText(sharedPref.getString("commenterUrl", ""));
93 |
94 | // Inflate and set the layout for the dialog
95 | // Pass null as the parent view because its going in the dialog layout
96 | builder.setView(view)
97 | // Add action buttons
98 | .setPositiveButton(R.string.comment, new DialogInterface.OnClickListener() {
99 | @Override
100 | public void onClick(DialogInterface dialog, int id) {
101 |
102 | }
103 | }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
104 | public void onClick(DialogInterface dialog, int id) {
105 | MakeCommentDialog.this.getDialog().cancel();
106 | }
107 | });
108 |
109 | dialog = builder.create();
110 |
111 | commenterName.setOnFocusChangeListener(new View.OnFocusChangeListener() {
112 | @Override
113 | public void onFocusChange(View v, boolean hasFocus) {
114 | if (hasFocus) {
115 | dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
116 | }
117 | }
118 | });
119 |
120 | return dialog;
121 | }
122 |
123 | @Override
124 | public void onStart() {
125 | spiceManager.start(getActivity());
126 | super.onStart();
127 |
128 | AlertDialog d = (AlertDialog) getDialog();
129 | if (d != null) {
130 | Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE);
131 | positiveButton.setOnClickListener(this);
132 | }
133 |
134 | ((BroadsheetApplication) getActivity().getApplication()).getTracker().sendView("Post Comment");
135 | }
136 |
137 | @Override
138 | public void onStop() {
139 | spiceManager.shouldStop();
140 | super.onStop();
141 | }
142 |
143 | @Override
144 | public void onClick(View v) {
145 | if (!validate()) {
146 | return;
147 | }
148 |
149 | SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
150 | SharedPreferences.Editor editor = sharedPref.edit();
151 | editor.putString("email", email.getText().toString());
152 | editor.putString("commenterName", commenterName.getText().toString());
153 | editor.putString("commenterUrl", commenterUrl.getText().toString());
154 | editor.commit();
155 |
156 | MakeCommentRequest makeCommentRequest = new MakeCommentRequest();
157 | makeCommentRequest.setPostId(postId);
158 | makeCommentRequest.setEmail(email.getText().toString());
159 | makeCommentRequest.setCommentUrl(commenterUrl.getText().toString());
160 | makeCommentRequest.setCommentName(commenterName.getText().toString());
161 | makeCommentRequest.setCommentBody(commentBody.getText().toString());
162 | makeCommentRequest.setCommentId(commentId);
163 |
164 | v.setEnabled(false);
165 |
166 | email.clearFocus();
167 | commenterName.clearFocus();
168 | commenterUrl.clearFocus();
169 | commentBody.clearFocus();
170 |
171 | InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
172 | imm.hideSoftInputFromWindow(commentBody.getWindowToken(), 0);
173 |
174 | ((BaseFragmentActivity) getActivity()).onPreExecute(getResources().getString(R.string.posting_comment));
175 |
176 | spiceManager.execute(makeCommentRequest, new MakeCommentListener());
177 | }
178 |
179 | private boolean validate() {
180 | boolean okay = true;
181 |
182 | if ((commenterName.getText().toString() == null) || (commenterName.getText().toString().length() < 1)) {
183 | okay = false;
184 | commenterName.setError(getResources().getString(R.string.error_no_name));
185 | } else {
186 | commenterName.setError(null);
187 | }
188 |
189 | if ((email.getText().toString() == null) || (email.getText().toString().length() < 1)) {
190 | okay = false;
191 | email.setError(getResources().getString(R.string.error_no_email));
192 | } else {
193 | email.setError(null);
194 | }
195 |
196 | if ((commentBody.getText().toString() == null) || (commentBody.getText().toString().length() < 1)) {
197 | okay = false;
198 | commentBody.setError(getResources().getString(R.string.error_no_message));
199 | } else {
200 | commentBody.setError(null);
201 | }
202 |
203 | return okay;
204 | }
205 |
206 | // ============================================================================================
207 | // INNER CLASSES
208 | // ============================================================================================
209 |
210 | public final class MakeCommentListener implements RequestListener {
211 |
212 | @Override
213 | public void onRequestFailure(SpiceException spiceException) {
214 | Log.d(TAG, "Failed to get results: " + spiceException.toString());
215 |
216 | ((BaseFragmentActivity) getActivity()).onPostExecute();
217 |
218 | ((AlertDialog) MakeCommentDialog.this.dialog).getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
219 | }
220 |
221 | @Override
222 | public void onRequestSuccess(final Comment result) {
223 | Log.d(TAG, "we got result: " + result.toString());
224 |
225 | ((AlertDialog) MakeCommentDialog.this.dialog).getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(true);
226 |
227 | ((BaseFragmentActivity) getActivity()).onPostExecute();
228 |
229 | MakeCommentDialog.this.dismiss();
230 |
231 | MakeCommentDialog.this.mListener.onCommentMade(result);
232 | }
233 | }
234 | }
235 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/dialog/TipDialog.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.dialog;
2 |
3 | import ie.broadsheet.app.BaseFragmentActivity;
4 | import ie.broadsheet.app.BroadsheetApplication;
5 | import ie.broadsheet.app.R;
6 | import ie.broadsheet.app.model.json.SubmitTipResponse;
7 | import ie.broadsheet.app.requests.DownloadFileRequest;
8 | import ie.broadsheet.app.requests.SubmitTipRequest;
9 |
10 | import java.io.File;
11 | import java.io.IOException;
12 | import java.text.SimpleDateFormat;
13 | import java.util.ArrayList;
14 | import java.util.Date;
15 | import java.util.List;
16 |
17 | import android.app.Activity;
18 | import android.app.AlertDialog;
19 | import android.app.Dialog;
20 | import android.content.ComponentName;
21 | import android.content.Context;
22 | import android.content.DialogInterface;
23 | import android.content.Intent;
24 | import android.content.SharedPreferences;
25 | import android.content.pm.PackageManager;
26 | import android.content.pm.ResolveInfo;
27 | import android.database.Cursor;
28 | import android.graphics.Bitmap;
29 | import android.graphics.BitmapFactory;
30 | import android.net.Uri;
31 | import android.os.Bundle;
32 | import android.os.Environment;
33 | import android.os.Parcelable;
34 | import android.provider.MediaStore;
35 | import android.support.v4.app.DialogFragment;
36 | import android.util.Log;
37 | import android.view.LayoutInflater;
38 | import android.view.View;
39 | import android.view.WindowManager;
40 | import android.view.inputmethod.InputMethodManager;
41 | import android.widget.Button;
42 | import android.widget.EditText;
43 | import android.widget.ImageView;
44 | import android.widget.ImageView.ScaleType;
45 |
46 | import com.octo.android.robospice.persistence.exception.SpiceException;
47 | import com.octo.android.robospice.request.listener.RequestListener;
48 |
49 | public class TipDialog extends DialogFragment implements android.view.View.OnClickListener {
50 | private static final String TAG = "TipDialog";
51 |
52 | private static final int IMAGE_REQUEST_CODE = 1000;
53 |
54 | public static final String CURRENT_IMAGE_FILENAME = "image_filename";
55 |
56 | private EditText mName;
57 |
58 | private EditText mEmail;
59 |
60 | private EditText mMessage;
61 |
62 | private String mPicturePath;
63 |
64 | private String mCurrentPhotoPath;
65 |
66 | private boolean mAskedAboutPicture;
67 |
68 | private Button mSelectPhoto;
69 |
70 | private DownloadFileRequest downloadFileRequest;
71 |
72 | @Override
73 | public Dialog onCreateDialog(Bundle savedInstanceState) {
74 |
75 | if (savedInstanceState != null) {
76 | mCurrentPhotoPath = savedInstanceState.getString(CURRENT_IMAGE_FILENAME);
77 | }
78 |
79 | mAskedAboutPicture = false;
80 |
81 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
82 |
83 | LayoutInflater inflater = getActivity().getLayoutInflater();
84 |
85 | View view = inflater.inflate(R.layout.dialog_submit_tip, null);
86 |
87 | mName = (EditText) view.findViewById(R.id.submitterName);
88 | mEmail = (EditText) view.findViewById(R.id.submitorEmail);
89 | mMessage = (EditText) view.findViewById(R.id.submitBody);
90 |
91 | SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
92 |
93 | mEmail.setText(sharedPref.getString("email", ""));
94 | mName.setText(sharedPref.getString("commenterName", ""));
95 |
96 | mSelectPhoto = (Button) view.findViewById(R.id.addImage);
97 | mSelectPhoto.setOnClickListener(this);
98 |
99 | builder.setView(view)
100 | // Add action buttons
101 | .setPositiveButton(R.string.submit_tip, null)
102 | .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
103 | public void onClick(DialogInterface dialog, int id) {
104 | TipDialog.this.getDialog().cancel();
105 | }
106 | });
107 |
108 | final Dialog dialog = builder.create();
109 |
110 | mName.setOnFocusChangeListener(new View.OnFocusChangeListener() {
111 | @Override
112 | public void onFocusChange(View v, boolean hasFocus) {
113 | if (hasFocus) {
114 | dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
115 | }
116 | }
117 | });
118 |
119 | return dialog;
120 | }
121 |
122 | @Override
123 | public void onStart() {
124 | super.onStart();
125 |
126 | AlertDialog d = (AlertDialog) getDialog();
127 | if (d != null) {
128 | Button positiveButton = (Button) d.getButton(Dialog.BUTTON_POSITIVE);
129 | positiveButton.setOnClickListener(this);
130 | }
131 |
132 | ((BroadsheetApplication) getActivity().getApplication()).getTracker().sendView("Submit Tip");
133 | }
134 |
135 | @Override
136 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
137 | super.onActivityResult(requestCode, resultCode, data);
138 |
139 | if (resultCode == Activity.RESULT_OK) {
140 | switch (requestCode) {
141 | case IMAGE_REQUEST_CODE:
142 | final boolean isCamera = (data == null)
143 | || android.provider.MediaStore.ACTION_IMAGE_CAPTURE.equals(data.getAction());
144 |
145 | if (isCamera) {
146 | mPicturePath = mCurrentPhotoPath;
147 |
148 | galleryAddPic();
149 |
150 | Log.d(TAG, "From the camera: " + mPicturePath);
151 |
152 | showImage();
153 | } else {
154 | Uri imageUri = data.getData();
155 | // some devices (OS versions return an URI of com.android instead of com.google.android
156 | if (imageUri.toString().startsWith("content://com.android.gallery3d.provider")) {
157 | imageUri = Uri.parse(imageUri.toString().replace("com.android.gallery3d",
158 | "com.google.android.gallery3d"));
159 | }
160 |
161 | mPicturePath = null;
162 | String[] projection = { MediaStore.Images.Media.DATA };
163 | Cursor cursor = getActivity().getContentResolver().query(imageUri, projection, null, null, null);
164 | if (cursor != null) {
165 | int column_index = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
166 | if (column_index != -1) {
167 | cursor.moveToFirst();
168 | mPicturePath = cursor.getString(column_index);
169 | }
170 | }
171 |
172 | if (mPicturePath == null) mPicturePath = imageUri.getPath();
173 |
174 | Log.d(TAG, "from gallery: " + mPicturePath);
175 |
176 | if (mPicturePath != null) {
177 | File file = new File(mPicturePath);
178 | if (file.exists()) {
179 | showImage();
180 | } else if (mPicturePath.matches("http(s)?://.*"))
181 | downloadImage();
182 | else {
183 | // error
184 | Log.d(TAG, "we've an error as the file doesn't exist or isn't a URL");
185 | }
186 |
187 | } else {
188 | // Error
189 | Log.d(TAG, "we've an error as the file doesn't exist or isn't a URL");
190 | }
191 | }
192 | break;
193 | }
194 | }
195 | }
196 |
197 | @Override
198 | public void onClick(View v) {
199 | if (v.getId() == R.id.addImage) {
200 | selectImage();
201 | } else {
202 | if (!validate()) {
203 | return;
204 | }
205 |
206 | if (!mAskedAboutPicture && (mPicturePath == null)) {
207 | askAboutPicture();
208 | mAskedAboutPicture = true;
209 |
210 | return;
211 | }
212 |
213 | SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE);
214 | SharedPreferences.Editor editor = sharedPref.edit();
215 | editor.putString("email", mEmail.getText().toString());
216 | editor.putString("commenterName", mName.getText().toString());
217 | editor.commit();
218 |
219 | SubmitTipRequest request = new SubmitTipRequest();
220 | request.setName(mName.getText().toString());
221 | request.setEmail(mEmail.getText().toString());
222 | request.setMessage(mMessage.getText().toString());
223 | request.setFilename(mPicturePath);
224 |
225 | mEmail.clearFocus();
226 | mName.clearFocus();
227 | mMessage.clearFocus();
228 |
229 | InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
230 | imm.hideSoftInputFromWindow(mMessage.getWindowToken(), 0);
231 |
232 | ((BaseFragmentActivity) getActivity()).onPreExecute(getResources().getString(R.string.posting_tip));
233 |
234 | BaseFragmentActivity activity = (BaseFragmentActivity) getActivity();
235 |
236 | activity.getSpiceManager().execute(request, new SubmitTipRequestListener());
237 | }
238 | }
239 |
240 | public void showImage() {
241 | ImageView imageView = (ImageView) getDialog().findViewById(R.id.sumbitorImage);
242 |
243 | int targetW = imageView.getWidth();
244 | int targetH = imageView.getHeight();
245 |
246 | /* Get the size of the image */
247 | BitmapFactory.Options bmOptions = new BitmapFactory.Options();
248 | bmOptions.inJustDecodeBounds = true;
249 | BitmapFactory.decodeFile(mPicturePath, bmOptions);
250 | int photoW = bmOptions.outWidth;
251 | int photoH = bmOptions.outHeight;
252 |
253 | /* Figure out which way needs to be reduced less */
254 | int scaleFactor = 1;
255 | if ((targetW > 0) || (targetH > 0)) {
256 | scaleFactor = Math.min(photoW / targetW, photoH / targetH);
257 | }
258 |
259 | /* Set bitmap options to scale the image decode target */
260 | bmOptions.inJustDecodeBounds = false;
261 | bmOptions.inSampleSize = scaleFactor;
262 | bmOptions.inPurgeable = true;
263 |
264 | /* Decode the JPEG file into a Bitmap */
265 | Bitmap bitmap = BitmapFactory.decodeFile(mPicturePath, bmOptions);
266 |
267 | imageView.setImageBitmap(bitmap);
268 | imageView.setScaleType(ScaleType.CENTER_INSIDE);
269 | }
270 |
271 | protected void selectImage() {
272 | File tempFile = null;
273 | try {
274 | tempFile = createImageFile();
275 | } catch (IOException e) {
276 | // TODO Auto-generated catch block
277 | e.printStackTrace();
278 | }
279 |
280 | mCurrentPhotoPath = tempFile.getAbsolutePath();
281 |
282 | Uri outputFileUri = Uri.fromFile(tempFile);
283 |
284 | final List cameraIntents = new ArrayList();
285 | final Intent captureIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
286 | final PackageManager packageManager = getActivity().getPackageManager();
287 | final List listCam = packageManager.queryIntentActivities(captureIntent, 0);
288 | for (ResolveInfo res : listCam) {
289 | final Intent intent = new Intent(captureIntent);
290 | intent.setComponent(new ComponentName(res.activityInfo.packageName, res.activityInfo.name));
291 | intent.setPackage(res.activityInfo.packageName);
292 | intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
293 | cameraIntents.add(intent);
294 | }
295 |
296 | final Intent pickPhoto = new Intent();
297 | pickPhoto.setType("image/*");
298 | pickPhoto.setAction(Intent.ACTION_GET_CONTENT);
299 | pickPhoto.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
300 | final Intent chooserIntent = Intent.createChooser(pickPhoto, getResources().getString(R.string.selectGallery));
301 | chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[] {}));
302 | startActivityForResult(chooserIntent, IMAGE_REQUEST_CODE);
303 | }
304 |
305 | private File getAlbumDir() {
306 | File storageDir = null;
307 |
308 | if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
309 |
310 | storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
311 | getString(R.string.app_name));
312 |
313 | if (storageDir != null) {
314 | if (!storageDir.mkdirs()) {
315 | if (!storageDir.exists()) {
316 | Log.d(TAG, "failed to create directory");
317 | return null;
318 | }
319 | }
320 | }
321 |
322 | } else {
323 | Log.v(getString(R.string.app_name), "External storage is not mounted READ/WRITE.");
324 | }
325 |
326 | return storageDir;
327 | }
328 |
329 | private File createImageFile() throws IOException {
330 | // Create an image file name
331 | String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
332 | String imageFileName = "BS_" + timeStamp + "_";
333 | File image = File.createTempFile(imageFileName, ".jpg", getAlbumDir());
334 | mCurrentPhotoPath = image.getAbsolutePath();
335 | return image;
336 | }
337 |
338 | private void galleryAddPic() {
339 | Intent mediaScanIntent = new Intent("android.intent.action.MEDIA_SCANNER_SCAN_FILE");
340 | File f = new File(mCurrentPhotoPath);
341 | Uri contentUri = Uri.fromFile(f);
342 | mediaScanIntent.setData(contentUri);
343 | getActivity().sendBroadcast(mediaScanIntent);
344 | }
345 |
346 | private void downloadImage() {
347 | if (downloadFileRequest != null && !downloadFileRequest.isCancelled()) downloadFileRequest.cancel();
348 | downloadFileRequest = new DownloadFileRequest(mPicturePath, getActivity().getExternalCacheDir());
349 | ((BaseFragmentActivity) getActivity()).getSpiceManager().execute(downloadFileRequest,
350 | new DownloadRequestListener());
351 | ((BaseFragmentActivity) getActivity()).onPreExecute(getResources().getString(R.string.downloadingFile));
352 | }
353 |
354 | public void askAboutPicture() {
355 | AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
356 | builder.setMessage(R.string.no_image_picked)
357 | .setPositiveButton(R.string.add_an_image, new DialogInterface.OnClickListener() {
358 | public void onClick(DialogInterface dialog, int id) {
359 | TipDialog.this.selectImage();
360 | }
361 | }).setNegativeButton(R.string.no_thanks, new DialogInterface.OnClickListener() {
362 | public void onClick(DialogInterface dialog, int id) {
363 | TipDialog.this.onClick((Button) ((AlertDialog) dialog).getButton(Dialog.BUTTON_POSITIVE));
364 | }
365 | });
366 |
367 | builder.create().show();
368 | }
369 |
370 | private boolean validate() {
371 | boolean okay = true;
372 |
373 | if ((mName.getText().toString() == null) || (mName.getText().toString().length() < 1)) {
374 | okay = false;
375 | mName.setError(getResources().getString(R.string.error_no_name));
376 | } else {
377 | mName.setError(null);
378 | }
379 |
380 | if ((mEmail.getText().toString() == null) || (mEmail.getText().toString().length() < 1)) {
381 | okay = false;
382 | mEmail.setError(getResources().getString(R.string.error_no_email));
383 | } else {
384 | mEmail.setError(null);
385 | }
386 |
387 | if ((mMessage.getText().toString() == null) || (mMessage.getText().toString().length() < 1)) {
388 | okay = false;
389 | mMessage.setError(getResources().getString(R.string.error_no_message));
390 | } else {
391 | mMessage.setError(null);
392 | }
393 |
394 | return okay;
395 | }
396 |
397 | // ============================================================================================
398 | // INNER CLASSES
399 | // ============================================================================================
400 |
401 | public final class SubmitTipRequestListener implements RequestListener {
402 |
403 | @Override
404 | public void onRequestFailure(SpiceException spiceException) {
405 | Log.d(TAG, "Failed to get results: " + spiceException.toString());
406 |
407 | ((BaseFragmentActivity) getActivity()).onPostExecute();
408 |
409 | ((BaseFragmentActivity) getActivity()).showError(getActivity().getResources().getString(
410 | R.string.tip_submit_problem));
411 | }
412 |
413 | @Override
414 | public void onRequestSuccess(final SubmitTipResponse result) {
415 | Log.d(TAG, "we got result: " + result.toString());
416 |
417 | ((BaseFragmentActivity) getActivity()).onPostExecute();
418 |
419 | TipDialog.this.dismiss();
420 | }
421 | }
422 |
423 | private class DownloadRequestListener implements RequestListener {
424 |
425 | @Override
426 | public void onRequestFailure(SpiceException e) {
427 | TipDialog.this.downloadFileRequest = null;
428 | ((BaseFragmentActivity) getActivity()).onPostExecute();
429 | Log.d(TAG, "Problem downloading");
430 | }
431 |
432 | @Override
433 | public void onRequestSuccess(File result) {
434 | TipDialog.this.downloadFileRequest = null;
435 | ((BaseFragmentActivity) getActivity()).onPostExecute();
436 | Log.d(TAG, result.toString());
437 |
438 | TipDialog.this.mPicturePath = result.getPath();
439 | TipDialog.this.showImage();
440 | }
441 | }
442 |
443 | @Override
444 | public void onSaveInstanceState(Bundle savedInstanceState) {
445 | Log.d(TAG, "saving instance");
446 |
447 | super.onSaveInstanceState(savedInstanceState);
448 |
449 | savedInstanceState.putSerializable(CURRENT_IMAGE_FILENAME, mCurrentPhotoPath);
450 | }
451 | }
452 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/dialog/WebViewDialog.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.dialog;
2 |
3 | import android.app.AlertDialog;
4 | import android.app.Dialog;
5 | import android.content.DialogInterface;
6 | import android.os.Bundle;
7 | import android.support.v4.app.DialogFragment;
8 | import android.webkit.WebView;
9 |
10 | public class WebViewDialog extends DialogFragment {
11 | public static WebViewDialog newInstance(String localHtml) {
12 | WebViewDialog frag = new WebViewDialog();
13 | Bundle args = new Bundle();
14 | args.putString("localHtml", localHtml);
15 | frag.setArguments(args);
16 | return frag;
17 | }
18 |
19 | public Dialog onCreateDialog(Bundle savedInstanceState) {
20 | String localHtml = getArguments().getString("localHtml");
21 | if (localHtml == null) {
22 | localHtml = "about";
23 | }
24 |
25 | WebView webView = new WebView(getActivity());
26 | webView.loadUrl("file:///android_asset/" + localHtml + ".html");
27 | AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity());
28 | dialog.setView(webView);
29 | dialog.setPositiveButton("Okay", new DialogInterface.OnClickListener() {
30 |
31 | public void onClick(DialogInterface dialog, int which) {
32 |
33 | dialog.dismiss();
34 | }
35 | });
36 |
37 | return dialog.create();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/fragments/PostDetailFragment.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.fragments;
2 |
3 | import ie.broadsheet.app.BaseFragmentActivity;
4 | import ie.broadsheet.app.BroadsheetApplication;
5 | import ie.broadsheet.app.CommentListActivity;
6 | import ie.broadsheet.app.PostDetailActivity;
7 | import ie.broadsheet.app.PostListActivity;
8 | import ie.broadsheet.app.R;
9 | import ie.broadsheet.app.dialog.MakeCommentDialog;
10 | import ie.broadsheet.app.model.json.Comment;
11 | import ie.broadsheet.app.model.json.Post;
12 | import ie.broadsheet.app.model.json.SinglePost;
13 | import ie.broadsheet.app.requests.PostRequest;
14 | import android.annotation.SuppressLint;
15 | import android.app.Activity;
16 | import android.content.Context;
17 | import android.content.Intent;
18 | import android.content.pm.PackageManager;
19 | import android.content.pm.PackageManager.NameNotFoundException;
20 | import android.net.Uri;
21 | import android.os.Bundle;
22 | import android.text.Html;
23 | import android.util.Log;
24 | import android.view.LayoutInflater;
25 | import android.view.View;
26 | import android.view.View.OnClickListener;
27 | import android.view.ViewGroup;
28 | import android.webkit.WebSettings.PluginState;
29 | import android.webkit.WebView;
30 | import android.webkit.WebViewClient;
31 | import android.widget.Button;
32 |
33 | import com.actionbarsherlock.app.SherlockFragment;
34 | import com.actionbarsherlock.view.Menu;
35 | import com.actionbarsherlock.view.MenuInflater;
36 | import com.actionbarsherlock.view.MenuItem;
37 | import com.actionbarsherlock.widget.ShareActionProvider;
38 | import com.octo.android.robospice.persistence.DurationInMillis;
39 | import com.octo.android.robospice.persistence.exception.SpiceException;
40 | import com.octo.android.robospice.request.listener.RequestListener;
41 |
42 | /**
43 | * A fragment representing a single Post detail screen. This fragment is either contained in a {@link PostListActivity}
44 | * in two-pane mode (on tablets) or a {@link PostDetailActivity} on handsets.
45 | */
46 | public class PostDetailFragment extends SherlockFragment implements MakeCommentDialog.CommentMadeListener,
47 | OnClickListener {
48 | private static final String TAG = "PostDetailFragment";
49 |
50 | /**
51 | * The fragment argument representing the item ID that this fragment represents.
52 | */
53 | public static final String ARG_ITEM_ID = "item_id";
54 |
55 | public static final String ARG_ITEM_URL = "item_url";
56 |
57 | public static final String CURRENT_POST = "current_post";
58 |
59 | public static final String CURRENT_POST_ID = "current_post_id";
60 |
61 | private Post mPost;
62 |
63 | private WebView mWebview;
64 |
65 | private int mPostIndex = -1;
66 |
67 | private ShareActionProvider mActionProvider;
68 |
69 | private Button mNext;
70 |
71 | private Button mPrevious;
72 |
73 | private BroadsheetApplication mApp;
74 |
75 | /**
76 | * Mandatory empty constructor for the fragment manager to instantiate the fragment (e.g. upon screen orientation
77 | * changes).
78 | */
79 | public PostDetailFragment() {
80 |
81 | }
82 |
83 | @Override
84 | public void onCreate(Bundle savedInstanceState) {
85 | super.onCreate(savedInstanceState);
86 |
87 | mApp = (BroadsheetApplication) getActivity().getApplication();
88 |
89 | if (savedInstanceState != null) {
90 | Log.d(TAG, "saved instance");
91 | mPost = (Post) savedInstanceState.getSerializable(CURRENT_POST);
92 | mPostIndex = savedInstanceState.getInt(CURRENT_POST_ID, -1);
93 | } else {
94 | String url = getArguments().getString(ARG_ITEM_URL);
95 |
96 | if (url != null) {
97 |
98 | ((BaseFragmentActivity) getActivity()).onPreExecute(getResources().getString(R.string.posting_comment));
99 |
100 | BaseFragmentActivity activity = (BaseFragmentActivity) getActivity();
101 |
102 | PostRequest postRequest = new PostRequest(url);
103 |
104 | activity.getSpiceManager().execute(postRequest, url, DurationInMillis.ONE_MINUTE, new PostListener());
105 | } else if (getArguments().containsKey(ARG_ITEM_ID)) {
106 |
107 | mPostIndex = getArguments().getInt(ARG_ITEM_ID);
108 | if (mPostIndex < mApp.getPosts().size()) {
109 | mPost = mApp.getPosts().get(mPostIndex);
110 | }
111 | }
112 | }
113 |
114 | setHasOptionsMenu(true);
115 |
116 | getActivity().setTitle("");
117 | }
118 |
119 | @Override
120 | public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
121 | super.onCreateOptionsMenu(menu, inflater);
122 |
123 | if (mPost != null) {
124 |
125 | inflater.inflate(R.menu.post_detail, menu);
126 |
127 | menu.findItem(R.id.menu_make_comment).setVisible(mPost.getComment_status().equals("open"));
128 |
129 | menu.findItem(R.id.menu_view_comments).setVisible((mPost.getComment_count() > 0));
130 |
131 | MenuItem actionItem = menu.findItem(R.id.menu_item_share_action_provider_action_bar);
132 |
133 | mActionProvider = (ShareActionProvider) actionItem.getActionProvider();
134 | mActionProvider.setShareHistoryFileName(ShareActionProvider.DEFAULT_SHARE_HISTORY_FILE_NAME);
135 |
136 | mActionProvider.setShareIntent(createShareIntent());
137 | }
138 | }
139 |
140 | @Override
141 | public void onPrepareOptionsMenu(Menu menu) {
142 |
143 | }
144 |
145 | @Override
146 | public void onStart() {
147 | super.onStart();
148 | }
149 |
150 | @Override
151 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
152 | View rootView = inflater.inflate(R.layout.fragment_post_detail, container, false);
153 |
154 | mWebview = (WebView) rootView.findViewById(R.id.webview);
155 |
156 | mWebview.getSettings().setJavaScriptEnabled(true);
157 | mWebview.setWebViewClient(new MyWebViewClient(this.getActivity()));
158 | if (android.os.Build.VERSION.SDK_INT < 8) {
159 | mWebview.getSettings().setPluginsEnabled(true);
160 | } else {
161 | mWebview.getSettings().setPluginState(PluginState.ON);
162 | }
163 |
164 | mNext = (Button) rootView.findViewById(R.id.next);
165 | mPrevious = (Button) rootView.findViewById(R.id.previous);
166 |
167 | mNext.setOnClickListener(this);
168 | mPrevious.setOnClickListener(this);
169 |
170 | if (mPostIndex == -1) {
171 | mNext.setVisibility(View.GONE);
172 | mPrevious.setVisibility(View.GONE);
173 | }
174 |
175 | if (mPost != null) {
176 | layoutView();
177 | }
178 |
179 | return rootView;
180 | }
181 |
182 | @Override
183 | public boolean onOptionsItemSelected(MenuItem item) {
184 | if (item.getItemId() == R.id.menu_view_comments) {
185 | Intent commentIntent = new Intent(this.getActivity(), CommentListActivity.class);
186 | commentIntent.putExtra(PostDetailFragment.ARG_ITEM_ID, mPostIndex);
187 | startActivity(commentIntent);
188 | return true;
189 | } else if (item.getItemId() == R.id.menu_make_comment) {
190 |
191 | MakeCommentDialog dialog = new MakeCommentDialog();
192 | dialog.setPostId(mPost.getId());
193 | dialog.setCommentMadeListener(this);
194 | dialog.show(getActivity().getSupportFragmentManager(), "MakeCommentDialog");
195 | }
196 | return super.onOptionsItemSelected(item);
197 | }
198 |
199 | private Intent createShareIntent() {
200 | Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
201 |
202 | String shareBody = mPost.getTitle() + " - " + mPost.getUrl();
203 |
204 | sharingIntent.setType("text/plain").putExtra(android.content.Intent.EXTRA_SUBJECT, "Broadsheet.ie")
205 | .putExtra(android.content.Intent.EXTRA_TEXT, shareBody);
206 |
207 | return sharingIntent;
208 | }
209 |
210 | @Override
211 | public void onCommentMade(Comment comment) {
212 | mPost.addComment(comment);
213 | }
214 |
215 | @SuppressLint("SetJavaScriptEnabled")
216 | private void layoutView() {
217 | String postHTML = "";
218 | postHTML += " ";
219 | postHTML += ""
220 | + mPost.getTitle()
221 | + "
";
226 | postHTML += "
" + mPost.getContent() + "
";
227 | postHTML += "
";
228 |
229 | mWebview.loadDataWithBaseURL("file:///android_asset/", postHTML, "text/html", "UTF-8", null);
230 |
231 | if ((mApp != null) && (mApp.getPosts().size() > 0)) {
232 | mNext.setEnabled(((mPostIndex + 1) < mApp.getPosts().size()));
233 | mPrevious.setEnabled((mPostIndex > 0));
234 | }
235 |
236 | getActivity().supportInvalidateOptionsMenu();
237 |
238 | if (mPost != null) {
239 | mApp.getTracker().sendView(
240 | "Post " + Html.fromHtml(mPost.getTitle_plain()) + " " + Integer.toString(mPost.getId()));
241 | }
242 | }
243 |
244 | @Override
245 | public void onClick(View v) {
246 | if (v.getId() == R.id.next) {
247 | mPostIndex++;
248 | } else if (v.getId() == R.id.previous) {
249 | mPostIndex--;
250 | }
251 |
252 | if (mPostIndex == -1) {
253 | return;
254 | }
255 |
256 | mPost = mApp.getPosts().get(mPostIndex);
257 |
258 | layoutView();
259 | }
260 |
261 | // Via
262 | // http://stackoverflow.com/questions/14088623/android-webview-to-play-youtube-videos
263 | public class MyWebViewClient extends WebViewClient {
264 |
265 | public Activity mActivity;
266 |
267 | public MyWebViewClient(Activity activity) {
268 | super();
269 | mActivity = activity;
270 | }
271 |
272 | @Override
273 | public boolean shouldOverrideUrlLoading(WebView view, String url) {
274 | Uri uri = Uri.parse(url);
275 | if (uri.getHost().contains("youtube.com")) {
276 | viewYoutube(mActivity, url);
277 | return true;
278 | }
279 | if (uri.getHost().contains("vimeo.com")) {
280 | viewVimeo(mActivity, url);
281 | return true;
282 | } else if (url.contains("broadsheet.ie/20")) {
283 | viewBroadsheetPost(url);
284 | return true;
285 | }
286 |
287 | return false;
288 | }
289 |
290 | public void viewYoutube(Context context, String url) {
291 | viewWithPackageName(context, url, "com.google.android.youtube");
292 | }
293 |
294 | public void viewVimeo(Context context, String url) {
295 | Intent postIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
296 | startActivity(postIntent);
297 | }
298 |
299 | public void viewBroadsheetPost(String url) {
300 | Intent postIntent = new Intent(getActivity(), PostDetailActivity.class);
301 | postIntent.putExtra(PostDetailFragment.ARG_ITEM_URL, url);
302 | startActivity(postIntent);
303 | }
304 |
305 | public void viewWithPackageName(Context context, String url, String packageName) {
306 | try {
307 | Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
308 | if (isAppInstalled(context, packageName)) {
309 | viewIntent.setPackage(packageName);
310 | }
311 | context.startActivity(viewIntent);
312 | } catch (Exception e) {
313 | Intent viewIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
314 | context.startActivity(viewIntent);
315 | }
316 | }
317 |
318 | public boolean isAppInstalled(Context context, String packageName) {
319 | PackageManager packageManager = context.getPackageManager();
320 | try {
321 | packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
322 | return true;
323 | } catch (NameNotFoundException e) {
324 | }
325 | return false;
326 | }
327 |
328 | @Override
329 | public void onPageFinished(final WebView view, String url) {
330 | String javascript = "javascript:" + "var iframes = document.getElementsByTagName('iframe');"
331 | + "for (var i = 0, l = iframes.length; i < l; i++) {" + " var iframe = iframes[i],"
332 | + " a = document.createElement('a');" + " a.setAttribute('href', iframe.src);"
333 | + " d = document.createElement('div');" + " d.style.width = iframe.offsetWidth + 'px';"
334 | + " d.style.height = iframe.offsetHeight + 'px';" + " d.style.top = iframe.offsetTop + 'px';"
335 | + " d.style.left = iframe.offsetLeft + 'px';" + " d.style.position = 'absolute';"
336 | + " d.style.opacity = '0';" + " d.style.filter = 'alpha(opacity=0)';"
337 | + " d.style.background = 'black';" + " a.appendChild(d);"
338 | + " iframe.offsetParent.appendChild(a);" + "}";
339 | view.loadUrl(javascript);
340 |
341 | super.onPageFinished(view, url);
342 | }
343 | }
344 |
345 | public final class PostListener implements RequestListener {
346 |
347 | @Override
348 | public void onRequestFailure(SpiceException spiceException) {
349 | Log.d(TAG, "Failed to get post");
350 |
351 | ((BaseFragmentActivity) getActivity()).onPostExecute();
352 |
353 | BaseFragmentActivity activity = (BaseFragmentActivity) getActivity();
354 |
355 | activity.showError(getActivity().getString(R.string.post_load_problem));
356 | }
357 |
358 | @Override
359 | public void onRequestSuccess(final SinglePost result) {
360 | Log.d(TAG, "we got a post: " + result.toString());
361 | PostDetailFragment.this.mPost = result.getPost();
362 |
363 | ((BaseFragmentActivity) getActivity()).onPostExecute();
364 |
365 | PostDetailFragment.this.getActivity().invalidateOptionsMenu();
366 |
367 | PostDetailFragment.this.layoutView();
368 | }
369 | }
370 |
371 | @Override
372 | public void onSaveInstanceState(Bundle savedInstanceState) {
373 | Log.d(TAG, "saving instance");
374 |
375 | super.onSaveInstanceState(savedInstanceState);
376 |
377 | if (mPostIndex != -1) {
378 | savedInstanceState.putInt(CURRENT_POST_ID, mPostIndex);
379 | }
380 |
381 | savedInstanceState.putSerializable(CURRENT_POST, mPost);
382 | }
383 | }
384 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/fragments/PostListFragment.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.fragments;
2 |
3 | import ie.broadsheet.app.PostListActivity;
4 | import ie.broadsheet.app.R;
5 | import ie.broadsheet.app.adapters.PostListEndlessAdapter;
6 | import ie.broadsheet.app.adapters.PostListEndlessAdapter.PostListLoadedListener;
7 | import ie.broadsheet.app.dialog.AboutDialog;
8 | import ie.broadsheet.app.dialog.TipDialog;
9 | import android.app.Activity;
10 | import android.app.ProgressDialog;
11 | import android.os.Bundle;
12 | import android.util.Log;
13 | import android.view.LayoutInflater;
14 | import android.view.View;
15 | import android.view.View.OnClickListener;
16 | import android.view.ViewGroup;
17 | import android.widget.FrameLayout;
18 | import android.widget.ListView;
19 |
20 | import com.actionbarsherlock.app.SherlockListFragment;
21 | import com.actionbarsherlock.view.Menu;
22 | import com.actionbarsherlock.view.MenuInflater;
23 | import com.actionbarsherlock.view.MenuItem;
24 | import com.actionbarsherlock.widget.SearchView;
25 | import com.actionbarsherlock.widget.SearchView.OnCloseListener;
26 | import com.actionbarsherlock.widget.SearchView.OnQueryTextListener;
27 | import com.handmark.pulltorefresh.library.PullToRefreshBase;
28 | import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener;
29 | import com.handmark.pulltorefresh.library.PullToRefreshListView;
30 | import com.nostra13.universalimageloader.core.ImageLoader;
31 | import com.nostra13.universalimageloader.core.assist.PauseOnScrollListener;
32 |
33 | /**
34 | * A list fragment representing a list of Posts. This fragment also supports tablet devices by allowing list items to be
35 | * given an 'activated' state upon selection. This helps indicate which item is currently being viewed in a
36 | * {@link PostDetailFragment}.
37 | *
38 | * Activities containing this fragment MUST implement the {@link Callbacks} interface.
39 | */
40 | public class PostListFragment extends SherlockListFragment implements OnQueryTextListener, PostListLoadedListener,
41 | OnClickListener, OnCloseListener {
42 | private static final String TAG = "PostListFragment";
43 |
44 | /**
45 | * The serialization (saved instance state) Bundle key representing the activated item position. Only used on
46 | * tablets.
47 | */
48 | private static final String STATE_ACTIVATED_POSITION = "activated_position";
49 |
50 | /**
51 | * The current activated item position. Only used on tablets.
52 | */
53 | private int mActivatedPosition = ListView.INVALID_POSITION;
54 |
55 | private Callbacks mCallbacks;
56 |
57 | private PostListEndlessAdapter postListAdapter;
58 |
59 | private PullToRefreshListView mPullRefreshListView;
60 |
61 | private SearchView searchView;
62 |
63 | private ProgressDialog searchProgress;
64 |
65 | /**
66 | * A callback interface that all activities containing this fragment must implement. This mechanism allows
67 | * activities to be notified of item selections.
68 | */
69 | public interface Callbacks {
70 | /**
71 | * Callback for when an item has been selected.
72 | */
73 | public void onItemSelected(int id);
74 | }
75 |
76 | /**
77 | * Mandatory empty constructor for the fragment manager to instantiate the fragment (e.g. upon screen orientation
78 | * changes).
79 | */
80 | public PostListFragment() {
81 | setHasOptionsMenu(true);
82 | }
83 |
84 | @Override
85 | public void onCreate(Bundle savedInstanceState) {
86 | super.onCreate(savedInstanceState);
87 | postListAdapter = new PostListEndlessAdapter(this.getActivity());
88 | postListAdapter.setPostListLoadedListener(this);
89 | setListAdapter(postListAdapter);
90 |
91 | searchProgress = new ProgressDialog(getActivity());
92 | searchProgress.setIndeterminate(true);
93 | searchProgress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
94 | }
95 |
96 | @Override
97 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
98 | View layout = super.onCreateView(inflater, container, savedInstanceState);
99 |
100 | // Get original ListView and Frame
101 | ListView originalLv = (ListView) layout.findViewById(android.R.id.list);
102 | ViewGroup frame = (ViewGroup) originalLv.getParent();
103 |
104 | // Remove old ListView
105 | frame.removeView(originalLv);
106 |
107 | // Create new PullToRefreshListView and add to Frame
108 | mPullRefreshListView = new PullToRefreshListView(getActivity());
109 | frame.addView(mPullRefreshListView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
110 | ViewGroup.LayoutParams.MATCH_PARENT));
111 |
112 | mPullRefreshListView.setOnRefreshListener(new OnRefreshListener() {
113 | @Override
114 | public void onRefresh(PullToRefreshBase refreshView) {
115 | fetchPosts(null);
116 | }
117 | });
118 |
119 | boolean pauseOnScroll = false;
120 | boolean pauseOnFling = true;
121 | PauseOnScrollListener listener = new PauseOnScrollListener(ImageLoader.getInstance(), pauseOnScroll,
122 | pauseOnFling);
123 | mPullRefreshListView.setOnScrollListener(listener);
124 |
125 | return layout;
126 | }
127 |
128 | @Override
129 | public void onViewCreated(View view, Bundle savedInstanceState) {
130 | super.onViewCreated(view, savedInstanceState);
131 |
132 | // Restore the previously serialized activated item position.
133 | if (savedInstanceState != null && savedInstanceState.containsKey(STATE_ACTIVATED_POSITION)) {
134 | setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
135 | }
136 |
137 | getListView().setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_INSET);
138 | }
139 |
140 | @Override
141 | public void onPause() {
142 | searchProgress.dismiss();
143 | super.onPause();
144 | }
145 |
146 | @Override
147 | public void onAttach(Activity activity) {
148 | super.onAttach(activity);
149 |
150 | // Activities containing this fragment must implement its callbacks.
151 | if (!(activity instanceof Callbacks)) {
152 | throw new IllegalStateException("Activity must implement fragment's callbacks.");
153 | }
154 |
155 | mCallbacks = (Callbacks) activity;
156 | }
157 |
158 | @Override
159 | public void onDetach() {
160 | super.onDetach();
161 |
162 | mCallbacks = null;
163 | }
164 |
165 | @Override
166 | public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
167 | super.onCreateOptionsMenu(menu, inflater);
168 |
169 | inflater.inflate(R.menu.post_list, menu);
170 |
171 | searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
172 | searchView.setOnQueryTextListener(this);
173 | searchView.setOnSearchClickListener(this);
174 | searchView.setOnCloseListener(this);
175 | }
176 |
177 | @Override
178 | public boolean onOptionsItemSelected(MenuItem item) {
179 |
180 | switch (item.getItemId()) {
181 | case R.id.menu_view_about:
182 | AboutDialog dialog = new AboutDialog();
183 | dialog.show(getActivity().getSupportFragmentManager(), "AboutDialog");
184 | return true;
185 | // break;
186 | case R.id.menu_submit_tip:
187 | TipDialog tipDialog = new TipDialog();
188 | tipDialog.show(getActivity().getSupportFragmentManager(), "TipDialog");
189 | return true;
190 | // break;
191 | }
192 |
193 | return super.onOptionsItemSelected(item);
194 | }
195 |
196 | @Override
197 | public void onListItemClick(ListView listView, View view, int position, long id) {
198 | super.onListItemClick(listView, view, position, id);
199 |
200 | // Notify the active callbacks interface (the activity, if the
201 | // fragment is attached to one) that an item has been selected.
202 | mCallbacks.onItemSelected(position);
203 |
204 | }
205 |
206 | @Override
207 | public void onSaveInstanceState(Bundle outState) {
208 | super.onSaveInstanceState(outState);
209 | if (mActivatedPosition != ListView.INVALID_POSITION) {
210 | // Serialize and persist the activated item position.
211 | outState.putInt(STATE_ACTIVATED_POSITION, mActivatedPosition);
212 | }
213 | }
214 |
215 | /**
216 | * Turns on activate-on-click mode. When this mode is on, list items will be given the 'activated' state when
217 | * touched.
218 | */
219 | public void setActivateOnItemClick(boolean activateOnItemClick) {
220 | // When setting CHOICE_MODE_SINGLE, ListView will automatically
221 | // give items the 'activated' state when touched.
222 | getListView().setChoiceMode(activateOnItemClick ? ListView.CHOICE_MODE_SINGLE : ListView.CHOICE_MODE_NONE);
223 | }
224 |
225 | private void setActivatedPosition(int position) {
226 | if (position == ListView.INVALID_POSITION) {
227 | getListView().setItemChecked(mActivatedPosition, false);
228 | } else {
229 | getListView().setItemChecked(position, true);
230 | }
231 |
232 | mActivatedPosition = position;
233 | }
234 |
235 | @Override
236 | public boolean onQueryTextSubmit(String query) {
237 | Log.i(TAG, "Query to search for: " + query);
238 | fetchPosts(query);
239 |
240 | searchProgress.setMessage(getResources().getString(R.string.searching));
241 | searchProgress.show();
242 |
243 | searchView.clearFocus();
244 |
245 | return false;
246 | }
247 |
248 | @Override
249 | public boolean onQueryTextChange(String newText) {
250 | Log.i(TAG, "Current search term: " + newText);
251 | return false;
252 | }
253 |
254 | @Override
255 | public boolean onClose() {
256 | // fetchPosts(null);
257 |
258 | return false;
259 | }
260 |
261 | @Override
262 | public void onPostListLoaded() {
263 | searchProgress.dismiss();
264 | mPullRefreshListView.onRefreshComplete();
265 |
266 | if ((((PostListActivity) getActivity()).isDualScreen()) && (postListAdapter.getCurrentPage() == 1)) {
267 | Log.d(TAG, "Setting first post");
268 | mCallbacks.onItemSelected(1);
269 | }
270 | }
271 |
272 | @Override
273 | public void onClick(View v) {
274 |
275 | }
276 |
277 | private void fetchPosts(String query) {
278 | postListAdapter.reset();
279 | getListView().setSelection(0);
280 | postListAdapter.setSearchTerm(query);
281 | postListAdapter.fetchPosts();
282 |
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/AttachmentItem.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.io.Serializable;
4 |
5 | import com.google.api.client.util.Key;
6 |
7 | public class AttachmentItem implements Serializable {
8 | private static final long serialVersionUID = 1L;
9 |
10 | @Key
11 | private Image full;
12 |
13 | @Key
14 | private Image thumbnail;
15 |
16 | @Key
17 | private Image medium;
18 |
19 | public Image getFull() {
20 | return full;
21 | }
22 |
23 | public void setFull(Image full) {
24 | this.full = full;
25 | }
26 |
27 | public Image getThumbnail() {
28 | return thumbnail;
29 | }
30 |
31 | public void setThumbnail(Image thumbnail) {
32 | this.thumbnail = thumbnail;
33 | }
34 |
35 | public Image getMedium() {
36 | return medium;
37 | }
38 |
39 | public void setMedium(Image medium) {
40 | this.medium = medium;
41 | }
42 |
43 | @Override
44 | public int hashCode() {
45 | final int prime = 31;
46 | int result = 1;
47 | result = prime * result + ((full == null) ? 0 : full.hashCode());
48 | result = prime * result + ((medium == null) ? 0 : medium.hashCode());
49 | result = prime * result + ((thumbnail == null) ? 0 : thumbnail.hashCode());
50 | return result;
51 | }
52 |
53 | @Override
54 | public boolean equals(Object obj) {
55 | if (this == obj)
56 | return true;
57 | if (obj == null)
58 | return false;
59 | if (getClass() != obj.getClass())
60 | return false;
61 | AttachmentItem other = (AttachmentItem) obj;
62 | if (full == null) {
63 | if (other.full != null)
64 | return false;
65 | } else if (!full.equals(other.full))
66 | return false;
67 | if (medium == null) {
68 | if (other.medium != null)
69 | return false;
70 | } else if (!medium.equals(other.medium))
71 | return false;
72 | if (thumbnail == null) {
73 | if (other.thumbnail != null)
74 | return false;
75 | } else if (!thumbnail.equals(other.thumbnail))
76 | return false;
77 | return true;
78 | }
79 |
80 | @Override
81 | public String toString() {
82 | return "AttachmentItem [full=" + full + ", thumbnail=" + thumbnail + ", medium=" + medium + "]";
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/Attachments.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.io.Serializable;
4 |
5 | import com.google.api.client.util.Key;
6 |
7 | public class Attachments implements Serializable {
8 | private static final long serialVersionUID = 1L;
9 |
10 | @Key
11 | private int id;
12 |
13 | @Key
14 | private String url;
15 |
16 | @Key
17 | private String slug;
18 |
19 | @Key
20 | private String title;
21 |
22 | @Key
23 | private String description;
24 |
25 | @Key
26 | private String caption;
27 |
28 | @Key
29 | private int parent;
30 |
31 | @Key
32 | private String mime_type;
33 |
34 | @Key
35 | private AttachmentItem images;
36 |
37 | public int getId() {
38 | return id;
39 | }
40 |
41 | public void setId(int id) {
42 | this.id = id;
43 | }
44 |
45 | public String getUrl() {
46 | return url;
47 | }
48 |
49 | public void setUrl(String url) {
50 | this.url = url;
51 | }
52 |
53 | public String getSlug() {
54 | return slug;
55 | }
56 |
57 | public void setSlug(String slug) {
58 | this.slug = slug;
59 | }
60 |
61 | public String getTitle() {
62 | return title;
63 | }
64 |
65 | public void setTitle(String title) {
66 | this.title = title;
67 | }
68 |
69 | public String getDescription() {
70 | return description;
71 | }
72 |
73 | public void setDescription(String description) {
74 | this.description = description;
75 | }
76 |
77 | public String getCaption() {
78 | return caption;
79 | }
80 |
81 | public void setCaption(String caption) {
82 | this.caption = caption;
83 | }
84 |
85 | public int getParent() {
86 | return parent;
87 | }
88 |
89 | public void setParent(int parent) {
90 | this.parent = parent;
91 | }
92 |
93 | public String getMime_type() {
94 | return mime_type;
95 | }
96 |
97 | public void setMime_type(String mime_type) {
98 | this.mime_type = mime_type;
99 | }
100 |
101 | public AttachmentItem getImages() {
102 | return images;
103 | }
104 |
105 | public void setImages(AttachmentItem images) {
106 | this.images = images;
107 | }
108 |
109 | @Override
110 | public int hashCode() {
111 | final int prime = 31;
112 | int result = 1;
113 | result = prime * result + ((caption == null) ? 0 : caption.hashCode());
114 | result = prime * result + ((description == null) ? 0 : description.hashCode());
115 | result = prime * result + id;
116 | result = prime * result + ((images == null) ? 0 : images.hashCode());
117 | result = prime * result + ((mime_type == null) ? 0 : mime_type.hashCode());
118 | result = prime * result + parent;
119 | result = prime * result + ((slug == null) ? 0 : slug.hashCode());
120 | result = prime * result + ((title == null) ? 0 : title.hashCode());
121 | result = prime * result + ((url == null) ? 0 : url.hashCode());
122 | return result;
123 | }
124 |
125 | @Override
126 | public boolean equals(Object obj) {
127 | if (this == obj)
128 | return true;
129 | if (obj == null)
130 | return false;
131 | if (getClass() != obj.getClass())
132 | return false;
133 | Attachments other = (Attachments) obj;
134 | if (caption == null) {
135 | if (other.caption != null)
136 | return false;
137 | } else if (!caption.equals(other.caption))
138 | return false;
139 | if (description == null) {
140 | if (other.description != null)
141 | return false;
142 | } else if (!description.equals(other.description))
143 | return false;
144 | if (id != other.id)
145 | return false;
146 | if (images == null) {
147 | if (other.images != null)
148 | return false;
149 | } else if (!images.equals(other.images))
150 | return false;
151 | if (mime_type == null) {
152 | if (other.mime_type != null)
153 | return false;
154 | } else if (!mime_type.equals(other.mime_type))
155 | return false;
156 | if (parent != other.parent)
157 | return false;
158 | if (slug == null) {
159 | if (other.slug != null)
160 | return false;
161 | } else if (!slug.equals(other.slug))
162 | return false;
163 | if (title == null) {
164 | if (other.title != null)
165 | return false;
166 | } else if (!title.equals(other.title))
167 | return false;
168 | if (url == null) {
169 | if (other.url != null)
170 | return false;
171 | } else if (!url.equals(other.url))
172 | return false;
173 | return true;
174 | }
175 |
176 | @Override
177 | public String toString() {
178 | return "Attachments [id=" + id + ", url=" + url + ", slug=" + slug + ", title=" + title + ", description="
179 | + description + ", caption=" + caption + ", parent=" + parent + ", mime_type=" + mime_type
180 | + ", images=" + images + "]";
181 | }
182 |
183 | }
184 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/Author.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.io.Serializable;
4 |
5 | import com.google.api.client.util.Key;
6 |
7 | public class Author implements Serializable {
8 | private static final long serialVersionUID = 1L;
9 |
10 | @Key
11 | private int id;
12 |
13 | @Key
14 | private String slug;
15 |
16 | @Key
17 | private String name;
18 |
19 | @Key
20 | private String first_name;
21 |
22 | @Key
23 | private String last_name;
24 |
25 | @Key
26 | private String nickname;
27 |
28 | @Key
29 | private String url;
30 |
31 | @Key
32 | private String description;
33 |
34 | public int getId() {
35 | return id;
36 | }
37 |
38 | public void setId(int id) {
39 | this.id = id;
40 | }
41 |
42 | public String getSlug() {
43 | return slug;
44 | }
45 |
46 | public void setSlug(String slug) {
47 | this.slug = slug;
48 | }
49 |
50 | public String getName() {
51 | return name;
52 | }
53 |
54 | public void setName(String name) {
55 | this.name = name;
56 | }
57 |
58 | public String getFirst_name() {
59 | return first_name;
60 | }
61 |
62 | public void setFirst_name(String first_name) {
63 | this.first_name = first_name;
64 | }
65 |
66 | public String getLast_name() {
67 | return last_name;
68 | }
69 |
70 | public void setLast_name(String last_name) {
71 | this.last_name = last_name;
72 | }
73 |
74 | public String getNickname() {
75 | return nickname;
76 | }
77 |
78 | public void setNickname(String nickname) {
79 | this.nickname = nickname;
80 | }
81 |
82 | public String getUrl() {
83 | return url;
84 | }
85 |
86 | public void setUrl(String url) {
87 | this.url = url;
88 | }
89 |
90 | public String getDescription() {
91 | return description;
92 | }
93 |
94 | public void setDescription(String description) {
95 | this.description = description;
96 | }
97 |
98 | @Override
99 | public int hashCode() {
100 | final int prime = 31;
101 | int result = 1;
102 | result = prime * result + ((description == null) ? 0 : description.hashCode());
103 | result = prime * result + ((first_name == null) ? 0 : first_name.hashCode());
104 | result = prime * result + id;
105 | result = prime * result + ((last_name == null) ? 0 : last_name.hashCode());
106 | result = prime * result + ((name == null) ? 0 : name.hashCode());
107 | result = prime * result + ((nickname == null) ? 0 : nickname.hashCode());
108 | result = prime * result + ((slug == null) ? 0 : slug.hashCode());
109 | result = prime * result + ((url == null) ? 0 : url.hashCode());
110 | return result;
111 | }
112 |
113 | @Override
114 | public boolean equals(Object obj) {
115 | if (this == obj)
116 | return true;
117 | if (obj == null)
118 | return false;
119 | if (getClass() != obj.getClass())
120 | return false;
121 | Author other = (Author) obj;
122 | if (description == null) {
123 | if (other.description != null)
124 | return false;
125 | } else if (!description.equals(other.description))
126 | return false;
127 | if (first_name == null) {
128 | if (other.first_name != null)
129 | return false;
130 | } else if (!first_name.equals(other.first_name))
131 | return false;
132 | if (id != other.id)
133 | return false;
134 | if (last_name == null) {
135 | if (other.last_name != null)
136 | return false;
137 | } else if (!last_name.equals(other.last_name))
138 | return false;
139 | if (name == null) {
140 | if (other.name != null)
141 | return false;
142 | } else if (!name.equals(other.name))
143 | return false;
144 | if (nickname == null) {
145 | if (other.nickname != null)
146 | return false;
147 | } else if (!nickname.equals(other.nickname))
148 | return false;
149 | if (slug == null) {
150 | if (other.slug != null)
151 | return false;
152 | } else if (!slug.equals(other.slug))
153 | return false;
154 | if (url == null) {
155 | if (other.url != null)
156 | return false;
157 | } else if (!url.equals(other.url))
158 | return false;
159 | return true;
160 | }
161 |
162 | @Override
163 | public String toString() {
164 | return "Author [id=" + id + ", slug=" + slug + ", name=" + name + ", first_name=" + first_name + ", last_name="
165 | + last_name + ", nickname=" + nickname + ", url=" + url + ", description=" + description + "]";
166 | }
167 |
168 | }
169 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/Category.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.io.Serializable;
4 |
5 | import com.google.api.client.util.Key;
6 |
7 | public class Category implements Serializable {
8 | private static final long serialVersionUID = 1L;
9 |
10 | @Key
11 | private int id;
12 |
13 | @Key
14 | private String slug;
15 |
16 | @Key
17 | private String title;
18 |
19 | @Key
20 | private String description;
21 |
22 | @Key
23 | private int parent;
24 |
25 | @Key
26 | private int post_count;
27 |
28 | public int getId() {
29 | return id;
30 | }
31 |
32 | public void setId(int id) {
33 | this.id = id;
34 | }
35 |
36 | public String getSlug() {
37 | return slug;
38 | }
39 |
40 | public void setSlug(String slug) {
41 | this.slug = slug;
42 | }
43 |
44 | public String getTitle() {
45 | return title;
46 | }
47 |
48 | public void setTitle(String title) {
49 | this.title = title;
50 | }
51 |
52 | public String getDescription() {
53 | return description;
54 | }
55 |
56 | public void setDescription(String description) {
57 | this.description = description;
58 | }
59 |
60 | public int getParent() {
61 | return parent;
62 | }
63 |
64 | public void setParent(int parent) {
65 | this.parent = parent;
66 | }
67 |
68 | public int getPost_count() {
69 | return post_count;
70 | }
71 |
72 | public void setPost_count(int post_count) {
73 | this.post_count = post_count;
74 | }
75 |
76 | @Override
77 | public int hashCode() {
78 | final int prime = 31;
79 | int result = 1;
80 | result = prime * result + ((description == null) ? 0 : description.hashCode());
81 | result = prime * result + id;
82 | result = prime * result + parent;
83 | result = prime * result + post_count;
84 | result = prime * result + ((slug == null) ? 0 : slug.hashCode());
85 | result = prime * result + ((title == null) ? 0 : title.hashCode());
86 | return result;
87 | }
88 |
89 | @Override
90 | public boolean equals(Object obj) {
91 | if (this == obj)
92 | return true;
93 | if (obj == null)
94 | return false;
95 | if (getClass() != obj.getClass())
96 | return false;
97 | Category other = (Category) obj;
98 | if (description == null) {
99 | if (other.description != null)
100 | return false;
101 | } else if (!description.equals(other.description))
102 | return false;
103 | if (id != other.id)
104 | return false;
105 | if (parent != other.parent)
106 | return false;
107 | if (post_count != other.post_count)
108 | return false;
109 | if (slug == null) {
110 | if (other.slug != null)
111 | return false;
112 | } else if (!slug.equals(other.slug))
113 | return false;
114 | if (title == null) {
115 | if (other.title != null)
116 | return false;
117 | } else if (!title.equals(other.title))
118 | return false;
119 | return true;
120 | }
121 |
122 | @Override
123 | public String toString() {
124 | return "Category [id=" + id + ", slug=" + slug + ", title=" + title + ", description=" + description
125 | + ", parent=" + parent + ", post_count=" + post_count + "]";
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/Comment.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.io.Serializable;
4 | import java.text.ParseException;
5 | import java.text.SimpleDateFormat;
6 | import java.util.Date;
7 | import java.util.TreeMap;
8 |
9 | import android.annotation.SuppressLint;
10 | import android.text.format.DateUtils;
11 |
12 | import com.google.api.client.util.Key;
13 |
14 | public class Comment implements Serializable {
15 | private static final long serialVersionUID = 1L;
16 |
17 | @Key
18 | private int id;
19 |
20 | @Key
21 | private String name;
22 |
23 | @Key
24 | private String url;
25 |
26 | @Key
27 | private String date;
28 |
29 | @Key
30 | private String content;
31 |
32 | @Key
33 | private int parent;
34 |
35 | @Key
36 | private String avatar;
37 |
38 | @Key
39 | private String status;
40 |
41 | private String relativeTime;
42 |
43 | private TreeMap childComment;
44 |
45 | private int childLevel = 0;
46 |
47 | public int getId() {
48 | return id;
49 | }
50 |
51 | public void setId(int id) {
52 | this.id = id;
53 | }
54 |
55 | public String getName() {
56 | return name;
57 | }
58 |
59 | public void setName(String name) {
60 | this.name = name;
61 | }
62 |
63 | public String getUrl() {
64 | return url;
65 | }
66 |
67 | public void setUrl(String url) {
68 | this.url = url;
69 | }
70 |
71 | public String getDate() {
72 | return date;
73 | }
74 |
75 | public void setDate(String date) {
76 | this.date = date;
77 | }
78 |
79 | public String getContent() {
80 | return content;
81 | }
82 |
83 | public void setContent(String content) {
84 | this.content = content;
85 | }
86 |
87 | public int getParent() {
88 | return parent;
89 | }
90 |
91 | public void setParent(int parent) {
92 | this.parent = parent;
93 | }
94 |
95 | public String getAvatar() {
96 | return avatar;
97 | }
98 |
99 | public void setAvatar(String avatar) {
100 | this.avatar = avatar;
101 | }
102 |
103 | public String getStatus() {
104 | return status;
105 | }
106 |
107 | public void setStatus(String status) {
108 | this.status = status;
109 | }
110 |
111 | public TreeMap getChildComment() {
112 | return childComment;
113 | }
114 |
115 | public void setChildComment(TreeMap childComment) {
116 | this.childComment = childComment;
117 | }
118 |
119 | public int getChildLevel() {
120 | return childLevel;
121 | }
122 |
123 | public void setChildLevel(int childLevel) {
124 | this.childLevel = childLevel;
125 | }
126 |
127 | @Override
128 | public int hashCode() {
129 | final int prime = 31;
130 | int result = 1;
131 | result = prime * result + ((avatar == null) ? 0 : avatar.hashCode());
132 | result = prime * result + ((content == null) ? 0 : content.hashCode());
133 | result = prime * result + ((date == null) ? 0 : date.hashCode());
134 | result = prime * result + id;
135 | result = prime * result + ((name == null) ? 0 : name.hashCode());
136 | result = prime * result + parent;
137 | result = prime * result + ((status == null) ? 0 : status.hashCode());
138 | result = prime * result + ((url == null) ? 0 : url.hashCode());
139 | return result;
140 | }
141 |
142 | @Override
143 | public boolean equals(Object obj) {
144 | if (this == obj)
145 | return true;
146 | if (obj == null)
147 | return false;
148 | if (getClass() != obj.getClass())
149 | return false;
150 | Comment other = (Comment) obj;
151 | if (avatar == null) {
152 | if (other.avatar != null)
153 | return false;
154 | } else if (!avatar.equals(other.avatar))
155 | return false;
156 | if (content == null) {
157 | if (other.content != null)
158 | return false;
159 | } else if (!content.equals(other.content))
160 | return false;
161 | if (date == null) {
162 | if (other.date != null)
163 | return false;
164 | } else if (!date.equals(other.date))
165 | return false;
166 | if (id != other.id)
167 | return false;
168 | if (name == null) {
169 | if (other.name != null)
170 | return false;
171 | } else if (!name.equals(other.name))
172 | return false;
173 | if (parent != other.parent)
174 | return false;
175 | if (status == null) {
176 | if (other.status != null)
177 | return false;
178 | } else if (!status.equals(other.status))
179 | return false;
180 | if (url == null) {
181 | if (other.url != null)
182 | return false;
183 | } else if (!url.equals(other.url))
184 | return false;
185 | return true;
186 | }
187 |
188 | @Override
189 | public String toString() {
190 | return "Comment [id=" + id + ", name=" + name + ", url=" + url + ", date=" + date + ", content=" + content
191 | + ", parent=" + parent + ", avatar=" + avatar + ", status=" + status + "]";
192 | }
193 |
194 | @SuppressLint("SimpleDateFormat")
195 | public String getRelativeTime() {
196 | if (relativeTime == null) {
197 | relativeTime = "";
198 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
199 | Date result = null;
200 | try {
201 | result = df.parse(this.date);
202 | relativeTime = (String) DateUtils.getRelativeTimeSpanString(result.getTime(), new Date().getTime(),
203 | DateUtils.MINUTE_IN_MILLIS);
204 |
205 | } catch (ParseException e) {
206 | // TODO Auto-generated catch block
207 | e.printStackTrace();
208 | }
209 | }
210 | return relativeTime;
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/Image.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.io.Serializable;
4 |
5 | import com.google.api.client.util.Key;
6 |
7 | public class Image implements Serializable {
8 | private static final long serialVersionUID = 1L;
9 |
10 | @Key
11 | private String url;
12 |
13 | @Key
14 | private int width;
15 |
16 | @Key
17 | private int height;
18 |
19 | public String getUrl() {
20 | return url;
21 | }
22 |
23 | public void setUrl(String url) {
24 | this.url = url;
25 | }
26 |
27 | public int getWidth() {
28 | return width;
29 | }
30 |
31 | public void setWidth(int width) {
32 | this.width = width;
33 | }
34 |
35 | public int getHeight() {
36 | return height;
37 | }
38 |
39 | public void setHeight(int height) {
40 | this.height = height;
41 | }
42 |
43 | @Override
44 | public int hashCode() {
45 | final int prime = 31;
46 | int result = 1;
47 | result = prime * result + height;
48 | result = prime * result + ((url == null) ? 0 : url.hashCode());
49 | result = prime * result + width;
50 | return result;
51 | }
52 |
53 | @Override
54 | public boolean equals(Object obj) {
55 | if (this == obj)
56 | return true;
57 | if (obj == null)
58 | return false;
59 | if (getClass() != obj.getClass())
60 | return false;
61 | Image other = (Image) obj;
62 | if (height != other.height)
63 | return false;
64 | if (url == null) {
65 | if (other.url != null)
66 | return false;
67 | } else if (!url.equals(other.url))
68 | return false;
69 | if (width != other.width)
70 | return false;
71 | return true;
72 | }
73 |
74 | @Override
75 | public String toString() {
76 | return "Image [url=" + url + ", width=" + width + ", height=" + height + "]";
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/Post.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.io.Serializable;
4 | import java.text.ParseException;
5 | import java.text.SimpleDateFormat;
6 | import java.util.ArrayList;
7 | import java.util.Date;
8 | import java.util.Iterator;
9 | import java.util.List;
10 | import java.util.SortedSet;
11 | import java.util.TreeMap;
12 | import java.util.TreeSet;
13 |
14 | import android.annotation.SuppressLint;
15 | import android.text.format.DateUtils;
16 |
17 | import com.google.api.client.util.Key;
18 |
19 | public class Post implements Serializable {
20 | private static final long serialVersionUID = 1L;
21 |
22 | @Key
23 | private int id;
24 |
25 | @Key
26 | private String type;
27 |
28 | @Key
29 | private String slug;
30 |
31 | @Key
32 | private String url;
33 |
34 | @Key
35 | private String status;
36 |
37 | @Key
38 | private String title;
39 |
40 | @Key
41 | private String title_plain;
42 |
43 | @Key
44 | private String content;
45 |
46 | @Key
47 | private String excerpt;
48 |
49 | @Key
50 | private String date;
51 |
52 | @Key
53 | private String modified;
54 |
55 | @Key
56 | private List categories;
57 |
58 | @Key
59 | private List tags;
60 |
61 | @Key
62 | private Author author;
63 |
64 | @Key
65 | private List comments;
66 |
67 | private List sortedComments = null;
68 |
69 | @Key
70 | private int comment_count;
71 |
72 | @Key
73 | private String comment_status;
74 |
75 | @Key
76 | private List attachments;
77 |
78 | private String relativeTime;
79 |
80 | public int getId() {
81 | return id;
82 | }
83 |
84 | public void setId(int id) {
85 | this.id = id;
86 | }
87 |
88 | public String getType() {
89 | return type;
90 | }
91 |
92 | public void setType(String type) {
93 | this.type = type;
94 | }
95 |
96 | public String getSlug() {
97 | return slug;
98 | }
99 |
100 | public void setSlug(String slug) {
101 | this.slug = slug;
102 | }
103 |
104 | public String getUrl() {
105 | return url;
106 | }
107 |
108 | public void setUrl(String url) {
109 | this.url = url;
110 | }
111 |
112 | public String getStatus() {
113 | return status;
114 | }
115 |
116 | public void setStatus(String status) {
117 | this.status = status;
118 | }
119 |
120 | public String getTitle() {
121 | return title;
122 | }
123 |
124 | public void setTitle(String title) {
125 | this.title = title;
126 | }
127 |
128 | public String getTitle_plain() {
129 | return title_plain;
130 | }
131 |
132 | public void setTitle_plain(String title_plain) {
133 | this.title_plain = title_plain;
134 | }
135 |
136 | public String getContent() {
137 | return content;
138 | }
139 |
140 | public void setContent(String content) {
141 | this.content = content;
142 | }
143 |
144 | public String getExcerpt() {
145 | return excerpt;
146 | }
147 |
148 | public void setExcerpt(String excerpt) {
149 | this.excerpt = excerpt;
150 | }
151 |
152 | public String getDate() {
153 | return date;
154 | }
155 |
156 | public void setDate(String date) {
157 | this.date = date;
158 | }
159 |
160 | public String getModified() {
161 | return modified;
162 | }
163 |
164 | public void setModified(String modified) {
165 | this.modified = modified;
166 | }
167 |
168 | public List getCategories() {
169 | return categories;
170 | }
171 |
172 | public void setCategories(List categories) {
173 | this.categories = categories;
174 | }
175 |
176 | public List getTags() {
177 | return tags;
178 | }
179 |
180 | public void setTags(List tags) {
181 | this.tags = tags;
182 | }
183 |
184 | public Author getAuthor() {
185 | return author;
186 | }
187 |
188 | public void setAuthor(Author author) {
189 | this.author = author;
190 | }
191 |
192 | public List getComments() {
193 | return comments;
194 | }
195 |
196 | public void setComments(List comments) {
197 | this.comments = comments;
198 | }
199 |
200 | public int getComment_count() {
201 | return comment_count;
202 | }
203 |
204 | public void setComment_count(int comment_count) {
205 | this.comment_count = comment_count;
206 | }
207 |
208 | public String getComment_status() {
209 | return comment_status;
210 | }
211 |
212 | public void setComment_status(String comment_status) {
213 | this.comment_status = comment_status;
214 | }
215 |
216 | public List getAttachments() {
217 | return attachments;
218 | }
219 |
220 | public void setAttachments(List attachments) {
221 | this.attachments = attachments;
222 | }
223 |
224 | @Override
225 | public int hashCode() {
226 | final int prime = 31;
227 | int result = 1;
228 | result = prime * result + ((attachments == null) ? 0 : attachments.hashCode());
229 | result = prime * result + ((author == null) ? 0 : author.hashCode());
230 | result = prime * result + ((categories == null) ? 0 : categories.hashCode());
231 | result = prime * result + comment_count;
232 | result = prime * result + ((comment_status == null) ? 0 : comment_status.hashCode());
233 | result = prime * result + ((comments == null) ? 0 : comments.hashCode());
234 | result = prime * result + ((content == null) ? 0 : content.hashCode());
235 | result = prime * result + ((date == null) ? 0 : date.hashCode());
236 | result = prime * result + ((excerpt == null) ? 0 : excerpt.hashCode());
237 | result = prime * result + id;
238 | result = prime * result + ((modified == null) ? 0 : modified.hashCode());
239 | result = prime * result + ((slug == null) ? 0 : slug.hashCode());
240 | result = prime * result + ((status == null) ? 0 : status.hashCode());
241 | result = prime * result + ((tags == null) ? 0 : tags.hashCode());
242 | result = prime * result + ((title == null) ? 0 : title.hashCode());
243 | result = prime * result + ((title_plain == null) ? 0 : title_plain.hashCode());
244 | result = prime * result + ((type == null) ? 0 : type.hashCode());
245 | result = prime * result + ((url == null) ? 0 : url.hashCode());
246 | return result;
247 | }
248 |
249 | @Override
250 | public boolean equals(Object obj) {
251 | if (this == obj)
252 | return true;
253 | if (obj == null)
254 | return false;
255 | if (getClass() != obj.getClass())
256 | return false;
257 | Post other = (Post) obj;
258 |
259 | if (attachments == null) {
260 | if (other.attachments != null)
261 | return false;
262 | } else if (!attachments.equals(other.attachments))
263 | return false;
264 |
265 | if (author == null) {
266 | if (other.author != null)
267 | return false;
268 | } else if (!author.equals(other.author))
269 | return false;
270 | if (categories == null) {
271 | if (other.categories != null)
272 | return false;
273 | } else if (!categories.equals(other.categories))
274 | return false;
275 | if (comment_count != other.comment_count)
276 | return false;
277 | if (comment_status == null) {
278 | if (other.comment_status != null)
279 | return false;
280 | } else if (!comment_status.equals(other.comment_status))
281 | return false;
282 | if (comments == null) {
283 | if (other.comments != null)
284 | return false;
285 | } else if (!comments.equals(other.comments))
286 | return false;
287 | if (content == null) {
288 | if (other.content != null)
289 | return false;
290 | } else if (!content.equals(other.content))
291 | return false;
292 | if (date == null) {
293 | if (other.date != null)
294 | return false;
295 | } else if (!date.equals(other.date))
296 | return false;
297 | if (excerpt == null) {
298 | if (other.excerpt != null)
299 | return false;
300 | } else if (!excerpt.equals(other.excerpt))
301 | return false;
302 | if (id != other.id)
303 | return false;
304 | if (modified == null) {
305 | if (other.modified != null)
306 | return false;
307 | } else if (!modified.equals(other.modified))
308 | return false;
309 | if (slug == null) {
310 | if (other.slug != null)
311 | return false;
312 | } else if (!slug.equals(other.slug))
313 | return false;
314 | if (status == null) {
315 | if (other.status != null)
316 | return false;
317 | } else if (!status.equals(other.status))
318 | return false;
319 | if (tags == null) {
320 | if (other.tags != null)
321 | return false;
322 | } else if (!tags.equals(other.tags))
323 | return false;
324 | if (title == null) {
325 | if (other.title != null)
326 | return false;
327 | } else if (!title.equals(other.title))
328 | return false;
329 | if (title_plain == null) {
330 | if (other.title_plain != null)
331 | return false;
332 | } else if (!title_plain.equals(other.title_plain))
333 | return false;
334 | if (type == null) {
335 | if (other.type != null)
336 | return false;
337 | } else if (!type.equals(other.type))
338 | return false;
339 | if (url == null) {
340 | if (other.url != null)
341 | return false;
342 | } else if (!url.equals(other.url))
343 | return false;
344 | return true;
345 | }
346 |
347 | @Override
348 | public String toString() {
349 | return "Post [id=" + id + ", type=" + type + ", slug=" + slug + ", url=" + url + ", status=" + status
350 | + ", title=" + title + ", title_plain=" + title_plain + ", content=" + content + ", excerpt=" + excerpt
351 | + ", date=" + date + ", modified=" + modified + ", categories=" + categories + ", tags=" + tags
352 | + ", author=" + author + ", comments=" + comments + ", comment_count=" + comment_count
353 | + ", comment_status=" + comment_status + ", attachments=" + attachments + "]";
354 | }
355 |
356 | public String getCommentCountString() {
357 | String comments;
358 |
359 | if (comment_count == 0) {
360 | comments = "No comments yet";
361 | } else if (comment_count == 1) {
362 | comments = "1 comment";
363 | } else {
364 | comments = Integer.toString(comment_count) + " comments";
365 | }
366 | return comments;
367 | }
368 |
369 | public String getFeaturedImage() {
370 | String imageUrl = null;
371 |
372 | if (attachments.size() > 0) {
373 | AttachmentItem image = (AttachmentItem) ((Attachments) attachments.get(0)).getImages();
374 |
375 | if (image != null) {
376 | Image thumbnail = image.getFull();
377 |
378 | if (thumbnail != null) {
379 | imageUrl = thumbnail.getUrl();
380 | }
381 | }
382 | }
383 |
384 | return imageUrl;
385 | }
386 |
387 | @SuppressLint("SimpleDateFormat")
388 | public String getRelativeTime() {
389 | if (relativeTime == null) {
390 | relativeTime = "";
391 | SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
392 | Date result = null;
393 | try {
394 | result = df.parse(this.date);
395 | relativeTime = (String) DateUtils.getRelativeTimeSpanString(result.getTime(), new Date().getTime(),
396 | DateUtils.MINUTE_IN_MILLIS);
397 |
398 | } catch (ParseException e) {
399 | // TODO Auto-generated catch block
400 | e.printStackTrace();
401 | }
402 | }
403 | return relativeTime;
404 | }
405 |
406 | public List getSortedComments() {
407 | if (sortedComments == null) {
408 | sortComments();
409 | }
410 |
411 | return sortedComments;
412 | }
413 |
414 | private void sortComments() {
415 | TreeMap allCommentsMap = new TreeMap();
416 | for (Iterator iterator = comments.iterator(); iterator.hasNext();) {
417 | Comment item = (Comment) iterator.next();
418 |
419 | item.setChildComment(new TreeMap());
420 | allCommentsMap.put(Integer.toString(item.getId()), item);
421 | }
422 |
423 | TreeMap commentParents = new TreeMap();
424 |
425 | TreeMap allComments = new TreeMap();
426 |
427 | SortedSet keys = new TreeSet(allCommentsMap.keySet());
428 | for (String key : keys) {
429 | Comment comment = allCommentsMap.get(key);
430 |
431 | if (comment.getParent() > 0) {
432 | Comment parentComment = allCommentsMap.get(Integer.toString(comment.getParent()));
433 |
434 | if (parentComment != null) {
435 | if (parentComment.getChildComment().size() > 0) {
436 | parentComment.getChildComment().put(key, comment);
437 | } else {
438 | TreeMap childer = new TreeMap();
439 | childer.put(key, comment);
440 | parentComment.setChildComment(childer);
441 | }
442 |
443 | comment.setChildLevel(parentComment.getChildLevel() + 1);
444 |
445 | allComments.put(Integer.toString(parentComment.getId()), parentComment);
446 | } else {
447 | commentParents.put(key, comment);
448 | }
449 | } else {
450 | commentParents.put(key, comment);
451 | }
452 | }
453 |
454 | sortedComments = new ArrayList();
455 |
456 | SortedSet parentkeys = new TreeSet(allCommentsMap.keySet());
457 | for (String key : parentkeys) {
458 | Comment comment = commentParents.get(key);
459 |
460 | if (comment != null) {
461 | sortedComments.add(comment);
462 |
463 | if ((comment.getChildComment() != null) && (comment.getChildComment().size() > 0)) {
464 | // sortedComments.addAll(flattenComments(comment.getChildComment()));
465 | for (Comment addcomment : flattenComments(comment.getChildComment())) {
466 | sortedComments.add(addcomment);
467 | }
468 | }
469 | }
470 | }
471 |
472 | }
473 |
474 | public List flattenComments(TreeMap comments) {
475 | List flattened = new ArrayList();
476 |
477 | SortedSet parentkeys = new TreeSet(comments.keySet());
478 | for (String key : parentkeys) {
479 | Comment comment = comments.get(key);
480 |
481 | flattened.add(comment);
482 |
483 | if (comment.getChildComment().size() > 0) {
484 | flattened.addAll(flattenComments(comment.getChildComment()));
485 | }
486 | }
487 |
488 | return flattened;
489 |
490 | }
491 |
492 | public void addComment(Comment comment) {
493 | comments.add(comment);
494 |
495 | sortComments();
496 | }
497 | }
498 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/PostList.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.io.Serializable;
4 | import java.util.List;
5 |
6 | import com.google.api.client.util.Key;
7 |
8 | public class PostList implements Serializable {
9 | private static final long serialVersionUID = 1L;
10 |
11 | @Key
12 | private String status;
13 |
14 | @Key
15 | private int count;
16 |
17 | @Key
18 | private int count_total;
19 |
20 | @Key
21 | private int pages;
22 |
23 | @Key
24 | private List posts;
25 |
26 | public String getStatus() {
27 | return status;
28 | }
29 |
30 | public void setStatus(String status) {
31 | this.status = status;
32 | }
33 |
34 | public int getCount() {
35 | return count;
36 | }
37 |
38 | public void setCount(int count) {
39 | this.count = count;
40 | }
41 |
42 | public int getCount_total() {
43 | return count_total;
44 | }
45 |
46 | public void setCount_total(int count_total) {
47 | this.count_total = count_total;
48 | }
49 |
50 | public int getPages() {
51 | return pages;
52 | }
53 |
54 | public void setPages(int pages) {
55 | this.pages = pages;
56 | }
57 |
58 | public List getPosts() {
59 | return posts;
60 | }
61 |
62 | public void setPosts(List posts) {
63 | this.posts = posts;
64 | }
65 |
66 | @Override
67 | public int hashCode() {
68 | final int prime = 31;
69 | int result = 1;
70 | result = prime * result + count;
71 | result = prime * result + count_total;
72 | result = prime * result + pages;
73 | result = prime * result + ((posts == null) ? 0 : posts.hashCode());
74 | result = prime * result + ((status == null) ? 0 : status.hashCode());
75 | return result;
76 | }
77 |
78 | @Override
79 | public boolean equals(Object obj) {
80 | if (this == obj)
81 | return true;
82 | if (obj == null)
83 | return false;
84 | if (getClass() != obj.getClass())
85 | return false;
86 | PostList other = (PostList) obj;
87 | if (count != other.count)
88 | return false;
89 | if (count_total != other.count_total)
90 | return false;
91 | if (pages != other.pages)
92 | return false;
93 | if (posts == null) {
94 | if (other.posts != null)
95 | return false;
96 | } else if (!posts.equals(other.posts))
97 | return false;
98 | if (status == null) {
99 | if (other.status != null)
100 | return false;
101 | } else if (!status.equals(other.status))
102 | return false;
103 | return true;
104 | }
105 |
106 | @Override
107 | public String toString() {
108 | return "PostList [status=" + status + ", count=" + count + ", count_total=" + count_total + ", pages=" + pages
109 | + ", posts=" + posts + "]";
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/ResponseData.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import com.google.api.client.util.Key;
4 |
5 | public class ResponseData {
6 | @Key
7 | private String message;
8 |
9 | @Override
10 | public String toString() {
11 | return "ResponseData [message=" + message + "]";
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/SinglePost.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.io.Serializable;
4 |
5 | import com.google.api.client.util.Key;
6 |
7 | public class SinglePost implements Serializable {
8 | private static final long serialVersionUID = 1L;
9 |
10 | @Key
11 | private String status;
12 |
13 | @Key
14 | private Post post;
15 |
16 | public String getStatus() {
17 | return status;
18 | }
19 |
20 | public void setStatus(String status) {
21 | this.status = status;
22 | }
23 |
24 | public Post getPost() {
25 | return post;
26 | }
27 |
28 | public void setPost(Post post) {
29 | this.post = post;
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return "SinglePost [status=" + status + ", post=" + post + "]";
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/SubmitTipResponse.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.util.List;
4 |
5 | import com.google.api.client.util.Key;
6 |
7 | public class SubmitTipResponse {
8 | @Key
9 | private int status;
10 |
11 | @Key
12 | private List data;
13 |
14 | @Override
15 | public String toString() {
16 | return "SubmitTipResponse [status=" + status + ", data=" + data + "]";
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/model/json/Tag.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.model.json;
2 |
3 | import java.io.Serializable;
4 |
5 | import com.google.api.client.util.Key;
6 |
7 | public class Tag implements Serializable {
8 | private static final long serialVersionUID = 1L;
9 |
10 | @Key
11 | private int id;
12 |
13 | @Key
14 | private String slug;
15 |
16 | @Key
17 | private String title;
18 |
19 | @Key
20 | private String description;
21 |
22 | @Key
23 | private int post_count;
24 |
25 | public int getId() {
26 | return id;
27 | }
28 |
29 | public void setId(int id) {
30 | this.id = id;
31 | }
32 |
33 | public String getSlug() {
34 | return slug;
35 | }
36 |
37 | public void setSlug(String slug) {
38 | this.slug = slug;
39 | }
40 |
41 | public String getTitle() {
42 | return title;
43 | }
44 |
45 | public void setTitle(String title) {
46 | this.title = title;
47 | }
48 |
49 | public String getDescription() {
50 | return description;
51 | }
52 |
53 | public void setDescription(String description) {
54 | this.description = description;
55 | }
56 |
57 | public int getPost_count() {
58 | return post_count;
59 | }
60 |
61 | public void setPost_count(int post_count) {
62 | this.post_count = post_count;
63 | }
64 |
65 | @Override
66 | public int hashCode() {
67 | final int prime = 31;
68 | int result = 1;
69 | result = prime * result + ((description == null) ? 0 : description.hashCode());
70 | result = prime * result + id;
71 | result = prime * result + post_count;
72 | result = prime * result + ((slug == null) ? 0 : slug.hashCode());
73 | result = prime * result + ((title == null) ? 0 : title.hashCode());
74 | return result;
75 | }
76 |
77 | @Override
78 | public boolean equals(Object obj) {
79 | if (this == obj)
80 | return true;
81 | if (obj == null)
82 | return false;
83 | if (getClass() != obj.getClass())
84 | return false;
85 | Tag other = (Tag) obj;
86 | if (description == null) {
87 | if (other.description != null)
88 | return false;
89 | } else if (!description.equals(other.description))
90 | return false;
91 | if (id != other.id)
92 | return false;
93 | if (post_count != other.post_count)
94 | return false;
95 | if (slug == null) {
96 | if (other.slug != null)
97 | return false;
98 | } else if (!slug.equals(other.slug))
99 | return false;
100 | if (title == null) {
101 | if (other.title != null)
102 | return false;
103 | } else if (!title.equals(other.title))
104 | return false;
105 | return true;
106 | }
107 |
108 | @Override
109 | public String toString() {
110 | return "Tag [id=" + id + ", slug=" + slug + ", title=" + title + ", description=" + description
111 | + ", post_count=" + post_count + "]";
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/requests/DownloadFileRequest.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.requests;
2 |
3 | import java.io.File;
4 | import java.io.FileOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.net.URL;
8 |
9 | import android.net.Uri;
10 |
11 | import com.octo.android.robospice.request.SpiceRequest;
12 |
13 | public class DownloadFileRequest extends SpiceRequest {
14 | private static final int MAX_BUFFER_SIZE = 1048576;
15 |
16 | private String source;
17 |
18 | private File destinationFolder;
19 |
20 | public DownloadFileRequest(String source, File destinationFolder) {
21 | super(File.class);
22 | this.source = source;
23 | this.destinationFolder = destinationFolder;
24 | }
25 |
26 | @Override
27 | public File loadDataFromNetwork() throws IOException {
28 | int bytesRead;
29 | URL url = new URL(source);
30 |
31 | File destFile = new File(destinationFolder, Uri.parse(source).getLastPathSegment());
32 | FileOutputStream fileOutput = new FileOutputStream(destFile);
33 |
34 | InputStream inputStream = (InputStream) url.getContent();
35 | byte[] buffer = new byte[MAX_BUFFER_SIZE];
36 | while ((bytesRead = inputStream.read(buffer)) > 0) {
37 | fileOutput.write(buffer, 0, bytesRead);
38 | }
39 | fileOutput.close();
40 |
41 | return destFile;
42 | }
43 |
44 | @Override
45 | public String toString() {
46 | return "DownloadFileRequest [source=" + source + ", destinationFolder=" + destinationFolder + "]";
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/requests/MakeCommentRequest.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.requests;
2 |
3 | import ie.broadsheet.app.BroadsheetApplication;
4 | import ie.broadsheet.app.R;
5 | import ie.broadsheet.app.model.json.Comment;
6 |
7 | import java.io.IOException;
8 |
9 | import com.google.api.client.http.GenericUrl;
10 | import com.google.api.client.http.HttpRequest;
11 | import com.google.api.client.http.UrlEncodedContent;
12 | import com.google.api.client.json.jackson.JacksonFactory;
13 | import com.google.api.client.util.GenericData;
14 | import com.octo.android.robospice.request.googlehttpclient.GoogleHttpClientSpiceRequest;
15 |
16 | public class MakeCommentRequest extends GoogleHttpClientSpiceRequest {
17 | // private static final String TAG = "MakeCommentRequest";
18 |
19 | private String baseUrl;
20 |
21 | private int postId;
22 |
23 | private int commentId = 0;
24 |
25 | private String email;
26 |
27 | private String commentName;
28 |
29 | private String commentUrl;
30 |
31 | private String commentBody;
32 |
33 | public int getPostId() {
34 | return postId;
35 | }
36 |
37 | public void setPostId(int postId) {
38 | this.postId = postId;
39 | }
40 |
41 | public String getEmail() {
42 | return email;
43 | }
44 |
45 | public void setEmail(String email) {
46 | this.email = email;
47 | }
48 |
49 | public String getCommentName() {
50 | return commentName;
51 | }
52 |
53 | public void setCommentName(String commentName) {
54 | this.commentName = commentName;
55 | }
56 |
57 | public String getCommentUrl() {
58 | return commentUrl;
59 | }
60 |
61 | public void setCommentUrl(String commentUrl) {
62 | this.commentUrl = commentUrl;
63 | }
64 |
65 | public String getCommentBody() {
66 | return commentBody;
67 | }
68 |
69 | public void setCommentBody(String commentBody) {
70 | this.commentBody = commentBody;
71 | }
72 |
73 | public int getCommentId() {
74 | return commentId;
75 | }
76 |
77 | public void setCommentId(int commentId) {
78 | this.commentId = commentId;
79 | }
80 |
81 | public MakeCommentRequest() {
82 | super(Comment.class);
83 |
84 | this.baseUrl = BroadsheetApplication.context().getString(R.string.apiURL) + "/?json=respond.submit_comment";
85 |
86 | }
87 |
88 | @Override
89 | public Comment loadDataFromNetwork() throws Exception {
90 | GenericData data = new GenericData();
91 | data.put("post_id", postId);
92 | data.put("email", email);
93 | data.put("name", commentName);
94 | if (commentUrl.length() > 0) {
95 | data.put("url", commentUrl);
96 | }
97 | data.put("content", commentBody);
98 | if (commentId > 0) {
99 | data.put("comment_parent", commentId);
100 | }
101 |
102 | UrlEncodedContent content = new UrlEncodedContent(data);
103 |
104 | HttpRequest request = null;
105 | try {
106 | request = getHttpRequestFactory().buildPostRequest(new GenericUrl(baseUrl), content);
107 | } catch (IOException e) {
108 | e.printStackTrace();
109 | } catch (Exception e) {
110 | e.printStackTrace();
111 | }
112 | request.setParser(new JacksonFactory().createJsonObjectParser());
113 |
114 | return request.execute().parseAs(getResultType());
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/requests/PostListRequest.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.requests;
2 |
3 | import ie.broadsheet.app.BroadsheetApplication;
4 | import ie.broadsheet.app.R;
5 | import ie.broadsheet.app.model.json.PostList;
6 |
7 | import java.io.UnsupportedEncodingException;
8 | import java.net.URLEncoder;
9 |
10 | import android.util.Log;
11 |
12 | import com.google.api.client.http.GenericUrl;
13 | import com.google.api.client.http.HttpRequest;
14 | import com.google.api.client.json.jackson.JacksonFactory;
15 | import com.octo.android.robospice.request.googlehttpclient.GoogleHttpClientSpiceRequest;
16 |
17 | public class PostListRequest extends GoogleHttpClientSpiceRequest {
18 | private static final String TAG = "PostListRequest";
19 |
20 | private String baseUrl;
21 |
22 | private int page = 1;
23 |
24 | private int count = 10;
25 |
26 | private String searchTerm;
27 |
28 | public int getPage() {
29 | return page;
30 | }
31 |
32 | public void setPage(int page) {
33 | this.page = page;
34 | }
35 |
36 | public String getSearchTerm() {
37 | return searchTerm;
38 | }
39 |
40 | public void setSearchTerm(String searchTerm) {
41 | this.searchTerm = searchTerm;
42 | }
43 |
44 | public PostListRequest() {
45 | super(PostList.class);
46 |
47 | this.baseUrl = BroadsheetApplication.context().getString(R.string.apiURL) + "/?json=1";
48 |
49 | }
50 |
51 | @Override
52 | public PostList loadDataFromNetwork() throws Exception {
53 | Log.d("PostListRequest", "Call web service " + generateUrl());
54 | HttpRequest request = getHttpRequestFactory().buildGetRequest(new GenericUrl(generateUrl()));
55 | request.setParser(new JacksonFactory().createJsonObjectParser());
56 | return request.execute().parseAs(getResultType());
57 | }
58 |
59 | public String generateUrl() {
60 | String generatedURL = this.baseUrl;
61 |
62 | if (page > 1) {
63 | generatedURL += "&page=" + Integer.toString(page);
64 | }
65 |
66 | generatedURL += "&count=" + Integer.toString(count);
67 |
68 | if ((searchTerm != null) && (searchTerm.length() > 0)) {
69 | try {
70 | generatedURL += "&s=" + URLEncoder.encode(searchTerm, "UTF-8");
71 | } catch (UnsupportedEncodingException e) {
72 | // TODO Auto-generated catch block
73 | e.printStackTrace();
74 | }
75 | }
76 |
77 | Log.d(TAG, generatedURL);
78 |
79 | return generatedURL;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/requests/PostRequest.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.requests;
2 |
3 | import ie.broadsheet.app.model.json.SinglePost;
4 | import android.util.Log;
5 |
6 | import com.google.api.client.http.GenericUrl;
7 | import com.google.api.client.http.HttpRequest;
8 | import com.google.api.client.json.jackson.JacksonFactory;
9 | import com.octo.android.robospice.request.googlehttpclient.GoogleHttpClientSpiceRequest;
10 |
11 | public class PostRequest extends GoogleHttpClientSpiceRequest {
12 | private static final String TAG = "PostRequest";
13 |
14 | private String url;
15 |
16 | public PostRequest(String url) {
17 | super(SinglePost.class);
18 |
19 | this.url = url + "?json=1";
20 |
21 | }
22 |
23 | @Override
24 | public SinglePost loadDataFromNetwork() throws Exception {
25 | Log.d(TAG, url);
26 |
27 | HttpRequest request = getHttpRequestFactory().buildGetRequest(new GenericUrl(url));
28 | request.setParser(new JacksonFactory().createJsonObjectParser());
29 | return request.execute().parseAs(getResultType());
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/requests/SubmitTipRequest.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.requests;
2 |
3 | import ie.broadsheet.app.BroadsheetApplication;
4 | import ie.broadsheet.app.R;
5 | import ie.broadsheet.app.client.http.MultipartFormDataContent;
6 | import ie.broadsheet.app.client.http.MultipartFormDataContent.Part;
7 | import ie.broadsheet.app.model.json.SubmitTipResponse;
8 |
9 | import java.io.File;
10 | import java.io.IOException;
11 |
12 | import android.util.Log;
13 | import android.webkit.MimeTypeMap;
14 |
15 | import com.google.api.client.http.FileContent;
16 | import com.google.api.client.http.GenericUrl;
17 | import com.google.api.client.http.HttpRequest;
18 | import com.google.api.client.json.jackson.JacksonFactory;
19 | import com.octo.android.robospice.request.googlehttpclient.GoogleHttpClientSpiceRequest;
20 |
21 | public class SubmitTipRequest extends GoogleHttpClientSpiceRequest {
22 | private static final String TAG = "SubmitTipRequest";
23 |
24 | private String name;
25 |
26 | private String email;
27 |
28 | private String message;
29 |
30 | private String filename;
31 |
32 | public String getName() {
33 | return name;
34 | }
35 |
36 | public void setName(String name) {
37 | this.name = name;
38 | }
39 |
40 | public String getEmail() {
41 | return email;
42 | }
43 |
44 | public void setEmail(String email) {
45 | this.email = email;
46 | }
47 |
48 | public String getMessage() {
49 | return message;
50 | }
51 |
52 | public void setMessage(String message) {
53 | this.message = message;
54 | }
55 |
56 | public void setFilename(String filename) {
57 | this.filename = filename;
58 | }
59 |
60 | public SubmitTipRequest() {
61 | super(SubmitTipResponse.class);
62 | }
63 |
64 | @Override
65 | public SubmitTipResponse loadDataFromNetwork() throws Exception {
66 | MultipartFormDataContent content = new MultipartFormDataContent();
67 |
68 | if (filename != null) {
69 | Log.d(TAG, "we have a file: " + filename);
70 |
71 | File file = new File(filename);
72 |
73 | MimeTypeMap mime = MimeTypeMap.getSingleton();
74 | String extension = MimeTypeMap.getFileExtensionFromUrl(file.getName());
75 | String mimeType = mime.getMimeTypeFromExtension(extension);
76 |
77 | Part part = new Part();
78 | part.setName("file");
79 | part.setFilename(file.getName());
80 | part.setContent(new FileContent(mimeType, file));
81 | content.addPart(part);
82 |
83 | }
84 |
85 | content.addUrlEncodedContent("name", name);
86 | content.addUrlEncodedContent("email", email);
87 | content.addUrlEncodedContent("message", message);
88 | content.addUrlEncodedContent("android", "android");
89 |
90 | Log.d(TAG, BroadsheetApplication.context().getString(R.string.apiURL) + "/iphone_tip.php");
91 | HttpRequest request = null;
92 | try {
93 | request = getHttpRequestFactory().buildPostRequest(
94 | new GenericUrl(BroadsheetApplication.context().getString(R.string.apiURL) + "/iphone_tip.php"),
95 | content);
96 | } catch (IOException e) {
97 | e.printStackTrace();
98 | } catch (Exception e) {
99 | e.printStackTrace();
100 | }
101 | request.setParser(new JacksonFactory().createJsonObjectParser());
102 |
103 | return request.execute().parseAs(getResultType());
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/ie/broadsheet/app/services/BroadsheetServices.java:
--------------------------------------------------------------------------------
1 | package ie.broadsheet.app.services;
2 |
3 | import android.app.Application;
4 |
5 | import com.octo.android.robospice.GoogleHttpClientSpiceService;
6 | import com.octo.android.robospice.persistence.CacheManager;
7 | import com.octo.android.robospice.persistence.exception.CacheCreationException;
8 | import com.octo.android.robospice.persistence.googlehttpclient.json.JacksonObjectPersisterFactory;
9 |
10 | public class BroadsheetServices extends GoogleHttpClientSpiceService {
11 |
12 | @Override
13 | public CacheManager createCacheManager(Application application) {
14 | CacheManager cacheManager = new CacheManager();
15 |
16 | JacksonObjectPersisterFactory jacksonObjectPersisterFactory;
17 | try {
18 | jacksonObjectPersisterFactory = new JacksonObjectPersisterFactory(application);
19 | cacheManager.addPersister(jacksonObjectPersisterFactory);
20 | } catch (CacheCreationException e) {
21 | // TODO Auto-generated catch block
22 | e.printStackTrace();
23 | }
24 |
25 | return cacheManager;
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------