diff --git a/app/build.gradle b/app/build.gradle index 4106623e..e3f337ea 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -21,13 +21,14 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:25.0.0' - compile 'com.android.support:design:25.0.0' + compile 'com.android.support:appcompat-v7:25.0.1' + compile 'com.android.support:design:25.0.1' compile 'com.squareup.okhttp3:okhttp:3.4.1' compile 'org.jsoup:jsoup:1.10.1' - compile 'com.android.support:support-v4:25.0.0' - compile 'com.android.support:cardview-v7:25.0.0' - compile 'com.android.support:recyclerview-v7:25.0.0' + compile 'com.android.support:support-v4:25.0.1' + compile 'com.android.support:cardview-v7:25.0.1' + compile 'com.android.support:recyclerview-v7:25.0.1' + compile 'com.android.volley:volley:1.0.0' compile 'com.github.franmontiel:PersistentCookieJar:v1.0.0' compile('com.mikepenz:materialdrawer:5.7.0@aar') { transitive = true diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a41b86e0..7611e6f0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ diff --git a/app/src/main/assets/style.css b/app/src/main/assets/style.css new file mode 100644 index 00000000..fe34bcac --- /dev/null +++ b/app/src/main/assets/style.css @@ -0,0 +1,838 @@ +/* TP specific classes */ +.sitemap{ + margin: 0; + padding: 0; + list-style: none; +} +.sitemap_topheader{ + background: #ECEDF3; + border-bottom: solid 1px #ffffff; + padding: 4px; +} + +.sitemap_header{ + background: #ECEDF3; + border-bottom: solid 1px #ffffff; + padding: 4px; + display: block; + font-weight: bold; + } + +.sitemap_header_active{ + background: #C8D6E1; + border-bottom: solid 1px #ffffff; + padding: 4px; + display: block; + font-weight: bold; +} + +.sitemap_header:hover , .sitemap_header_active:hover{ + background: #DBE4ED; + border-bottom: solid 1px #ffffff; + padding: 4px; + display: block; + text-decoration: none; +} + +/* TP other styles */ +ul#articlelist +{ + margin: 0; + padding: 0.5ex 0; + list-style: none; +} +ul#catlist +{ + margin: 0; + padding: 0; + list-style: none; + border-top: solid 1px #d0d0d0; +} + +ul#articlelist li +{ + margin: 0; + display: block; + padding: 0 0 0 3ex; + background: url(images/divider.gif) no-repeat 5px 3px; +} +ul#catlist li +{ + display: block; + padding: 0 0 0 3ex; + margin: 0; +} + +/* TP rss feed styles */ +.rss_title{ + font-weight: bold; +} + +.rss_body{ + margin-bottom: 1ex; +} + +.rss_image{ + margin: 4px 0 4px 0; +} +/* Normal, standard links. */ +a:link, a:visited +{ + color: #004080; + text-decoration: none; +} +a:hover +{ + text-decoration: underline; +} + +/* Navigation links - for the link tree. */ +.nav, .nav:link, .nav:visited +{ + color: #000000; + text-decoration: none; +} +a.nav:hover +{ + color: #cc3333; +} + +/* Tables should show empty cells. */ +table +{ + empty-cells: show; +} +/* The main body of the entire forum. */ +body +{ + background: white; + margin: 0; + padding: 0; +} +/* By default (td, body..) use verdana in black. */ +body, td, th , tr +{ + color: #000000; + font-size: small; + font-family: Trebuchet, sans-serif; +} + + + +/* Input boxes - just a bit smaller than normal so they align well. */ +input, textarea, button +{ + color: #000000; + font-family: Trebuchet, sans-serif; + border: 1px solid #aaa; +} +input, button +{ + font-size: 90%; +} + +textarea +{ + font-size: 100%; + color: #000000; + font-family: Trebuchet, sans-serif; +} + +/* All input elements that are checkboxes or radio buttons. */ +input.check +{ +} + +/* Selects are a bit smaller, because it makes them look even better 8). */ +select +{ + font-size: 90%; + font-weight: normal; + color: #000000; + font-family: Trebuchet, sans-serif; +} + +/* Standard horizontal rule.. ([hr], etc.) */ +hr, .hrcolor +{ + height: 1px; + border: 0; + color: #666666; + background-color: #666666; +} + +/* No image should have a border when linked */ +a img +{ + border: 0; +} +/* A quote, perhaps from another post. */ +.quote +{ + font-family: tahoma, sans-serif; + color: #000000; + background-color: #D7DAEC; + border: 1px solid #000000; + margin: 1px; + padding: 1px; + font-size: x-small; + line-height: 1.4em; +} + +/* A code block - maybe even PHP ;). */ +.code +{ + color: #000000; + background-color: #dddddd; + font-family: "Comic Sans MS", "times new roman", monospace; + font-size: x-small; + line-height: 1.3em; + /* Put a nice border around it. */ + border: 1px solid #000000; + margin: 1px auto 1px auto; + padding: 1px; + width: 99%; + /* Don't wrap its contents, and show scrollbars. */ + white-space: nowrap; + overflow: auto; + /* Stop after about 24 lines, and just show a scrollbar. */ + max-height: 24em; +} + +/* The "Quote:" and "Code:" header parts... */ +.quoteheader, .codeheader +{ + font-family: tahoma, sans-serif; + color: #000000; + text-decoration: none; + font-style: normal; + font-weight: bold; + font-size: x-small; + line-height: 1.2em; +} + +/* Generally, those [?] icons. This makes your cursor a help icon. */ +.help +{ + cursor: help; +} + +/* /me uses this a lot. (emote, try typing /me in a post.) */ +.meaction +{ + color: red; +} + +/* The main post box - this makes it as wide as possible. */ +.editor +{ + width: 96%; +} + +/* Highlighted text - such as search results. */ +.highlight +{ + background-color: yellow; + font-weight: bold; + color: black; +} + +/* Alternating backgrounds for posts, and several other sections of the forum. */ +.windowbg +{ + color: #000000; + background-color: #E3E6E1; +} +.windowbg2 +{ + color: #000000; + background-color: #F2F5F0; +} +.windowbg3 +{ + color: #000000; + background-color: #E1E8E0; +} +/* the today container in calendar */ +.calendar_today +{ + background-color: #FFFFFF; +} + +/* These are used primarily for titles, but also for headers (the row that says what everything in the table is.) */ +.titlebg, tr.titlebg th, tr.titlebg td, .titlebg2, tr.titlebg2 th, tr.titlebg2 td +{ + background-color: #A3A392; + padding-top: 10px; +} +.titlebg, tr.titlebg th, tr.titlebg td, .titlebg a:link, .titlebg a:visited, .titlebg2, tr.titlebg2 th, tr.titlebg2 td, .titlebg2 a:link, .titlebg2 a:visited +{ + color: white; + font-style: normal; +} +.titlebg a:hover +{ + color: #dfdfdf; +} + +.catbg, .catbg2, .catbg3 +{ + font-weight: bold; + background-color: #e4e2e0; + color: #000000; +} +/* This is used for tables that have a grid/border background color (such as the topic listing.) */ +.bordercolor +{ + background-color: white; +} + +/* This is used on tables that should just have a border around them. */ +.tborder +{ + background-color: #FFFFFF; +} + +/* Default font sizes: small (8pt), normal (10pt), and large (14pt). */ +.smalltext +{ + font-size: x-small; + font-family: tahoma, sans-serif; +} +.middletext +{ + font-size: 90%; +} +.normaltext +{ + font-size: small; +} +.largetext +{ + font-size: large; +} + + +/* Posts and personal messages displayed throughout the forum. */ +.post, .personalmessage +{ + width: 100%; + overflow: auto; + line-height: 1.3em; +} + +/* All the signatures used in the forum. If your forum users use Mozilla, Opera, or Safari, you might add max-height here ;). */ +.signature +{ + width: 100%; + overflow: auto; + padding-bottom: 3px; + line-height: 1.3em; +} + +/* Sometimes there will be an error when you post */ +.error +{ + color: red; +} + + +/* definitions for the main tab, active means the tab reflects which page is displayed */ +.maintab_first, .maintab_back, .maintab_last, .maintab_active_first, .maintab_active_back, .maintab_active_last +{ + text-transform: uppercase; + vertical-align: top; +} +.maintab_back, .maintab_active_back +{ + text-decoration: none; + font-size: 9px; + vertical-align: top; + padding: 2px 6px 6px 6px; + font-family: Trebuchet, sans-serif; +} + +.maintab_first +{ + display: none; +} +.maintab_back +{ +} +.maintab_last +{ + display: none; +} +.maintab_active_first +{ + display: none; +} +.maintab_active_back +{ + background: #ffd; +} +.maintab_active_last +{ + display: none; +} + +/* how links behave in main tab. */ +.maintab_back a:link , .maintab_back a:visited, .maintab_active_back a:link , .maintab_active_back a:visited +{ + color: black; + text-decoration: none; +} + +.maintab_back a:hover, .maintab_active_back a:hover +{ + text-decoration: underline; +} +/* definitions for the mirror tab */ +.mirrortab_first, .mirrortab_back, .mirrortab_last, .mirrortab_active_first, .mirrortab_active_back, .mirrortab_active_last +{ + color: black; + text-transform: uppercase; + vertical-align: top; +} +.mirrortab_back, .mirrortab_active_back +{ + text-decoration: none; + font-size: 9px; + vertical-align: bottom; + padding: 6px 6px 2px 6px; + font-family: Trebuchet, sans-serif; +} + +.mirrortab_first +{ + display: none; +} +.mirrortab_back +{ +} +.mirrortab_last +{ + display: none; +} +.mirrortab_active_first +{ + display: none; +} +.mirrortab_active_back +{ + background: #ffd; +} +.mirrortab_active_last +{ + display: none; +} + +/* how links behave in mirror tab. */ +.mirrortab_back a:link , .mirrortab_back a:visited, .mirrortab_active_back a:link , .mirrortab_active_back a:visited +{ + color: black; + text-decoration: none; +} + +.mirrortab_back a:hover, .mirrortab_active_back a:hover +{ + text-decoration: underline; +} + +/* The AJAX notifier */ +#ajax_in_progress +{ + background: #32CD32; + color: white; + text-align: center; + font-weight: bold; + font-size: 18pt; + padding: 3px; + width: 100%; + position: fixed; + top: 0; + left: 0; +} + +/* ################################### */ + +#left +{ + background: url(images/img2/leftbg.jpg) repeat-y white; + margin: auto; +} +#right +{ + background: url(images/img2/rightbg.gif) repeat-y top right; +} +#top +{ + background: url(images/img2/top.jpg) repeat-x; +} +#topleft +{ + background: url(images/img2/lefttop.jpg) no-repeat; +} +#topright +{ + background: url(images/img2/logo.jpg) no-repeat top right; +} +#main +{ + padding: 100px 81px 20px 81px; +} +/* #################### */ + +ul#menubox +{ + padding: 0 0 44px 0; + margin: 0; + list-style: none; + position: absolute; + left: 0; + top: 87px; + background: url(images/img2/leftbot.gif) no-repeat bottom left; +} +#smfshout +{ + padding: 6px; + font-size: xx-small; +} +.smfshout_delete +{ + border: solid 1px #888; + background: white; + padding: 1px; +} +.smfshout_body +{ + border: solid 1px #888; + background: white; + padding: 3px; + text-align: left; +} +.smfshout_frame +{ + padding: 5px 0 0 0; +} +ul#menubox li +{ + padding: 0 0 0 8px; + width: 65px; + height: 44px; + margin: 0; + background: url(images/img2/left.gif) repeat-y; +} +ul#menubox li a +{ + font-family: "Comic Sans MS", serif; + display: block; + color: black; + width: 45px; + height: 42px; + padding: 0 0 0 6px; +} +ul#menubox li a span +{ + display: none; +} + +ul#menubox li.m1 +{ + padding-left: 2px; +} +ul#menubox li.m2 +{ + padding-left: 6px; +} +ul#menubox li.m3 +{ + padding-left: 10px; +} +ul#menubox li.m4 +{ + padding-left: 14px; +} +ul#menubox li.m5 +{ + padding-left: 18px; +} + +/* home button */ +a#homebtn +{ + background: url(images/features/home.gif) no-repeat; +} +a#homebtn:hover +{ + background: url(images/features/home-over.gif) no-repeat; +} +a.chosen#homebtn +{ + background: url(images/features/home-select.gif) no-repeat; +} +/* help button */ +a#helpbtn +{ + background: url(images/features/help.gif) no-repeat; +} +a#helpbtn:hover +{ + background: url(images/features/help-over.gif) no-repeat; +} +a.chosen#helpbtn +{ + background: url(images/features/help-select.gif) no-repeat; +} +/* forum button */ +a#forumbtn +{ + background: url(images/features/forum.gif) no-repeat; +} +a#forumbtn:hover +{ + background: url(images/features/forum-over.gif) no-repeat; +} +a.chosen#forumbtn +{ + background: url(images/features/forum-select.gif) no-repeat; +} +/* search button */ +a#searchbtn +{ + background: url(images/features/search.gif) no-repeat; +} +a#searchbtn:hover +{ + background: url(images/features/search-over.gif) no-repeat; +} +a.chosen#searchbtn +{ + background: url(images/features/search-select.gif) no-repeat; +} +/* profile button */ +a#profilebtn +{ + background: url(images/features/profile.gif) no-repeat; +} +a#profilebtn:hover +{ + background: url(images/features/profile-over.gif) no-repeat; +} +a.chosen#profilebtn +{ + background: url(images/features/profile-select.gif) no-repeat; +} +/* admin button */ +a#adminbtn +{ + background: url(images/features/admin.gif) no-repeat; +} +a#adminbtn:hover +{ + background: url(images/features/admin-over.gif) no-repeat; +} +a.chosen#adminbtn +{ + background: url(images/features/admin-select.gif) no-repeat; +} +/* pm button */ +a#pmbtn +{ + background: url(images/features/pm.gif) no-repeat; +} +a#pmbtn:hover +{ + background: url(images/features/pm-over.gif) no-repeat; +} +a.chosen#pmbtn +{ + background: url(images/features/pm-select.gif) no-repeat; +} +/* calendar button */ +a#calendarbtn +{ + background: url(images/features/calendar.gif) no-repeat; +} +a#calendarbtn:hover +{ + background: url(images/features/calendar-over.gif) no-repeat; +} +a.chosen#calendarbtn +{ + background: url(images/features/calendar-select.gif) no-repeat; +} +/* register button */ +a#registerbtn +{ + background: url(images/features/register.gif) no-repeat; +} +a#registerbtn:hover +{ + background: url(images/features/register-over.gif) no-repeat; +} +a.chosen#registerbtn +{ + background: url(images/features/register-select.gif) no-repeat; +} +/* login button */ +a#loginbtn +{ + background: url(images/features/login.gif) no-repeat; +} +a#loginbtn:hover +{ + background: url(images/features/login-over.gif) no-repeat; +} +a.chosen#loginbtn +{ + background: url(images/features/login-select.gif) no-repeat; +} +/* logout button */ +a#logoutbtn +{ + background: url(images/features/logout.gif) no-repeat; +} +a#logoutbtn:hover +{ + background: url(images/features/logout-over.gif) no-repeat; +} +a.chosen#logoutbtn +{ + background: url(images/features/logout-select.gif) no-repeat; +} +/* shop button */ +a#shopbtn +{ + background: url(images/features/shop.gif) no-repeat; +} +a#shopbtn:hover +{ + background: url(images/features/shop-over.gif) no-repeat; +} +a.chosen#shopbtn +{ + background: url(images/features/shop-select.gif) no-repeat; +} +/* arcade button */ +a#arcadebtn +{ + background: url(images/features/arcade.gif) no-repeat; +} +a#arcadebtn:hover +{ + background: url(images/features/arcade-over.gif) no-repeat; +} +a.chosen#arcadebtn +{ + background: url(images/features/arcade-select.gif) no-repeat; +} +/* gallery button */ +a#gallerybtn +{ + background: url(images/features/gallery.gif) no-repeat; +} +a#gallerybtn:hover +{ + background: url(images/features/gallery-over.gif) no-repeat; +} +a.chosen#gallerybtn +{ + background: url(images/features/gallery-select.gif) no-repeat; +} + +#myuser +{ + font-size: small; + padding-bottom: 1em; +} +#ava +{ + float: right; + margin-right: 10px; + text-align: right; + font-family: "Comic Sans MS", sans-serif; +} +#bodyarea +{ + border-bottom: solid 1px #ddd; + margin-bottom: 1em; + padding-bottom: 1em; +} +.clearfix:after +{ + content: "."; + display: block; + height: 0; + clear: both; + visibility: hidden; +} + +.clearfix +{ + display: inline-block; +} + +/* Hides from IE-mac \*/ +* html .clearfix , * html .catbg, * html .catbg2, * html .catbg3 +{ + height: 1%; +} +/* End hide from IE-mac */ + +ul#topmenu +{ + position: absolute; + top: 45px; + margin: 0 195px 0 40px; + padding: 0 5px 4px 5px; + list-style: none; + font-weight: bold; + font-size: 11px; + border-bottom: groove 2px #EDF4ED; +} +ul#topmenu li +{ + float: left; +} +ul#topmenu li a +{ + display: block; + padding: 2px 5px 2px 5px; + border-style: solid solid; + border-width: 0px 1px; + border-color: #E3E6E1; + font-size: 11px; + color: #004080; +} +ul#topmenu li a:hover +{ + background: #E3E6E1; + text-decoration: none; + color: #E78E13; +} +#pages +{ + padding-top: 1em; +} +#uppersection +{ + padding: 1em; + background: url(images/img/upper.jpg) repeat-x; +} +.errorbar +{ + color: white; + font-size: xx-small; + text-align: center; + padding: 3px; + border-bottom: solid 1px black; +} +#errorpanel +{ + position: absolute; + top: 0; + left: 0; + z-index: 90; + width: 100%; +} \ No newline at end of file diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/BaseActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/BaseActivity.java index 483787e8..fb0afd67 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/BaseActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/BaseActivity.java @@ -13,13 +13,24 @@ import okhttp3.OkHttpClient; public class BaseActivity extends AppCompatActivity { - private static boolean init =false; //To initialize stuff only once per app start - protected static OkHttpClient client; protected static CookieJar cookieJar; protected static SharedPrefsCookiePersistor sharedPrefsCookiePersistor; - protected static Thmmy.LoginData loginData; + private static boolean init =false; //To initialize stuff only once per app start + + public static CookieJar getCookieJar() + { + return cookieJar; + } + + public static SharedPrefsCookiePersistor getSharedPrefsCookiePersistor() { + return sharedPrefsCookiePersistor; + } + + public static OkHttpClient getClient() { + return client; + } @Override protected void onCreate(Bundle savedInstanceState) { @@ -39,20 +50,7 @@ public class BaseActivity extends AppCompatActivity { } - public static CookieJar getCookieJar() - { - return cookieJar; - } - - public static SharedPrefsCookiePersistor getSharedPrefsCookiePersistor() { - return sharedPrefsCookiePersistor; - } - - public static OkHttpClient getClient() { - return client; - } - public void setLoginData(Thmmy.LoginData loginData) { - this.loginData = loginData; + BaseActivity.loginData = loginData; } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java index ee086929..d62c9334 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/LoginActivity.java @@ -23,19 +23,19 @@ import static gr.thmmy.mthmmy.utils.Thmmy.login; public class LoginActivity extends BaseActivity { private static final String TAG = "LoginActivity"; private static boolean passed=false; //becomes true after (guest) login - to redirect to Main - private EditText inputUsername; - private EditText inputPassword; Button btnLogin; Button btnGuest; + private EditText inputUsername; + private EditText inputPassword; @Override public void onCreate(Bundle savedInstanceState) { - if(passed) //redirect to MainActivity if user passed this one at least once + /*if(passed) //redirect to MainActivity if user passed this one at least once { Intent intent = new Intent(LoginActivity.this, MainActivity.class); startActivity(intent); finish(); - } + }*/ super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); @@ -89,6 +89,29 @@ public class LoginActivity extends BaseActivity { btnLogin.setEnabled(true); } + public boolean validate() { + boolean valid = true; + + String email = inputUsername.getText().toString(); + String password = inputPassword.getText().toString(); + + if (email.isEmpty()) { + inputUsername.setError("Enter a valid username"); + valid = false; + } else { + inputUsername.setError(null); + } + + if (password.isEmpty()) { + inputPassword.setError("Enter a valid password"); + valid = false; + } else { + inputPassword.setError(null); + } + + return valid; + } + private class LoginTask extends AsyncTask { ProgressDialog progressDialog; @@ -154,28 +177,5 @@ public class LoginActivity extends BaseActivity { progressDialog.dismiss(); } } - - public boolean validate() { - boolean valid = true; - - String email = inputUsername.getText().toString(); - String password = inputPassword.getText().toString(); - - if (email.isEmpty()) { - inputUsername.setError("Enter a valid username"); - valid = false; - } else { - inputUsername.setError(null); - } - - if (password.isEmpty()) { - inputPassword.setError("Enter a valid password"); - valid = false; - } else { - inputPassword.setError(null); - } - - return valid; - } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/MainActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/MainActivity.java index 8d38bf1e..aea722cb 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/MainActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/MainActivity.java @@ -79,6 +79,12 @@ public class MainActivity extends BaseActivity implements RecentFragment.OnListF } else if (id == R.id.action_logout) new LogoutTask().execute(); + else{ + Intent intent = new Intent(MainActivity.this,LoginActivity.class); + startActivity(intent); + finish(); + overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out); + } return super.onOptionsItemSelected(item); } diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/TopicActivity.java index b153e47f..3dbadff0 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/activities/TopicActivity.java +++ b/app/src/main/java/gr/thmmy/mthmmy/activities/TopicActivity.java @@ -1,20 +1,32 @@ package gr.thmmy.mthmmy.activities; +import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; +import android.util.SparseArray; +import android.view.Gravity; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.EditorInfo; import android.webkit.WebView; +import android.widget.EditText; +import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.toolbox.ImageLoader; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.select.Elements; import java.util.ArrayList; import java.util.List; @@ -23,46 +35,87 @@ import javax.net.ssl.SSLHandshakeException; import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.data.Post; +import gr.thmmy.mthmmy.utils.CircularNetworkImageView; import gr.thmmy.mthmmy.utils.CustomRecyclerView; +import gr.thmmy.mthmmy.utils.ImageController; import okhttp3.Request; import okhttp3.Response; public class TopicActivity extends BaseActivity { - - private CustomRecyclerView recyclerView; + private ImageLoader imageLoader = ImageController.getInstance().getImageLoader(); private TopicAdapter topicAdapter; private ProgressBar progressBar; - private List postsList; + private EditText pageSelect; + + private int thisPage = 1; + private SparseArray pagesUrls = new SparseArray<>(); + private String base_url = ""; + private int numberOfPages = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_topic); + Bundle extras = getIntent().getExtras(); + final String topicTitle = getIntent().getExtras().getString("TOPIC_TITLE"); + progressBar = (ProgressBar) findViewById(R.id.progressBar); + if (imageLoader == null) + imageLoader = ImageController.getInstance().getImageLoader(); - Bundle extras = getIntent().getExtras(); ActionBar actionbar = getSupportActionBar(); - if(actionbar!=null) - actionbar.setTitle(extras.getString("TOPIC_TITLE")); + if (actionbar != null) + actionbar.setTitle(topicTitle); + + ActionBar.LayoutParams lp = new ActionBar.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT + , LinearLayout.LayoutParams.WRAP_CONTENT + , Gravity.END | Gravity.CENTER_VERTICAL); + View customNav = LayoutInflater.from(this).inflate(R.layout.topic_page_select, null); + + pageSelect = (EditText) customNav.findViewById(R.id.select_page); + pageSelect.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_GO) { + int pageRequested = Integer.parseInt(pageSelect.getText().toString()); + if (pageRequested == thisPage) { + Toast.makeText(getBaseContext() + , "You already are here!", Toast.LENGTH_LONG).show(); + } else if (pageRequested >= 1 && pageRequested <= numberOfPages) { + Intent intent = getIntent(); + intent.putExtra("TOPIC_URL", pagesUrls.get(pageRequested - 1)); + intent.putExtra("TOPIC_TITLE", topicTitle); + finish(); + startActivity(intent); + } else { + Toast.makeText(getBaseContext() + , "There is no such page!", Toast.LENGTH_LONG).show(); + } + } + return true; + } + }); + assert actionbar != null; + actionbar.setCustomView(customNav, lp); + actionbar.setDisplayShowCustomEnabled(true); - postsList = new ArrayList<>(); + postsList = new ArrayList<>(); topicAdapter = new TopicAdapter(); - recyclerView = (CustomRecyclerView) findViewById(R.id.list); - recyclerView.setLayoutManager(new LinearLayoutManager(findViewById(R.id.list).getContext())); + CustomRecyclerView recyclerView = (CustomRecyclerView) findViewById(R.id.posts_list); + recyclerView.setLayoutManager(new LinearLayoutManager(findViewById(R.id.posts_list).getContext())); recyclerView.setAdapter(topicAdapter); new TopicTask().execute(extras.getString("TOPIC_URL")); - } - private class TopicAdapter extends RecyclerView.Adapter - { + private class TopicAdapter extends RecyclerView.Adapter { @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) @@ -71,29 +124,19 @@ public class TopicActivity extends BaseActivity { } - @Override public void onBindViewHolder(final ViewHolder holder, final int position) { +//----------------------------------- Holder behaves erratically ----------------------------------- + if (postsList.get(position).getThumbnailUrl() != "") { + holder.mThumbnailView.setImageUrl(postsList.get(position).getThumbnailUrl(), imageLoader); + } holder.mAuthorView.setText(postsList.get(position).getAuthor()); - holder.mDateTimeView.setText(postsList.get(position).getDateTime()); - holder.mContentView.loadData(postsList.get(position).getContent(), "text/html", null); - -// holder.topic = recentList.get(position); -// -// holder.mView.setOnClickListener(new View.OnClickListener() { -// @Override -// public void onClick(View v) { -// -// if (null != mListener) { -// // Notify the active callbacks interface (the activity, if the -// // fragment is attached to one) that an item has been selected. -// mListener.onFragmentInteraction(holder.topic); //? -// -// } -// -// } -// }); + holder.mSubjectView.setText(postsList.get(position).getDateTime()); + holder.mContentView.loadDataWithBaseURL("file:///android_asset/" + , postsList.get(position).getContent() + , "text/html", "UTF-8", null); +//----------------------------------- Holder behaves erratically ----------------------------------- } @Override @@ -101,30 +144,30 @@ public class TopicActivity extends BaseActivity { return postsList.size(); } - public class ViewHolder extends RecyclerView.ViewHolder { - public final View mView; - public final TextView mAuthorView; - public final WebView mContentView; - public final TextView mDateTimeView; + class ViewHolder extends RecyclerView.ViewHolder { + final View mView; + final CircularNetworkImageView mThumbnailView; + final TextView mAuthorView; + final TextView mSubjectView; + final WebView mContentView; - public ViewHolder(View view) { + ViewHolder(View view) { super(view); mView = view; - mAuthorView = (TextView) view.findViewById(R.id.author); - mContentView = (WebView) view.findViewById(R.id.content); - mDateTimeView = (TextView) view.findViewById(R.id.dateTime); + mThumbnailView = (CircularNetworkImageView) view.findViewById(R.id.thumbnail); + mAuthorView = (TextView) view.findViewById(R.id.username); + mSubjectView = (TextView) view.findViewById(R.id.subject); + mContentView = (WebView) view.findViewById(R.id.post); } } } - //---------------------------------------TOPIC ASYNC TASK------------------------------------------- - public class TopicTask extends AsyncTask - { - private static final String TAG="TopicTask"; + public class TopicTask extends AsyncTask { + private static final String TAG = "TopicTask"; private String pageLink; private Document document; @@ -134,8 +177,9 @@ public class TopicActivity extends BaseActivity { progressBar.setVisibility(ProgressBar.VISIBLE); } - protected Boolean doInBackground(String... strings) - { + protected Boolean doInBackground(String... strings) { + base_url = strings[0].substring(0, strings[0].lastIndexOf(".")); + pageLink = strings[0]; Request request = new Request.Builder() @@ -154,23 +198,73 @@ public class TopicActivity extends BaseActivity { Log.e("TAG", "ERROR", e); return false; } - } - - protected void onPostExecute(Boolean result) - { + protected void onPostExecute(Boolean result) { progressBar.setVisibility(ProgressBar.INVISIBLE); topicAdapter.notifyDataSetChanged(); + pageSelect.setHint(String.valueOf(thisPage) + "/" + String.valueOf(numberOfPages)); } - private boolean parse(Document document) - { - return true; + private boolean parse(Document document) { + { + Elements findCurrentPage = document.select("td:contains(Pages:)>b"); + for (Element item : findCurrentPage) { + if (!item.text().contains("...") + && !item.text().contains("Pages")) { + thisPage = Integer.parseInt(item.text()); + break; + } + } + } + { + Elements footer_pages = document.select("td:contains(Pages:)>a.navPages"); + if (footer_pages.size() != 0) { + numberOfPages = thisPage; + for (Element item : footer_pages) { + if (Integer.parseInt(item.text()) > numberOfPages) + numberOfPages = Integer.parseInt(item.text()); + } + } + for (int i = 0; i < numberOfPages; i++) { + pagesUrls.put(i, base_url + "." + String.valueOf(i * 15)); + } + } + Elements form_quickModForm = document.select("form[id=quickModForm]"); + Elements nickNames = form_quickModForm.select("a[title^=View the profile of]"); + Elements topic_subjectS = form_quickModForm.select("div[id^=subject_]"); + Elements postTextS = form_quickModForm.select("div").select(".post"); + Elements img_smalltexts = form_quickModForm.select("div").select(":matches(Posts:)"); + //Elements replies_smalltexts = form_quickModForm.select("div.smalltext:matches(Reply #)"); + + for (int i = 0; i < nickNames.size(); i++) { + + String tmp_nickName = nickNames.get(i).html(); + Element thumbnail_urls = img_smalltexts.get(i).select("img").select(".avatar").first(); + + String tmp_url = ""; + if (thumbnail_urls != null) { + tmp_url = thumbnail_urls.attr("abs:src"); + } + String tmp_topic_subject = topic_subjectS.get(i).select("a").first().text(); + String tmp_post_text = postTextS.get(i).html(); + tmp_post_text = ("" + tmp_post_text); //style.css + + + /*int tmp_postNum = 0; //topic starter + if (replies_smalltexts.size() == nickNames.size()) { + String tmp_prep = replies_smalltexts.get(i).text().substring(9); + tmp_postNum = Integer.parseInt(tmp_prep.substring(0, tmp_prep.indexOf(" on"))); + } else if (i != 0) { + String tmp_prep = replies_smalltexts.get(i - 1).text().substring(9); + tmp_postNum = Integer.parseInt(tmp_prep.substring(0, tmp_prep.indexOf(" on"))); + }*/ + + postsList.add(new Post(tmp_url, tmp_nickName, tmp_topic_subject, tmp_post_text)); + } + return true; } - - } } 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 c7eb6bee..05a579cb 100644 --- a/app/src/main/java/gr/thmmy/mthmmy/data/Post.java +++ b/app/src/main/java/gr/thmmy/mthmmy/data/Post.java @@ -1,20 +1,21 @@ package gr.thmmy.mthmmy.data; -/** - * Created by ezero on 14/9/2016. - */ public class Post { + private final String thumbnailUrl; private final String author; - private final String dateTime; + private final String subject; private String content; - public Post(String author, String dateTime, String content) { + public Post(String thumbnailUrl, String author, String subject, String content) { + this.thumbnailUrl = thumbnailUrl; this.author = author; - this.dateTime = dateTime; + this.subject = subject; this.content = content; } + public String getThumbnailUrl() { return thumbnailUrl;} + public String getContent() { return content; } @@ -24,6 +25,6 @@ public class Post } public String getDateTime() { - return dateTime; + return subject; } } diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/CircularNetworkImageView.java b/app/src/main/java/gr/thmmy/mthmmy/utils/CircularNetworkImageView.java new file mode 100644 index 00000000..e6420d1a --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/CircularNetworkImageView.java @@ -0,0 +1,87 @@ +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 = 100; + 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; + } + + public static Bitmap scaleDown(Bitmap realImage, float maxImageSize, + boolean filter) { + float ratio = Math.min( + maxImageSize / realImage.getWidth(), + maxImageSize / realImage.getHeight()); + int width = Math.round(ratio * realImage.getWidth()); + int height = Math.round(ratio * realImage.getHeight()); + + return Bitmap.createScaledBitmap(realImage, width, + height, filter); + } + + @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 + * + * @param bitmap + * @return bitmap + */ + public Bitmap getCircularBitmap(Bitmap bitmap) { + Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), + bitmap.getHeight(), Config.ARGB_8888); + Canvas canvas = new Canvas(output); + int width = bitmap.getWidth(); + if(bitmap.getWidth()>bitmap.getHeight()) + width = bitmap.getHeight(); + final int color = 0xff424242; + final Paint paint = new Paint(); + final Rect rect = new Rect(0, 0, width, width); + final RectF rectF = new RectF(rect); + final float roundPx = width / 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); + + output = scaleDown(output, THUMBNAIL_SIZE, true); + 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 new file mode 100644 index 00000000..864dbcd5 --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/ImageController.java @@ -0,0 +1,63 @@ +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 { + + public 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; + } + + public 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(Object tag) { + if (mRequestQueue != null) { + mRequestQueue.cancelAll(tag); + } + } +} + + diff --git a/app/src/main/java/gr/thmmy/mthmmy/utils/LruBitmapCache.java b/app/src/main/java/gr/thmmy/mthmmy/utils/LruBitmapCache.java new file mode 100644 index 00000000..330c2e45 --- /dev/null +++ b/app/src/main/java/gr/thmmy/mthmmy/utils/LruBitmapCache.java @@ -0,0 +1,41 @@ +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/anim/push_right_in.xml b/app/src/main/res/anim/push_right_in.xml new file mode 100644 index 00000000..6b4cdf8d --- /dev/null +++ b/app/src/main/res/anim/push_right_in.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/anim/push_right_out.xml b/app/src/main/res/anim/push_right_out.xml new file mode 100644 index 00000000..1d45e3b5 --- /dev/null +++ b/app/src/main/res/anim/push_right_out.xml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/page_first.xml b/app/src/main/res/drawable/page_first.xml new file mode 100644 index 00000000..258658e2 --- /dev/null +++ b/app/src/main/res/drawable/page_first.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/page_last.xml b/app/src/main/res/drawable/page_last.xml new file mode 100644 index 00000000..9e9d9915 --- /dev/null +++ b/app/src/main/res/drawable/page_last.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/page_next.xml b/app/src/main/res/drawable/page_next.xml new file mode 100644 index 00000000..7692c3ef --- /dev/null +++ b/app/src/main/res/drawable/page_next.xml @@ -0,0 +1,8 @@ + + + + diff --git a/app/src/main/res/drawable/page_previous.xml b/app/src/main/res/drawable/page_previous.xml new file mode 100644 index 00000000..58c22797 --- /dev/null +++ b/app/src/main/res/drawable/page_previous.xml @@ -0,0 +1,8 @@ + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index a471081e..f374eccd 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,5 +1,6 @@ - - - + android:layout_height="wrap_content"/> - - - + app:layout_behavior="@string/appbar_scrolling_view_behavior"/> diff --git a/app/src/main/res/layout/activity_topic.xml b/app/src/main/res/layout/activity_topic.xml index 154aa4b2..fb2bbd67 100644 --- a/app/src/main/res/layout/activity_topic.xml +++ b/app/src/main/res/layout/activity_topic.xml @@ -1,34 +1,34 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@color/background" + tools:context="gr.thmmy.mthmmy.activities.TopicActivity"> + android:id="@+id/posts_list" + android:name="gr.thmmy.mthmmy.activities.Topic" + class="gr.thmmy.mthmmy.utils.CustomRecyclerView" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_alignParentTop="true" + android:clipToPadding="false" + android:paddingBottom="4dp" + android:paddingTop="4dp" + app:layoutManager="LinearLayoutManager" + tools:context="gr.thmmy.mthmmy.activities.TopicActivity" + tools:listitem="@layout/activity_topic_post_row"/> - + android:visibility="invisible"/> diff --git a/app/src/main/res/layout/activity_topic_post_row.xml b/app/src/main/res/layout/activity_topic_post_row.xml index 2242102d..456db2f6 100644 --- a/app/src/main/res/layout/activity_topic_post_row.xml +++ b/app/src/main/res/layout/activity_topic_post_row.xml @@ -1,111 +1,104 @@ - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_gravity="center" + android:foreground="?android:attr/selectableItemBackground" + card_view:cardBackgroundColor="@color/white" + card_view:cardCornerRadius="0dp" + card_view:cardElevation="2dp" + card_view:cardPreventCornerOverlap="true" + card_view:cardUseCompatPadding="true"> + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/fragment_recent.xml b/app/src/main/res/layout/fragment_recent.xml index 9e185aab..845233f2 100644 --- a/app/src/main/res/layout/fragment_recent.xml +++ b/app/src/main/res/layout/fragment_recent.xml @@ -3,8 +3,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" - android:layout_height="match_parent" - android:layout_width="match_parent"> + android:layout_width="match_parent" + android:layout_height="match_parent"> - + tools:listitem="@layout/fragment_recent_row"/> + android:visibility="invisible"/> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_recent_row.xml b/app/src/main/res/layout/fragment_recent_row.xml index bfc62f09..8c62b89e 100644 --- a/app/src/main/res/layout/fragment_recent_row.xml +++ b/app/src/main/res/layout/fragment_recent_row.xml @@ -1,77 +1,68 @@ + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingEnd="4dp" + android:paddingStart="4dp"> - - - - - - - - + android:layout_alignParentTop="true" + android:paddingBottom="6dp" + android:paddingLeft="10dp" + android:paddingRight="10dp" + android:paddingTop="6dp"> + + - + + + - - \ No newline at end of file diff --git a/app/src/main/res/layout/topic_page_select.xml b/app/src/main/res/layout/topic_page_select.xml new file mode 100644 index 00000000..e2ac2907 --- /dev/null +++ b/app/src/main/res/layout/topic_page_select.xml @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 88b48966..cd46d12c 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,30 +1,17 @@ - - - - + #3F51B5 #303F9F #C5CAE9 #FFFFFF #E7E7E7 #757575 + #FFFFFF + #8B8B8B #00000000 #ffffff #CCCCCC - #616161 - - #ffb74d - #1e88e5 - #f57f17 - #7e57c2 - #388e3c - #d32f2f + #D3D3D3 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 444ec77e..854e6cdf 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -9,6 +9,7 @@ @color/primary_text @color/secondary_text @color/primary + @color/card_background @color/iron @color/white