diff --git a/app/build.gradle b/app/build.gradle index e6c6380b..0cf9686f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,8 +33,8 @@ dependencies { compile 'com.android.support:cardview-v7:25.0.1' compile 'com.android.support:recyclerview-v7:25.0.1' compile 'com.squareup.okhttp3:okhttp:3.5.0' + compile 'com.squareup.picasso:picasso:2.5.2' compile 'org.jsoup:jsoup:1.10.1' - compile 'com.android.volley:volley:1.0.0' compile 'com.github.franmontiel:PersistentCookieJar:v1.0.0' compile('com.mikepenz:materialdrawer:5.8.0@aar') { transitive = true diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 8e49bf42..45de250a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,7 +6,6 @@ postsList; - private LinearLayout postsLinearLayout; private static final int NO_POST_FOCUS = -1; private int postFocus = NO_POST_FOCUS; //Quote - private final ArrayList toQuoteList = new ArrayList<>(); + public static final ArrayList toQuoteList = new ArrayList<>(); /* --Topic's pages-- */ private int thisPage = 1; - private String base_url = ""; + public static String base_url = ""; private int numberOfPages = 1; private final SparseArray pagesUrls = new SparseArray<>(); //Page select @@ -83,21 +66,19 @@ public class TopicActivity extends BaseActivity { private static final int SMALL_STEP = 1; private static final int LARGE_STEP = 10; private Integer pageRequestValue; + private ImageButton firstPage; private ImageButton previousPage; private ImageButton nextPage; private ImageButton lastPage; - /* --Thumbnail-- */ - private static final int THUMBNAIL_SIZE = 80; - private ImageLoader imageLoader = ImageController.getInstance().getImageLoader(); - //Other variables private ProgressBar progressBar; + @SuppressWarnings("unused") private static final String TAG = "TopicActivity"; private String topicTitle; - private String parsedTitle; private FloatingActionButton replyFAB; + private String parsedTitle; @Override protected void onCreate(Bundle savedInstanceState) { @@ -107,7 +88,7 @@ public class TopicActivity extends BaseActivity { Bundle extras = getIntent().getExtras(); topicTitle = getIntent().getExtras().getString("TOPIC_TITLE"); - //Initialize toolbar + //Initialize toolbar, drawer and ProgressBar toolbar = (Toolbar) findViewById(R.id.toolbar); toolbar.setTitle(topicTitle); setSupportActionBar(toolbar); @@ -116,14 +97,8 @@ public class TopicActivity extends BaseActivity { createDrawer(); - //Variables initialization - postsLinearLayout = (LinearLayout) findViewById(R.id.posts_list); - progressBar = (ProgressBar) findViewById(R.id.progressBar); - if (imageLoader == null) - imageLoader = ImageController.getInstance().getImageLoader(); - postsList = new ArrayList<>(); @@ -137,6 +112,7 @@ public class TopicActivity extends BaseActivity { initDecrementButton(previousPage, SMALL_STEP); initIncrementButton(nextPage, SMALL_STEP); initIncrementButton(lastPage, LARGE_STEP); + firstPage.setEnabled(false); previousPage.setEnabled(false); nextPage.setEnabled(false); @@ -211,11 +187,10 @@ public class TopicActivity extends BaseActivity { @Override protected void onDestroy() { //When finished cancel whatever request can still be canceled super.onDestroy(); - ImageController.getInstance().cancelPendingRequests(); } -//--------------------------------------BOTTOM NAV BAR METHODS-------------------------------------- + //--------------------------------------BOTTOM NAV BAR METHODS-------------------------------------- private void initIncrementButton(ImageButton increment, final int step) { // Increment once for a click increment.setOnClickListener(new View.OnClickListener() { @@ -318,8 +293,8 @@ public class TopicActivity extends BaseActivity { private void changePage(int pageRequested) { if (pageRequested != thisPage - 1) { //Restart activity with new page - Pair p1 = Pair.create((View)replyFAB, "fab"); - Pair p2 = Pair.create((View)toolbar, "toolbar"); + Pair p1 = Pair.create((View) replyFAB, "fab"); + Pair p2 = Pair.create((View) toolbar, "toolbar"); ActivityOptionsCompat options = ActivityOptionsCompat. makeSceneTransitionAnimation(this, p1, p2); @@ -332,7 +307,7 @@ public class TopicActivity extends BaseActivity { } //------------------------------------BOTTOM NAV BAR METHODS END------------------------------------ -//---------------------------------------TOPIC ASYNC TASK------------------------------------------- + //---------------------------------------TOPIC ASYNC TASK------------------------------------------- public class TopicTask extends AsyncTask { //Class variables private static final String TAG = "TopicTask"; //Separate tag for AsyncTask @@ -389,6 +364,14 @@ public class TopicActivity extends BaseActivity { pageRequestValue = thisPage; if (numberOfPages >= 1000) pageIndicator.setTextSize(16); + + firstPage.setEnabled(true); + previousPage.setEnabled(true); + nextPage.setEnabled(true); + lastPage.setEnabled(true); + + if (topicTitle == null || Objects.equals(topicTitle, "")) + toolbar.setTitle(parsedTitle); } /* Parse method */ @@ -396,11 +379,10 @@ public class TopicActivity extends BaseActivity { //Find topic title if missing if (topicTitle == null || Objects.equals(topicTitle, "")) { parsedTitle = document.select("td[id=top_subject]").first().text(); - if(parsedTitle.contains("Topic:")) { + if (parsedTitle.contains("Topic:")) { parsedTitle = parsedTitle.substring(parsedTitle.indexOf("Topic:") + 7 , parsedTitle.indexOf("(Read") - 2); - } - else{ + } else { parsedTitle = parsedTitle.substring(parsedTitle.indexOf("Θέμα:") + 6 , parsedTitle.indexOf("(Αναγνώστηκε") - 2); Log.d(TAG, parsedTitle); @@ -432,298 +414,26 @@ public class TopicActivity extends BaseActivity { * adds a card for each post to the ScrollView. */ private void populateLayout() { - //Enable reply button - replyFAB.setEnabled(true); - - //Set topic title if not already present - if (topicTitle == null || Objects.equals(topicTitle, "")) { - topicTitle = parsedTitle; - if (toolbar != null) { - toolbar.setTitle(topicTitle); - } - } - - //Now that parsing is complete and we have the url for every page enable page nav buttons - firstPage.setEnabled(true); - previousPage.setEnabled(true); - nextPage.setEnabled(true); - lastPage.setEnabled(true); - - //Initialize an inflater - LayoutInflater inflater = (LayoutInflater) getApplicationContext() - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - - //Create a card for each post - for (final Post currentPost : postsList) { - //Inflate a topic post row layout - View convertView = inflater.inflate(R.layout.activity_topic_post_row - , postsLinearLayout, false); - - //Get an ImageLoader instance - if (imageLoader == null) - imageLoader = ImageController.getInstance().getImageLoader(); - - //Initialize layout's graphic elements - //Basic stuff - final CardView cardView = (CardView) convertView.findViewById(R.id.card_view); - final FrameLayout postDateAndNumberExp = (FrameLayout) convertView.findViewById(R.id.post_date_and_number_exp); - TextView postDate = (TextView) convertView.findViewById(R.id.post_date); - TextView postNum = (TextView) convertView.findViewById(R.id.post_number); - CircularNetworkImageView thumbnail = (CircularNetworkImageView) convertView.findViewById(R.id.thumbnail); - final TextView username = (TextView) convertView.findViewById(R.id.username); - final TextView subject = (TextView) convertView.findViewById(R.id.subject); - final WebView post = (WebView) convertView.findViewById(R.id.post); - final ImageButton quoteToggle = (ImageButton) convertView.findViewById(R.id.toggle_quote_button); - - //User's extra - RelativeLayout header = (RelativeLayout) convertView.findViewById(R.id.header); - final LinearLayout userExtraInfo = (LinearLayout) convertView.findViewById(R.id.user_extra_info); - - //Post's WebView parameters set - post.setClickable(true); - post.setWebViewClient(new LinkLauncher()); - post.getSettings().setJavaScriptEnabled(true); - //TODO - post.getSettings().setPluginState(WebSettings.PluginState.ON_DEMAND); - - - - //Avoiding errors about layout having 0 width/height - thumbnail.setMinimumWidth(1); - thumbnail.setMinimumHeight(1); - //Set thumbnail size - thumbnail.setMaxWidth(THUMBNAIL_SIZE); - thumbnail.setMaxHeight(THUMBNAIL_SIZE); - - //Thumbnail image set - if (currentPost.getThumbnailUrl() != null - && !Objects.equals(currentPost.getThumbnailUrl(), "")) { - thumbnail.setImageUrl(currentPost.getThumbnailUrl(), imageLoader); - } - - //Username set - username.setText(currentPost.getAuthor()); - - //Post's submit date set - postDate.setText(currentPost.getPostDate()); - - //Post's index number set - if (currentPost.getPostNumber() != 0) - postNum.setText(getString(R.string.user_number_of_posts, currentPost.getPostNumber())); - //postNum.setText("#" + currentPost.getPostNumber()); - else - postNum.setText(""); - - //Post's subject set - subject.setText(currentPost.getSubject()); - - //Post's text set - post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null); - - quoteToggle.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - if (view.isSelected()) { - if (toQuoteList.contains(currentPost.getPostNumber())) { - toQuoteList.remove(toQuoteList.indexOf(currentPost.getPostNumber())); - view.setSelected(false); - } else - Log.i(TAG, "An error occurred while trying to exclude post from" + - "toQuoteList, post wasn't there!"); - } else { - toQuoteList.add(currentPost.getPostNumber()); - view.setSelected(true); - } - } - }); - - //If user is not deleted then we have more to do - if (!currentPost.isDeleted()) { //Set extra info - //Variables for Graphics - TextView g_specialRank, g_rank, g_gender, g_numberOfPosts, g_personalText; - LinearLayout g_stars_holder = (LinearLayout) convertView.findViewById(R.id.stars); - - //Variables for content - String c_specialRank = currentPost.getSpecialRank(), c_rank = currentPost.getRank(), c_gender = currentPost.getGender(), c_numberOfPosts = currentPost.getNumberOfPosts(), c_personalText = currentPost.getPersonalText(), c_urlOfStars = currentPost.getUrlOfStars(); - int c_numberOfStars = currentPost.getNumberOfStars(); - - if (!Objects.equals(c_specialRank, "") && c_specialRank != null) { - g_specialRank = (TextView) convertView.findViewById(R.id.special_rank); - g_specialRank.setText(c_specialRank); - g_specialRank.setVisibility(View.VISIBLE); - } - if (!Objects.equals(c_rank, "") && c_rank != null) { - g_rank = (TextView) convertView.findViewById(R.id.rank); - g_rank.setText(c_rank); - g_rank.setVisibility(View.VISIBLE); - } - if (!Objects.equals(c_gender, "") && c_gender != null) { - g_gender = (TextView) convertView.findViewById(R.id.gender); - g_gender.setText(c_gender); - g_gender.setVisibility(View.VISIBLE); - } - if (!Objects.equals(c_numberOfPosts, "") && c_numberOfPosts != null) { - g_numberOfPosts = (TextView) convertView.findViewById(R.id.number_of_posts); - g_numberOfPosts.setText(c_numberOfPosts); - g_numberOfPosts.setVisibility(View.VISIBLE); - } - if (!Objects.equals(c_personalText, "") && c_personalText != null) { - g_personalText = (TextView) convertView.findViewById(R.id.personal_text); - g_personalText.setText("\"" + c_personalText + "\""); - g_personalText.setVisibility(View.VISIBLE); - } - for (int i = 0; i < c_numberOfStars; ++i) { - CircularNetworkImageView star = new CircularNetworkImageView(this); - star.setImageUrl(c_urlOfStars, imageLoader); - - //Remove spacing between stars... - //Don't know why this is happening in the first place - LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ); - params.setMargins((int) getResources().getDimension(R.dimen.stars_margin) - , 0 - , (int) getResources().getDimension(R.dimen.stars_margin) - , 0); - star.setLayoutParams(params); - - g_stars_holder.addView(star, 0); - g_stars_holder.setVisibility(View.VISIBLE); - } - - /* --Header expand/collapse functionality-- */ - - header.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - TopicAnimations.animateUserExtraInfoVisibility(userExtraInfo); - } - }); - - //Clicking the expanded part of a header should collapse the extra info - userExtraInfo.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - TopicAnimations.animateUserExtraInfoVisibility(v); - } - }); - /* --Header expand/collapse functionality end-- */ - } - - /* --Card expand/collapse functionality-- */ - - //Should expand/collapse when card is touched - cardView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - TopicAnimations.animatePostExtraInfoVisibility(postDateAndNumberExp - , username, subject - ,ContextCompat.getColor(getApplicationContext(), R.color.black) - ,ContextCompat.getColor(getApplicationContext(), R.color.secondary_text)); - } - }); - - //Also when post is clicked - post.setOnTouchListener(new CustomTouchListener(post,cardView, quoteToggle)); - - /* --Card expand/collapse-like functionality end-- */ - - //Add view to the linear layout that holds all posts - postsLinearLayout.addView(convertView); - - //Set post focus - if (postFocus != NO_POST_FOCUS) { + RecyclerView recyclerView = (RecyclerView)findViewById(R.id.topic_recycler_view); + recyclerView.setHasFixedSize(true); + RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext()); + recyclerView.setLayoutManager(layoutManager); + + TopicAdapter adapter = new TopicAdapter(getApplicationContext(), postsList); + recyclerView.setAdapter(adapter); + + //Set post focus + if (postFocus != NO_POST_FOCUS) { + for (int i = 0; i < postsList.size(); ++i) { + Post currentPost = postsList.get(i); if (currentPost.getPostIndex() == postFocus) { //TODO } } } } -//--------------------------------------POPULATE UI METHOD END-------------------------------------- - -//--------------------------------------CUSTOM WEBVIEW CLIENT--------------------------------------- - - /** - * This class is used to handle link clicks in WebViews. - * When link url is one that the app can handle internally, it does. - * Otherwise user is prompt to open the link in a browser. - */ - @SuppressWarnings("unchecked") - private class LinkLauncher extends WebViewClient { //Used to handle link clicks - //Older versions - @SuppressWarnings("deprecation") - @Override - public boolean shouldOverrideUrlLoading(WebView view, String url) { - final Uri uri = Uri.parse(url); - return handleUri(uri); - } - //Newest versions - @TargetApi(Build.VERSION_CODES.N) - @Override - public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { - final Uri uri = request.getUrl(); - return handleUri(uri); - } - - //Handle url clicks - private boolean handleUri(final Uri uri) { - //Method always returns true as we don't want any url to be loaded in WebViews - - Log.i(TAG, "Uri = " + uri); - final String host = uri.getHost(); //Get requested url's host - final String uriString = uri.toString(); - - //Determine if you are going to pass the url to a - //host's application activity or load it in a browser. - if (Objects.equals(host, "www.thmmy.gr")) { - //This is my web site, so figure out what Activity should launch - if (uriString.contains("topic=")) { //This url points to a topic - //Is the link pointing to current topic? - if (Objects.equals( - uriString.substring(0, uriString.lastIndexOf(".")), base_url)) { - - //Get uri's targeted message's index number - String msgIndexReq = uriString.substring(uriString.indexOf("msg") + 3); - if (msgIndexReq.contains("#")) - msgIndexReq = msgIndexReq.substring(0, msgIndexReq.indexOf("#")); - else - msgIndexReq = msgIndexReq.substring(0, msgIndexReq.indexOf(";")); - - //Is this post already shown now? (is it in current page?) - for (Post post : postsList) { - if (post.getPostIndex() == Integer.parseInt(msgIndexReq)) { - //Don't restart Activity - //Just change post focus - //TODO - return true; - } - } - } - //Restart activity with new data - Pair p1 = Pair.create((View) replyFAB, "fab"); - Pair p2 = Pair.create((View) toolbar, "toolbar"); - ActivityOptionsCompat options = ActivityOptionsCompat. - makeSceneTransitionAnimation(TopicActivity.this, p1, p2); - - Intent intent = getIntent(); - intent.putExtra("TOPIC_URL", uri.toString()); - intent.putExtra("TOPIC_TITLE", ""); - startActivity(intent, options.toBundle()); - finish(); - - } - return true; - } - //Otherwise, the link is not for a page on my site, so launch - //another Activity that handles URLs - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - startActivity(intent); - return true; - } - } -//------------------------------------CUSTOM WEBVIEW CLIENT END------------------------------------- +//--------------------------------------POPULATE UI METHOD END-------------------------------------- //----------------------------------------REPETITIVE UPDATER---------------------------------------- @@ -750,94 +460,4 @@ public class TopicActivity extends BaseActivity { } } //--------------------------------------REPETITIVE UPDATER END-------------------------------------- - -//--------------------------------------CUSTOM TOUCH LISTENER--------------------------------------- - /** - * This class is a gesture detector for WebViews. - * It handles post's clicks, long clicks and touch and drag. - */ - - private class CustomTouchListener implements View.OnTouchListener { - //Long press handling - private final int LONG_PRESS_DURATION = 650; - private final Handler webViewLongClickHandler = new Handler(); - private boolean wasLongClick = false; - private float downCoordinateX; - private float downCoordinateY; - private final float SCROLL_THRESHOLD = 7; - final private WebView post; - final private CardView cardView; - final private ImageButton quoteToggle; - - //Other variables - final static int FINGER_RELEASED = 0; - final static int FINGER_TOUCHED = 1; - final static int FINGER_DRAGGING = 2; - final static int FINGER_UNDEFINED = 3; - - private int fingerState = FINGER_RELEASED; - - CustomTouchListener(WebView pPost, CardView pCard, ImageButton pQuoteToggle){ - post = pPost; - cardView = pCard; - quoteToggle = pQuoteToggle; - } - - final Runnable WebViewLongClick = new Runnable() { - public void run() { - wasLongClick = true; - quoteToggle.performClick(); - } - }; - - @Override - public boolean onTouch(View view, MotionEvent motionEvent) { - - switch (motionEvent.getAction()) { - - case MotionEvent.ACTION_DOWN: - downCoordinateX = motionEvent.getX(); - downCoordinateY = motionEvent.getY(); - if (fingerState == FINGER_RELEASED) - fingerState = FINGER_TOUCHED; - else - fingerState = FINGER_UNDEFINED; - //Start long click runnable - webViewLongClickHandler.postDelayed(WebViewLongClick - , LONG_PRESS_DURATION); - break; - - case MotionEvent.ACTION_UP: - webViewLongClickHandler.removeCallbacks(WebViewLongClick); - - if (!wasLongClick && fingerState != FINGER_DRAGGING) { - //If this was a link don't expand the card - WebView.HitTestResult htResult = post.getHitTestResult(); - if (htResult.getExtra() != null - && htResult.getExtra() != null) - return false; - //Else expand/collapse card - cardView.performClick(); - } else - wasLongClick = false; - fingerState = FINGER_RELEASED; - break; - - case MotionEvent.ACTION_MOVE: - //If finger moved too much, cancel long click - if (((Math.abs(downCoordinateX - motionEvent.getX()) > SCROLL_THRESHOLD || - Math.abs(downCoordinateY - motionEvent.getY()) > SCROLL_THRESHOLD))) { - webViewLongClickHandler.removeCallbacks(WebViewLongClick); - fingerState = FINGER_DRAGGING; - } else fingerState = FINGER_UNDEFINED; - break; - - default: - fingerState = FINGER_UNDEFINED; - - } - return false; - } - } -//------------------------------------CUSTOM TOUCH LISTENER END------------------------------------- } \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java new file mode 100644 index 00000000..938225c4 --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java @@ -0,0 +1,431 @@ +package gr.thmmy.mthmmy.activities.topic; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.Intent; +import android.graphics.Color; +import android.net.Uri; +import android.os.Build; +import android.os.Handler; +import android.support.v4.content.res.ResourcesCompat; +import android.support.v7.widget.CardView; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.webkit.WebResourceRequest; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import com.squareup.picasso.Picasso; + +import java.util.List; +import java.util.Objects; + +import gr.thmmy.mthmmy.R; +import gr.thmmy.mthmmy.data.Post; +import gr.thmmy.mthmmy.utils.CircleTransform; + +import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; +import static gr.thmmy.mthmmy.activities.topic.TopicActivity.base_url; +import static gr.thmmy.mthmmy.activities.topic.TopicActivity.toQuoteList; + +class TopicAdapter extends RecyclerView.Adapter { + private static final String TAG = "TopicAdapter"; + + private static int THUMBNAIL_SIZE; + private final Context context; + private final List postsList; + + class MyViewHolder extends RecyclerView.ViewHolder { + final CardView cardView; + final FrameLayout postDateAndNumberExp; + final TextView postDate, postNum, username, subject; + final ImageView thumbnail; + final public WebView post; + final ImageButton quoteToggle; + final RelativeLayout header; + final LinearLayout userExtraInfo; + + final TextView specialRank, rank, gender, numberOfPosts, personalText; + final LinearLayout stars_holder; + + MyViewHolder(View view) { + super(view); + + //Initialize layout's graphic elements + //Basic stuff + cardView = (CardView) view.findViewById(R.id.card_view); + postDateAndNumberExp = (FrameLayout) view.findViewById(R.id.post_date_and_number_exp); + postDate = (TextView) view.findViewById(R.id.post_date); + postNum = (TextView) view.findViewById(R.id.post_number); + thumbnail = (ImageView) view.findViewById(R.id.thumbnail); + username = (TextView) view.findViewById(R.id.username); + subject = (TextView) view.findViewById(R.id.subject); + post = (WebView) view.findViewById(R.id.post); + quoteToggle = (ImageButton) view.findViewById(R.id.toggle_quote_button); + + //User's extra + header = (RelativeLayout) view.findViewById(R.id.header); + userExtraInfo = (LinearLayout) view.findViewById(R.id.user_extra_info); + specialRank = (TextView) view.findViewById(R.id.special_rank); + rank = (TextView) view.findViewById(R.id.rank); + gender = (TextView) view.findViewById(R.id.gender); + numberOfPosts = (TextView) view.findViewById(R.id.number_of_posts); + personalText = (TextView) view.findViewById(R.id.personal_text); + stars_holder = (LinearLayout) view.findViewById(R.id.stars); + } + + /** + * Possible cleanup needed (like so:) + * https://stackoverflow.com/questions/24897441/picasso-how-to-cancel-all-image-requests-made-in-an-adapter + * TODO + */ + } + + + TopicAdapter(Context context, List postsList) { + this.context = context; + this.postsList = postsList; + + THUMBNAIL_SIZE = (int) context.getResources().getDimension(R.dimen.thumbnail_size); + } + + @Override + public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View itemView = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.activity_topic_post_row, parent, false); + + return new MyViewHolder(itemView); + } + + @Override + public void onBindViewHolder(final MyViewHolder holder, int position) { + final Post currentPost = postsList.get(position); + + //Post's WebView parameters set + holder.post.setClickable(true); + holder.post.setWebViewClient(new LinkLauncher()); + holder.post.getSettings().setJavaScriptEnabled(true); + + //Avoiding errors about layout having 0 width/height + holder.thumbnail.setMinimumWidth(1); + holder.thumbnail.setMinimumHeight(1); + //Set thumbnail size + holder.thumbnail.setMaxWidth(THUMBNAIL_SIZE); + holder.thumbnail.setMaxHeight(THUMBNAIL_SIZE); + + //noinspection ConstantConditions + Picasso.with(context) + .load(currentPost.getThumbnailUrl()) + .resize(THUMBNAIL_SIZE,THUMBNAIL_SIZE) + .centerCrop() + .error(ResourcesCompat.getDrawable(context.getResources() + , R.drawable.ic_default_user_thumbnail, null)) + .placeholder(ResourcesCompat.getDrawable(context.getResources() + , R.drawable.ic_default_user_thumbnail, null)) + .transform(new CircleTransform()) + .into(holder.thumbnail); + + //Username set + holder.username.setText(currentPost.getAuthor()); + + //Post's submit date set + holder.postDate.setText(currentPost.getPostDate()); + + //Post's index number set + if (currentPost.getPostNumber() != 0) + holder.postNum.setText(context.getString( + R.string.user_number_of_posts, currentPost.getPostNumber())); + else + holder.postNum.setText(""); + + //Post's subject set + holder.subject.setText(currentPost.getSubject()); + + //Post's text set + holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null); + + holder.quoteToggle.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + if (view.isSelected()) { + if (toQuoteList.contains(currentPost.getPostNumber())) { + toQuoteList.remove(toQuoteList.indexOf(currentPost.getPostNumber())); + view.setSelected(false); + } else + Log.i(TAG, "An error occurred while trying to exclude post from" + + "toQuoteList, post wasn't there!"); + } else { + toQuoteList.add(currentPost.getPostNumber()); + view.setSelected(true); + } + } + }); + + //If user is not deleted then we have more to do + if (!currentPost.isDeleted()) { //Set extra info + //Variables for content + String c_specialRank = currentPost.getSpecialRank(), c_rank = currentPost.getRank(), c_gender = currentPost.getGender(), c_numberOfPosts = currentPost.getNumberOfPosts(), c_personalText = currentPost.getPersonalText(), c_urlOfStars = currentPost.getUrlOfStars(); + int c_numberOfStars = currentPost.getNumberOfStars(); + + if (!Objects.equals(c_specialRank, "") && c_specialRank != null) { + holder.specialRank.setText(c_specialRank); + holder.specialRank.setVisibility(View.VISIBLE); + } + if (!Objects.equals(c_rank, "") && c_rank != null) { + holder.rank.setText(c_rank); + holder.rank.setVisibility(View.VISIBLE); + } + if (!Objects.equals(c_gender, "") && c_gender != null) { + holder.gender.setText(c_gender); + holder.gender.setVisibility(View.VISIBLE); + } + if (!Objects.equals(c_numberOfPosts, "") && c_numberOfPosts != null) { + holder.numberOfPosts.setText(c_numberOfPosts); + holder.numberOfPosts.setVisibility(View.VISIBLE); + } + if (!Objects.equals(c_personalText, "") && c_personalText != null) { + holder.personalText.setText("\"" + c_personalText + "\""); + holder.personalText.setVisibility(View.VISIBLE); + } + + for (int i = 0; i < c_numberOfStars; ++i) { + ImageView star = new ImageView(context); + + Picasso.with(context) + .load(c_urlOfStars) + .into(star); + + //Remove spacing between stars... + //Don't know why this is happening in the first place + //TODO change layout? other solution? + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + params.setMargins((int) context.getResources().getDimension(R.dimen.stars_margin) + , 0 + , (int) context.getResources().getDimension(R.dimen.stars_margin) + , 0); + star.setLayoutParams(params); + + holder.stars_holder.addView(star, 0); + holder.stars_holder.setVisibility(View.VISIBLE); + } + + /* --Header expand/collapse functionality-- */ + + holder.header.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TopicAnimations.animateUserExtraInfoVisibility(holder.userExtraInfo); + } + }); + + //Clicking the expanded part of a header should collapse the extra info + holder.userExtraInfo.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TopicAnimations.animateUserExtraInfoVisibility(v); + } + }); + /* --Header expand/collapse functionality end-- */ + } + + /* --Card expand/collapse functionality-- */ + + //Should expand/collapse when card is touched + holder.cardView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + TopicAnimations.animatePostExtraInfoVisibility(holder.postDateAndNumberExp + , holder.username, holder.subject + , Color.parseColor("#000000") + , Color.parseColor("#757575")); + } + }); + + //Also when post is clicked + holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView, holder.quoteToggle)); + } + + @Override + public int getItemCount() { + return postsList.size(); + } + +//--------------------------------------CUSTOM TOUCH LISTENER--------------------------------------- + + /** + * This class is a gesture detector for WebViews. + * It handles post's clicks, long clicks and touch and drag. + */ + + private class CustomTouchListener implements View.OnTouchListener { + //Long press handling + private final int LONG_PRESS_DURATION = 650; + private final Handler webViewLongClickHandler = new Handler(); + private boolean wasLongClick = false; + private float downCoordinateX; + private float downCoordinateY; + private final float SCROLL_THRESHOLD = 7; + final private WebView post; + final private CardView cardView; + final private ImageButton quoteToggle; + + //Other variables + final static int FINGER_RELEASED = 0; + final static int FINGER_TOUCHED = 1; + final static int FINGER_DRAGGING = 2; + final static int FINGER_UNDEFINED = 3; + + private int fingerState = FINGER_RELEASED; + + CustomTouchListener(WebView pPost, CardView pCard, ImageButton pQuoteToggle) { + post = pPost; + cardView = pCard; + quoteToggle = pQuoteToggle; + } + + final Runnable WebViewLongClick = new Runnable() { + public void run() { + wasLongClick = true; + quoteToggle.performClick(); + } + }; + + @Override + public boolean onTouch(View view, MotionEvent motionEvent) { + + switch (motionEvent.getAction()) { + + case MotionEvent.ACTION_DOWN: + downCoordinateX = motionEvent.getX(); + downCoordinateY = motionEvent.getY(); + if (fingerState == FINGER_RELEASED) + fingerState = FINGER_TOUCHED; + else + fingerState = FINGER_UNDEFINED; + //Start long click runnable + webViewLongClickHandler.postDelayed(WebViewLongClick + , LONG_PRESS_DURATION); + break; + + case MotionEvent.ACTION_UP: + webViewLongClickHandler.removeCallbacks(WebViewLongClick); + + if (!wasLongClick && fingerState != FINGER_DRAGGING) { + //If this was a link don't expand the card + WebView.HitTestResult htResult = post.getHitTestResult(); + if (htResult.getExtra() != null + && htResult.getExtra() != null) + return false; + //Else expand/collapse card + cardView.performClick(); + } else + wasLongClick = false; + fingerState = FINGER_RELEASED; + break; + + case MotionEvent.ACTION_MOVE: + //If finger moved too much, cancel long click + if (((Math.abs(downCoordinateX - motionEvent.getX()) > SCROLL_THRESHOLD || + Math.abs(downCoordinateY - motionEvent.getY()) > SCROLL_THRESHOLD))) { + webViewLongClickHandler.removeCallbacks(WebViewLongClick); + fingerState = FINGER_DRAGGING; + } else fingerState = FINGER_UNDEFINED; + break; + + default: + fingerState = FINGER_UNDEFINED; + + } + return false; + } + } +//------------------------------------CUSTOM TOUCH LISTENER END------------------------------------- + +//--------------------------------------CUSTOM WEBVIEW CLIENT--------------------------------------- + + /** + * This class is used to handle link clicks in WebViews. + * When link url is one that the app can handle internally, it does. + * Otherwise user is prompt to open the link in a browser. + */ + @SuppressWarnings("unchecked") + private class LinkLauncher extends WebViewClient { //Used to handle link clicks + //Older versions + @SuppressWarnings("deprecation") + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + final Uri uri = Uri.parse(url); + return handleUri(uri); + } + + //Newest versions + @TargetApi(Build.VERSION_CODES.N) + @Override + public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { + final Uri uri = request.getUrl(); + return handleUri(uri); + } + + //Handle url clicks + private boolean handleUri(final Uri uri) { + //Method always returns true as we don't want any url to be loaded in WebViews + + Log.i(TAG, "Uri clicked = " + uri); + final String host = uri.getHost(); //Get requested url's host + final String uriString = uri.toString(); + + //Determine if you are going to pass the url to a + //host's application activity or load it in a browser. + if (Objects.equals(host, "www.thmmy.gr")) { + //This is my web site, so figure out what Activity should launch + if (uriString.contains("topic=")) { //This url points to a topic + //Is the link pointing to current topic? + if (Objects.equals( + uriString.substring(0, uriString.lastIndexOf(".")), base_url)) { + + //Get uri's targeted message's index number + String msgIndexReq = uriString.substring(uriString.indexOf("msg") + 3); + if (msgIndexReq.contains("#")) + msgIndexReq = msgIndexReq.substring(0, msgIndexReq.indexOf("#")); + else + msgIndexReq = msgIndexReq.substring(0, msgIndexReq.indexOf(";")); + + //Is this post already shown now? (is it in current page?) + for (Post post : postsList) { + if (post.getPostIndex() == Integer.parseInt(msgIndexReq)) { + //Don't restart Activity + //Just change post focus + //TODO + return true; + } + } + } + //Restart activity with new data + //TODO + } + return true; + } + //Otherwise, the link is not for a page on my site, so launch + //another Activity that handles URLs + Intent intent = new Intent(Intent.ACTION_VIEW, uri); + intent.setFlags(FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + return true; + } + } +//------------------------------------CUSTOM WEBVIEW CLIENT END------------------------------------- + +} \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java index 771b86ca..5b49cf65 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java @@ -1,7 +1,5 @@ package gr.thmmy.mthmmy.activities.topic; -import android.util.Log; - import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; @@ -28,6 +26,7 @@ class TopicParser { private static String genderAltMale; private static String genderAltFemale; + @SuppressWarnings("unused") private static final String TAG = "TopicParser"; static int parseCurrentPageIndex(Document doc) { @@ -123,15 +122,18 @@ class TopicParser { for (Element _noembed : noembedTag) { embededVideosUrls.add(_noembed.text().substring(_noembed.text() - .indexOf("href=\"https://www.youtube.com/watch?") + 6 - , _noembed.text().indexOf("target") - 6)); + .indexOf("href=\"https://www.youtube.com/watch?") + 38 + , _noembed.text().indexOf("target") - 2)); } int tmp_counter = 0; while (p_post.contains(" embededVideosUrls.size()) + break; p_post = p_post.replace( p_post.substring(p_post.indexOf("") + 9) - , "" ); @@ -223,14 +225,14 @@ class TopicParser { } //Add new post in postsList, extended information needed returnList.add(new Post(p_thumbnailUrl, p_userName, p_subject, p_post - , p_postIndex, p_postNum, p_postDate, false, p_rank + , p_postIndex, p_postNum, p_postDate, p_rank , p_specialRank, p_gender, p_numberOfPosts, p_personalText , p_urlOfStars, p_numberOfStars)); } else { //Deleted user //Add new post in postsList, only standard information needed returnList.add(new Post(p_thumbnailUrl, p_userName, p_subject - , p_post, p_postIndex, p_postNum, p_postDate, true)); + , p_post, p_postIndex, p_postNum, p_postDate)); } } return returnList; diff --git a/app/src/main/java/gr/thmmy/mthmmy/data/Post.java b/app/src/main/java/gr/thmmy/mthmmy/data/Post.java index 2352d711..ef9aab49 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/data/Post.java +++ b/app/src/main/java/gr/thmmy/mthmmy/data/Post.java @@ -21,8 +21,8 @@ public class Post { private int numberOfStars; public Post(String thumbnailUrl, String author, String subject, String content - , int postIndex, int postNumber, String postDate, boolean isDeleted - , String rank, String special_rank, String gender, String numberOfPosts + , int postIndex, int postNumber, String postDate, String rank + , String special_rank, String gender, String numberOfPosts , String personalText, String urlOfStars, int numberOfStars) { this.thumbnailUrl = thumbnailUrl; this.author = author; @@ -31,7 +31,7 @@ public class Post { this.postIndex = postIndex; this.postNumber = postNumber; this.postDate = postDate; - this.isDeleted = isDeleted; + this.isDeleted = false; this.rank = rank; this.specialRank = special_rank; this.gender = gender; @@ -42,7 +42,7 @@ public class Post { } public Post(String thumbnailUrl, String author, String subject, String content - , int postIndex, int postNumber, String postDate, boolean isDeleted) { + , int postIndex, int postNumber, String postDate) { this.thumbnailUrl = thumbnailUrl; this.author = author; this.subject = subject; @@ -50,7 +50,7 @@ public class Post { this.postIndex = postIndex; this.postNumber = postNumber; this.postDate = postDate; - this.isDeleted = isDeleted; + this.isDeleted = true; rank = "Rank"; specialRank = "Special rank"; gender = "Gender"; diff --git a/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java b/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java index 5cea4362..2bd02620 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java +++ b/app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java @@ -4,8 +4,6 @@ import android.content.SharedPreferences; import android.graphics.Bitmap; import android.os.Environment; -import com.android.volley.VolleyError; -import com.android.volley.toolbox.ImageLoader; import com.franmontiel.persistentcookiejar.PersistentCookieJar; import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor; @@ -23,8 +21,6 @@ import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import gr.thmmy.mthmmy.utils.ImageController; -import mthmmy.utils.Report; import okhttp3.Cookie; import okhttp3.FormBody; import okhttp3.HttpUrl; @@ -308,7 +304,7 @@ public class SessionManager return null; } - private File getUserAvatar(String image_url, final String package_name, final String image_name) { + /*private File getUserAvatar(String image_url, final String package_name, final String image_name) { final File[] returnImage = {null}; ImageController.getInstance().getImageLoader().get(image_url, new ImageLoader.ImageListener() { @@ -342,7 +338,7 @@ public class SessionManager } }); return returnImage[0]; - } + }*/ /** Create a File for saving an image or video */ private File getOutputMediaFile(String packageName, String imageName){ @@ -371,4 +367,4 @@ public class SessionManager //----------------------------------OTHER FUNCTIONS END----------------------------------------- -} +} \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/CircleTransform.java b/app/src/main/java/gr/thmmy/mthmmy/utils/CircleTransform.java new file mode 100644 index 00000000..874e07d4 --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/CircleTransform.java @@ -0,0 +1,57 @@ +package gr.thmmy.mthmmy.utils; +/* + * Copyright 2014 Julian Shen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; + +import com.squareup.picasso.Transformation; + +public class CircleTransform implements Transformation { + @Override + public Bitmap transform(Bitmap source) { + int size = Math.min(source.getWidth(), source.getHeight()); + + int x = (source.getWidth() - size) / 2; + int y = (source.getHeight() - size) / 2; + + Bitmap squaredBitmap = Bitmap.createBitmap(source, x, y, size, size); + if (squaredBitmap != source) { + source.recycle(); + } + + Bitmap bitmap = Bitmap.createBitmap(size, size, source.getConfig()); + + Canvas canvas = new Canvas(bitmap); + Paint paint = new Paint(); + BitmapShader shader = new BitmapShader(squaredBitmap, BitmapShader.TileMode.CLAMP, BitmapShader.TileMode.CLAMP); + paint.setShader(shader); + paint.setAntiAlias(true); + + float r = size / 2f; + canvas.drawCircle(r, r, r, paint); + + squaredBitmap.recycle(); + return bitmap; + } + + @Override + public String key() { + return "circle"; + } +} \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/CircularNetworkImageView.java b/app/src/main/java/gr/thmmy/mthmmy/utils/CircularNetworkImageView.java deleted file mode 100644 index 78a68a8a..00000000 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/CircularNetworkImageView.java +++ /dev/null @@ -1,72 +0,0 @@ -package gr.thmmy.mthmmy.utils; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffXfermode; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.drawable.BitmapDrawable; -import android.util.AttributeSet; - -import com.android.volley.toolbox.NetworkImageView; - -public class CircularNetworkImageView extends NetworkImageView { - private static final int THUMBNAIL_SIZE = 80; - private Context mContext; - - public CircularNetworkImageView(Context context) { - super(context); - mContext = context; - } - - public CircularNetworkImageView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - mContext = context; - } - - public CircularNetworkImageView(Context context, AttributeSet attrs, - int defStyle) { - super(context, attrs, defStyle); - mContext = context; - } - - @Override - public void setImageBitmap(Bitmap bm) { - if (bm == null) return; - setImageDrawable(new BitmapDrawable(mContext.getResources(), - getCircularBitmap(bm))); - } - - /** - * Creates a circular bitmap and uses whichever dimension is smaller to determine the width - *
Also constrains the circle to the leftmost part of the image - */ - private Bitmap getCircularBitmap(Bitmap bitmap) { - bitmap = Bitmap.createScaledBitmap(bitmap, THUMBNAIL_SIZE, THUMBNAIL_SIZE, false); - Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), - bitmap.getHeight(), Config.ARGB_8888); - Canvas canvas = new Canvas(output); - int size = bitmap.getWidth(); - if (bitmap.getWidth() > bitmap.getHeight()) - size = bitmap.getHeight(); - final int color = 0xff424242; - final Paint paint = new Paint(); - final Rect rect = new Rect(0, 0, size, size); - final RectF rectF = new RectF(rect); - final float roundPx = size / 2; - - paint.setAntiAlias(true); - canvas.drawARGB(0, 0, 0, 0); - paint.setColor(color); - canvas.drawRoundRect(rectF, roundPx, roundPx, paint); - - paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); - canvas.drawBitmap(bitmap, rect, rect, paint); - - return output; - } -} \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/ImageController.java b/app/src/main/java/gr/thmmy/mthmmy/utils/ImageController.java deleted file mode 100644 index e88350a6..00000000 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/ImageController.java +++ /dev/null @@ -1,66 +0,0 @@ -package gr.thmmy.mthmmy.utils; - -import android.app.Application; -import android.text.TextUtils; - -import com.android.volley.Request; -import com.android.volley.RequestQueue; -import com.android.volley.toolbox.ImageLoader; -import com.android.volley.toolbox.Volley; - -public class ImageController extends Application { - - private static final String TAG = ImageController.class.getSimpleName(); - private static ImageController mInstance; - private RequestQueue mRequestQueue; - private ImageLoader mImageLoader; - - public static synchronized ImageController getInstance() { - return mInstance; - } - - @Override - public void onCreate() { - super.onCreate(); - mInstance = this; - } - - private RequestQueue getRequestQueue() { - if (mRequestQueue == null) { - mRequestQueue = Volley.newRequestQueue(getApplicationContext()); - } - - return mRequestQueue; - } - - public ImageLoader getImageLoader() { - getRequestQueue(); - if (mImageLoader == null) { - mImageLoader = new ImageLoader(this.mRequestQueue, - new LruBitmapCache()); - } - return this.mImageLoader; - } - - public void addToRequestQueue(Request req, String tag) { - // set the default tag if tag is empty - req.setTag(TextUtils.isEmpty(tag) ? TAG : tag); - getRequestQueue().add(req); - } - - public void addToRequestQueue(Request req) { - req.setTag(TAG); - getRequestQueue().add(req); - } - - public void cancelPendingRequests() { - mRequestQueue.cancelAll(new RequestQueue.RequestFilter() { - @Override - public boolean apply(Request request) { - return true; - } - }); - } -} - - diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/LruBitmapCache.java b/app/src/main/java/gr/thmmy/mthmmy/utils/LruBitmapCache.java deleted file mode 100644 index 32ae5971..00000000 --- a/app/src/main/java/gr/thmmy/mthmmy/utils/LruBitmapCache.java +++ /dev/null @@ -1,41 +0,0 @@ -package gr.thmmy.mthmmy.utils; - -import android.graphics.Bitmap; -import android.support.v4.util.LruCache; - -import com.android.volley.toolbox.ImageLoader.ImageCache; - -class LruBitmapCache extends LruCache implements - ImageCache { - private static final int CACHE_SIZE_DIVIDER = 8; - - LruBitmapCache() { - this(getDefaultLruCacheSize()); - } - - private LruBitmapCache(int sizeInKiloBytes) { - super(sizeInKiloBytes); - } - - private static int getDefaultLruCacheSize() { - final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); - final int cacheSize = maxMemory / CACHE_SIZE_DIVIDER; - - return cacheSize; - } - - @Override - protected int sizeOf(String key, Bitmap value) { - return value.getRowBytes() * value.getHeight() / 1024; - } - - @Override - public Bitmap getBitmap(String url) { - return get(url); - } - - @Override - public void putBitmap(String url, Bitmap bitmap) { - put(url, bitmap); - } -} \ No newline at end of file diff --git a/app/src/main/res/drawable/login_progress_bar_bg.xml b/app/src/main/res/drawable/progress_bar_bg.xml similarity index 100% rename from app/src/main/res/drawable/login_progress_bar_bg.xml rename to app/src/main/res/drawable/progress_bar_bg.xml diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index d3db5790..5228f8a0 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -114,7 +114,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:background="@drawable/login_progress_bar_bg"/> + android:background="@drawable/progress_bar_bg"/> - - - - - - + - + android:maxWidth="@dimen/thumbnail_size" + android:src="@drawable/ic_default_user_thumbnail"/> + android:background="@drawable/ic_toggle_quote_bg" + android:contentDescription="@string/quote"/> 16dp 16dp 8dp - 80dp - 16dp + 44dp -15dp 36dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 68e1c88a..2c5904f0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -17,6 +17,8 @@ Username should be here… Subject should be here… Post should be here… + Thumbnail should be here… + Quote button should be here… first previous Page