mirror of https://github.com/ThmmyNoLife/mTHMMY
Browse Source
# Conflicts: # app/build.gradle # app/src/main/java/gr/thmmy/mthmmy/activities/AboutActivity.java # app/src/main/java/gr/thmmy/mthmmy/activities/bookmarks/BoardBookmarksFragment.java # app/src/main/java/gr/thmmy/mthmmy/activities/downloads/DownloadsActivity.java # app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java # app/src/main/java/gr/thmmy/mthmmy/base/BaseActivity.java # app/src/main/java/gr/thmmy/mthmmy/base/BaseApplication.java # app/src/main/java/gr/thmmy/mthmmy/editorview/EditorView.java # app/src/main/res/layout/activity_downloads.xml # app/src/main/res/xml/app_preferences_user.xml # build.gradlepull/61/merge
Thodoris1999
6 years ago
103 changed files with 1316 additions and 367 deletions
@ -0,0 +1,50 @@ |
|||
package gr.thmmy.mthmmy.activities.shoutbox; |
|||
|
|||
import org.jsoup.nodes.Document; |
|||
|
|||
import java.io.IOException; |
|||
|
|||
import gr.thmmy.mthmmy.utils.NetworkResultCodes; |
|||
import gr.thmmy.mthmmy.utils.NetworkTask; |
|||
import okhttp3.MultipartBody; |
|||
import okhttp3.OkHttpClient; |
|||
import okhttp3.Request; |
|||
import okhttp3.Response; |
|||
|
|||
public class SendShoutTask extends NetworkTask<Void> { |
|||
|
|||
public SendShoutTask(OnTaskStartedListener onTaskStartedListener, OnNetworkTaskFinishedListener<Void> onNetworkTaskFinishedListener) { |
|||
super(onTaskStartedListener, onNetworkTaskFinishedListener); |
|||
} |
|||
|
|||
@Override |
|||
protected Response sendRequest(OkHttpClient client, String... input) throws IOException { |
|||
MultipartBody.Builder postBodyBuilder = new MultipartBody.Builder() |
|||
.setType(MultipartBody.FORM) |
|||
.addFormDataPart("sc", input[2]) |
|||
.addFormDataPart("tp-shout", input[1]) |
|||
.addFormDataPart("tp-shout-name", input[3]) |
|||
.addFormDataPart("shout_send", input[4]) |
|||
.addFormDataPart("tp-shout-url", input[5]); |
|||
|
|||
Request voteRequest = new Request.Builder() |
|||
.url(input[0]) |
|||
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36") |
|||
.post(postBodyBuilder.build()) |
|||
.build(); |
|||
client.newCall(voteRequest).execute(); |
|||
return client.newCall(voteRequest).execute(); |
|||
} |
|||
|
|||
|
|||
|
|||
@Override |
|||
protected Void performTask(Document document, Response response) { |
|||
return null; |
|||
} |
|||
|
|||
@Override |
|||
protected int getResultCode(Response response, Void data) { |
|||
return NetworkResultCodes.SUCCESSFUL; |
|||
} |
|||
} |
@ -0,0 +1,154 @@ |
|||
package gr.thmmy.mthmmy.activities.shoutbox; |
|||
|
|||
import android.annotation.TargetApi; |
|||
import android.content.Context; |
|||
import android.content.Intent; |
|||
import android.net.Uri; |
|||
import android.os.Build; |
|||
import android.os.Bundle; |
|||
import android.view.LayoutInflater; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.webkit.WebResourceRequest; |
|||
import android.webkit.WebView; |
|||
import android.webkit.WebViewClient; |
|||
import android.widget.TextView; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import gr.thmmy.mthmmy.R; |
|||
import gr.thmmy.mthmmy.activities.board.BoardActivity; |
|||
import gr.thmmy.mthmmy.activities.profile.ProfileActivity; |
|||
import gr.thmmy.mthmmy.activities.topic.TopicActivity; |
|||
import gr.thmmy.mthmmy.model.Shout; |
|||
import gr.thmmy.mthmmy.model.ThmmyPage; |
|||
import gr.thmmy.mthmmy.utils.CustomRecyclerView; |
|||
|
|||
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; |
|||
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE; |
|||
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL; |
|||
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL; |
|||
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL; |
|||
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME; |
|||
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL; |
|||
|
|||
public class ShoutAdapter extends CustomRecyclerView.Adapter<ShoutAdapter.ShoutViewHolder> { |
|||
private Context context; |
|||
private Shout[] shouts; |
|||
|
|||
public ShoutAdapter(Context context, Shout[] shouts) { |
|||
this.context = context; |
|||
this.shouts = shouts; |
|||
} |
|||
|
|||
public void setShouts(Shout[] shouts) { |
|||
this.shouts = shouts; |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public ShoutViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { |
|||
View view = LayoutInflater.from(parent.getContext()) |
|||
.inflate(R.layout.fragment_shoutbox_shout_row, parent, false); |
|||
return new ShoutViewHolder(view); |
|||
} |
|||
|
|||
@Override |
|||
public void onBindViewHolder(@NonNull ShoutViewHolder holder, int position) { |
|||
Shout currentShout = shouts[position]; |
|||
holder.author.setText(currentShout.getShouter()); |
|||
if (currentShout.isMemberOfTheMonth()) holder.author.setTextColor(context.getResources().getColor(R.color.member_of_the_month)); |
|||
else holder.author.setTextColor(context.getResources().getColor(R.color.accent)); |
|||
holder.author.setOnClickListener(view -> { |
|||
Intent intent = new Intent(context, ProfileActivity.class); |
|||
Bundle extras = new Bundle(); |
|||
extras.putString(BUNDLE_PROFILE_URL, shouts[holder.getAdapterPosition()].getShouterProfileURL()); |
|||
extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, ""); |
|||
extras.putString(BUNDLE_PROFILE_USERNAME, ""); |
|||
intent.putExtras(extras); |
|||
intent.setFlags(FLAG_ACTIVITY_NEW_TASK); |
|||
context.startActivity(intent); |
|||
}); |
|||
holder.dateTime.setText(currentShout.getDate()); |
|||
holder.shoutContent.setClickable(true); |
|||
holder.shoutContent.setWebViewClient(new LinkLauncher()); |
|||
holder.shoutContent.loadDataWithBaseURL("file:///android_asset/", currentShout.getShout(), |
|||
"text/html", "UTF-8", null); |
|||
} |
|||
|
|||
@Override |
|||
public int getItemCount() { |
|||
return shouts.length; |
|||
} |
|||
|
|||
static class ShoutViewHolder extends CustomRecyclerView.ViewHolder { |
|||
|
|||
TextView author, dateTime; |
|||
WebView shoutContent; |
|||
|
|||
ShoutViewHolder(@NonNull View itemView) { |
|||
super(itemView); |
|||
|
|||
author = itemView.findViewById(R.id.author_textview); |
|||
dateTime = itemView.findViewById(R.id.date_time_textview); |
|||
shoutContent = itemView.findViewById(R.id.shout_content); |
|||
} |
|||
} |
|||
|
|||
class LinkLauncher extends WebViewClient { |
|||
|
|||
@TargetApi(Build.VERSION_CODES.LOLLIPOP) |
|||
@Override |
|||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { |
|||
final Uri uri = request.getUrl(); |
|||
return handleUri(uri); |
|||
} |
|||
|
|||
@Override |
|||
public boolean shouldOverrideUrlLoading(WebView view, String url) { |
|||
final Uri uri = Uri.parse(url); |
|||
return handleUri(uri); |
|||
} |
|||
|
|||
private boolean handleUri(Uri uri) { |
|||
final String uriString = uri.toString(); |
|||
|
|||
ThmmyPage.PageCategory target = ThmmyPage.resolvePageCategory(uri); |
|||
if (target.is(ThmmyPage.PageCategory.TOPIC)) { |
|||
//This url points to a topic
|
|||
Intent intent = new Intent(context, TopicActivity.class); |
|||
Bundle extras = new Bundle(); |
|||
extras.putString(BUNDLE_TOPIC_URL, uriString); |
|||
intent.putExtras(extras); |
|||
intent.setFlags(FLAG_ACTIVITY_NEW_TASK); |
|||
context.startActivity(intent); |
|||
return true; |
|||
} else if (target.is(ThmmyPage.PageCategory.BOARD)) { |
|||
Intent intent = new Intent(context, BoardActivity.class); |
|||
Bundle extras = new Bundle(); |
|||
extras.putString(BUNDLE_BOARD_URL, uriString); |
|||
extras.putString(BUNDLE_BOARD_TITLE, ""); |
|||
intent.putExtras(extras); |
|||
intent.setFlags(FLAG_ACTIVITY_NEW_TASK); |
|||
context.startActivity(intent); |
|||
return true; |
|||
} else if (target.is(ThmmyPage.PageCategory.PROFILE)) { |
|||
Intent intent = new Intent(context, ProfileActivity.class); |
|||
Bundle extras = new Bundle(); |
|||
extras.putString(BUNDLE_PROFILE_URL, uriString); |
|||
extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, ""); |
|||
extras.putString(BUNDLE_PROFILE_USERNAME, ""); |
|||
intent.putExtras(extras); |
|||
intent.setFlags(FLAG_ACTIVITY_NEW_TASK); |
|||
context.startActivity(intent); |
|||
return true; |
|||
} |
|||
|
|||
Intent intent = new Intent(Intent.ACTION_VIEW, uri); |
|||
intent.setFlags(FLAG_ACTIVITY_NEW_TASK); |
|||
context.startActivity(intent); |
|||
|
|||
//Method always returns true as no url should be loaded in the WebViews
|
|||
return true; |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,39 @@ |
|||
package gr.thmmy.mthmmy.activities.shoutbox; |
|||
|
|||
import android.os.Bundle; |
|||
|
|||
import gr.thmmy.mthmmy.R; |
|||
import gr.thmmy.mthmmy.base.BaseActivity; |
|||
|
|||
public class ShoutboxActivity extends BaseActivity { |
|||
|
|||
@Override |
|||
protected void onCreate(Bundle savedInstanceState) { |
|||
super.onCreate(savedInstanceState); |
|||
setContentView(R.layout.activity_shoutbox); |
|||
|
|||
//Initialize toolbar
|
|||
toolbar = findViewById(R.id.toolbar); |
|||
toolbar.setTitle("Shoutbox"); |
|||
setSupportActionBar(toolbar); |
|||
if (getSupportActionBar() != null) { |
|||
getSupportActionBar().setDisplayHomeAsUpEnabled(true); |
|||
getSupportActionBar().setDisplayShowHomeEnabled(true); |
|||
} |
|||
|
|||
createDrawer(); |
|||
drawer.setSelection(SHOUTBOX_ID); |
|||
|
|||
if (savedInstanceState == null) { |
|||
getSupportFragmentManager().beginTransaction() |
|||
.replace(R.id.container, ShoutboxFragment.newInstance()) |
|||
.commitNow(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
protected void onResume() { |
|||
drawer.setSelection(SHOUTBOX_ID); |
|||
super.onResume(); |
|||
} |
|||
} |
@ -0,0 +1,182 @@ |
|||
package gr.thmmy.mthmmy.activities.shoutbox; |
|||
|
|||
import android.app.Activity; |
|||
import android.os.Bundle; |
|||
import android.view.LayoutInflater; |
|||
import android.view.Menu; |
|||
import android.view.MenuInflater; |
|||
import android.view.MenuItem; |
|||
import android.view.View; |
|||
import android.view.ViewGroup; |
|||
import android.view.inputmethod.InputConnection; |
|||
import android.view.inputmethod.InputMethodManager; |
|||
import android.widget.Toast; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import androidx.annotation.Nullable; |
|||
import androidx.fragment.app.Fragment; |
|||
import androidx.lifecycle.ViewModelProviders; |
|||
import androidx.recyclerview.widget.LinearLayoutManager; |
|||
import gr.thmmy.mthmmy.R; |
|||
import gr.thmmy.mthmmy.editorview.EditorView; |
|||
import gr.thmmy.mthmmy.editorview.EmojiKeyboard; |
|||
import gr.thmmy.mthmmy.model.Shout; |
|||
import gr.thmmy.mthmmy.model.Shoutbox; |
|||
import gr.thmmy.mthmmy.session.SessionManager; |
|||
import gr.thmmy.mthmmy.utils.CustomRecyclerView; |
|||
import gr.thmmy.mthmmy.utils.NetworkResultCodes; |
|||
import gr.thmmy.mthmmy.viewmodel.ShoutboxViewModel; |
|||
import me.zhanghai.android.materialprogressbar.MaterialProgressBar; |
|||
import timber.log.Timber; |
|||
|
|||
public class ShoutboxFragment extends Fragment implements EmojiKeyboard.EmojiKeyboardOwner { |
|||
|
|||
private MaterialProgressBar progressBar; |
|||
private ShoutboxTask shoutboxTask; |
|||
private ShoutAdapter shoutAdapter; |
|||
private EmojiKeyboard emojiKeyboard; |
|||
private EditorView editorView; |
|||
|
|||
private ShoutboxViewModel shoutboxViewModel; |
|||
|
|||
public static ShoutboxFragment newInstance() { |
|||
return new ShoutboxFragment(); |
|||
} |
|||
|
|||
@Nullable |
|||
@Override |
|||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, |
|||
@Nullable Bundle savedInstanceState) { |
|||
final View rootView = inflater.inflate(R.layout.fragment_shoutbox, container, false); |
|||
setHasOptionsMenu(true); |
|||
|
|||
progressBar = rootView.findViewById(R.id.progressBar); |
|||
CustomRecyclerView recyclerView = rootView.findViewById(R.id.shoutbox_recyclerview); |
|||
shoutAdapter = new ShoutAdapter(getContext(), new Shout[0]); |
|||
recyclerView.setAdapter(shoutAdapter); |
|||
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext()); |
|||
layoutManager.setReverseLayout(true); |
|||
recyclerView.setLayoutManager(layoutManager); |
|||
recyclerView.setOnTouchListener((view, motionEvent) -> { |
|||
editorView.hideMarkdown(); |
|||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Activity.INPUT_METHOD_SERVICE); |
|||
imm.hideSoftInputFromWindow(editorView.getWindowToken(), 0); |
|||
return false; |
|||
}); |
|||
|
|||
emojiKeyboard = rootView.findViewById(R.id.emoji_keyboard); |
|||
editorView = rootView.findViewById(R.id.edior_view); |
|||
editorView.setEmojiKeyboardOwner(this); |
|||
InputConnection ic = editorView.getInputConnection(); |
|||
setEmojiKeyboardInputConnection(ic); |
|||
editorView.setOnSubmitListener(view -> { |
|||
if (shoutboxViewModel.getShoutboxMutableLiveData().getValue() == null) return; |
|||
if (editorView.getText().toString().isEmpty()) { |
|||
editorView.setError("Required"); |
|||
return; |
|||
} |
|||
shoutboxViewModel.sendShout(editorView.getText().toString()); |
|||
}); |
|||
editorView.hideMarkdown(); |
|||
editorView.setOnTouchListener((view, motionEvent) -> { |
|||
editorView.showMarkdown(); |
|||
return false; |
|||
}); |
|||
editorView.setMarkdownVisible(false); |
|||
editorView.showMarkdownOnfocus(); |
|||
|
|||
return rootView; |
|||
} |
|||
|
|||
@Override |
|||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { |
|||
inflater.inflate(R.menu.shoutbox_menu, menu); |
|||
} |
|||
|
|||
@Override |
|||
public boolean onOptionsItemSelected(MenuItem item) { |
|||
if (item.getItemId() == R.id.menu_refresh) { |
|||
shoutboxViewModel.loadShoutbox(); |
|||
return true; |
|||
} else { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onActivityCreated(@Nullable Bundle savedInstanceState) { |
|||
super.onActivityCreated(savedInstanceState); |
|||
shoutboxViewModel = ViewModelProviders.of(this).get(ShoutboxViewModel.class); |
|||
shoutboxViewModel.getShoutboxMutableLiveData().observe(this, shoutbox -> { |
|||
if (shoutbox != null) { |
|||
Timber.i("Shoutbox loaded successfully"); |
|||
shoutAdapter.setShouts(shoutbox.getShouts()); |
|||
shoutAdapter.notifyDataSetChanged(); |
|||
} |
|||
}); |
|||
shoutboxViewModel.setOnShoutboxTaskStarted(this::onShoutboxTaskSarted); |
|||
shoutboxViewModel.setOnShoutboxTaskFinished(this::onShoutboxTaskFinished); |
|||
shoutboxViewModel.setOnSendShoutTaskStarted(this::onSendShoutTaskStarted); |
|||
shoutboxViewModel.setOnSendShoutTaskFinished(this::onSendShoutTaskFinished); |
|||
|
|||
shoutboxViewModel.loadShoutbox(); |
|||
} |
|||
|
|||
private void onShoutboxTaskSarted() { |
|||
Timber.i("Starting shoutbox task..."); |
|||
progressBar.setVisibility(View.VISIBLE); |
|||
} |
|||
|
|||
private void onSendShoutTaskStarted() { |
|||
Timber.i("Start sending a shout..."); |
|||
editorView.setAlpha(0.5f); |
|||
editorView.setEnabled(false); |
|||
setEmojiKeyboardVisible(false); |
|||
progressBar.setVisibility(View.VISIBLE); |
|||
} |
|||
|
|||
private void onSendShoutTaskFinished(int resultCode, Void ignored) { |
|||
editorView.setAlpha(1f); |
|||
editorView.setEnabled(true); |
|||
progressBar.setVisibility(View.INVISIBLE); |
|||
if (resultCode == NetworkResultCodes.SUCCESSFUL) { |
|||
Timber.i("Shout was sent successfully"); |
|||
editorView.getEditText().getText().clear(); |
|||
shoutboxTask = new ShoutboxTask(ShoutboxFragment.this::onShoutboxTaskSarted, ShoutboxFragment.this::onShoutboxTaskFinished); |
|||
shoutboxTask.execute(SessionManager.shoutboxUrl.toString()); |
|||
} else if (resultCode == NetworkResultCodes.NETWORK_ERROR) { |
|||
Timber.w("Failed to send shout"); |
|||
Toast.makeText(getContext(), "NetworkError", Toast.LENGTH_SHORT).show(); |
|||
} |
|||
} |
|||
|
|||
private void onShoutboxTaskFinished(int resultCode, Shoutbox shoutbox) { |
|||
progressBar.setVisibility(View.INVISIBLE); |
|||
if (resultCode == NetworkResultCodes.SUCCESSFUL) { |
|||
shoutboxViewModel.setShoutbox(shoutbox); |
|||
if (shoutbox.getShoutSend() != null) |
|||
editorView.setVisibility(View.VISIBLE); |
|||
} else if (resultCode == NetworkResultCodes.NETWORK_ERROR) { |
|||
Timber.w("Failed to retreive shoutbox due to network error"); |
|||
Toast.makeText(getContext(), "NetworkError", Toast.LENGTH_SHORT).show(); |
|||
} else { |
|||
Timber.wtf("Failed to retreive shoutbox due to unknown error"); |
|||
Toast.makeText(getContext(), "Failed to retrieve shoutbox, please contact mthmmy developer team", Toast.LENGTH_LONG).show(); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void setEmojiKeyboardVisible(boolean visible) { |
|||
emojiKeyboard.setVisibility(visible ? View.VISIBLE : View.GONE); |
|||
} |
|||
|
|||
@Override |
|||
public boolean isEmojiKeyboardVisible() { |
|||
return emojiKeyboard.getVisibility() == View.VISIBLE; |
|||
} |
|||
|
|||
@Override |
|||
public void setEmojiKeyboardInputConnection(InputConnection ic) { |
|||
emojiKeyboard.setInputConnection(ic); |
|||
} |
|||
} |
@ -0,0 +1,61 @@ |
|||
package gr.thmmy.mthmmy.activities.shoutbox; |
|||
|
|||
import org.jsoup.nodes.Document; |
|||
import org.jsoup.nodes.Element; |
|||
|
|||
import java.util.ArrayList; |
|||
|
|||
import gr.thmmy.mthmmy.model.Shout; |
|||
import gr.thmmy.mthmmy.model.Shoutbox; |
|||
import gr.thmmy.mthmmy.utils.NetworkResultCodes; |
|||
import gr.thmmy.mthmmy.utils.parsing.NewParseTask; |
|||
import gr.thmmy.mthmmy.utils.parsing.ParseException; |
|||
import gr.thmmy.mthmmy.utils.parsing.ParseHelpers; |
|||
import okhttp3.Response; |
|||
|
|||
public class ShoutboxTask extends NewParseTask<Shoutbox> { |
|||
|
|||
public ShoutboxTask(OnTaskStartedListener onTaskStartedListener, OnNetworkTaskFinishedListener<Shoutbox> onParseTaskFinishedListener) { |
|||
super(onTaskStartedListener, onParseTaskFinishedListener); |
|||
} |
|||
|
|||
@Override |
|||
protected Shoutbox parse(Document document, Response response) throws ParseException { |
|||
// fragment_shoutbox_shout_row container: document.select("div[class=smalltext]" && div.text().contains("Τελευταίες 75 φωνές:") η στα αγγλικα
|
|||
Element shoutboxContainer = document.select("table.windowbg").first(); |
|||
ArrayList<Shout> shouts = new ArrayList<>(); |
|||
for (Element shout : shoutboxContainer.select("div[style=margin: 4px;]")) { |
|||
Element user = shout.child(0); |
|||
Element link = user.select("a").first(); |
|||
String profileUrl = link.attr("href"); |
|||
String profileName = link.text(); |
|||
boolean memberOfTheMonth = link.attr("style").contains("#EA00FF"); |
|||
|
|||
Element date = shout.child(1); |
|||
String dateString = date.text(); |
|||
|
|||
Element content = shout.child(2); |
|||
content.removeAttr("style"); |
|||
String shoutContent = "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />" + |
|||
ParseHelpers.youtubeEmbeddedFix(content); |
|||
shouts.add(new Shout(profileName, profileUrl, dateString, shoutContent, memberOfTheMonth)); |
|||
} |
|||
|
|||
Element shoutboxForm = document.select("form[name=tp-shoutbox]").first(); |
|||
String formUrl = shoutboxForm.attr("action"); |
|||
String sc = shoutboxForm.select("input[name=sc]").first().attr("value"); |
|||
String shoutName = shoutboxForm.select("input[name=tp-shout-name]").first().attr("value"); |
|||
// TODO: make shout send nullable and disable shouting
|
|||
Element shoutSendInput = shoutboxForm.select("input[name=shout_send]").first(); |
|||
String shoutSend = null; |
|||
if (shoutSendInput != null) |
|||
shoutSend = shoutSendInput.attr("value"); |
|||
String shoutUrl = shoutboxForm.select("input[name=tp-shout-url]").first().attr("value"); |
|||
return new Shoutbox(shouts.toArray(new Shout[0]), sc, formUrl, shoutName, shoutSend, shoutUrl); |
|||
} |
|||
|
|||
@Override |
|||
protected int getResultCode(Response response, Shoutbox data) { |
|||
return NetworkResultCodes.SUCCESSFUL; |
|||
} |
|||
} |
@ -0,0 +1,34 @@ |
|||
package gr.thmmy.mthmmy.model; |
|||
|
|||
public class Shout { |
|||
private final String shouter, shouterProfileURL, date, shout; |
|||
private final boolean memberOfTheMonth; |
|||
|
|||
public Shout(String shouter, String shouterProfileURL, String date, String shout, boolean memberOfTheMonth) { |
|||
this.shouter = shouter; |
|||
this.shouterProfileURL = shouterProfileURL; |
|||
this.date = date; |
|||
this.shout = shout; |
|||
this.memberOfTheMonth = memberOfTheMonth; |
|||
} |
|||
|
|||
public String getShouter() { |
|||
return shouter; |
|||
} |
|||
|
|||
public String getShouterProfileURL() { |
|||
return shouterProfileURL; |
|||
} |
|||
|
|||
public String getDate() { |
|||
return date; |
|||
} |
|||
|
|||
public String getShout() { |
|||
return shout; |
|||
} |
|||
|
|||
public boolean isMemberOfTheMonth() { |
|||
return memberOfTheMonth; |
|||
} |
|||
} |
@ -0,0 +1,42 @@ |
|||
package gr.thmmy.mthmmy.model; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
import timber.log.Timber; |
|||
|
|||
public class Shoutbox { |
|||
private Shout[] shouts; |
|||
private String sc, sendShoutUrl, shoutName, shoutSend, shoutUrl; |
|||
|
|||
public Shoutbox(Shout[] shouts, String sc, String sendShoutUrl, String shoutName, String shoutSend, String shoutUrl) { |
|||
this.shouts = shouts; |
|||
this.sc = sc; |
|||
this.sendShoutUrl = sendShoutUrl; |
|||
this.shoutName = shoutName; |
|||
this.shoutSend = shoutSend; |
|||
this.shoutUrl = shoutUrl; |
|||
} |
|||
|
|||
public Shout[] getShouts() { |
|||
return shouts; |
|||
} |
|||
|
|||
public String getSc() { |
|||
return sc; |
|||
} |
|||
|
|||
public String getSendShoutUrl() { |
|||
return sendShoutUrl; |
|||
} |
|||
|
|||
public String getShoutName() { |
|||
return shoutName; |
|||
} |
|||
|
|||
public String getShoutSend() { |
|||
return shoutSend; |
|||
} |
|||
|
|||
public String getShoutUrl() { |
|||
return shoutUrl; |
|||
} |
|||
} |
@ -0,0 +1,58 @@ |
|||
package gr.thmmy.mthmmy.viewmodel; |
|||
|
|||
import android.os.AsyncTask; |
|||
|
|||
import androidx.lifecycle.MutableLiveData; |
|||
import androidx.lifecycle.ViewModel; |
|||
import gr.thmmy.mthmmy.activities.shoutbox.SendShoutTask; |
|||
import gr.thmmy.mthmmy.activities.shoutbox.ShoutboxTask; |
|||
import gr.thmmy.mthmmy.model.Shoutbox; |
|||
import gr.thmmy.mthmmy.session.SessionManager; |
|||
|
|||
public class ShoutboxViewModel extends ViewModel { |
|||
private MutableLiveData<Shoutbox> shoutboxMutableLiveData = new MutableLiveData<>(); |
|||
private ShoutboxTask shoutboxTask; |
|||
private ShoutboxTask.OnTaskStartedListener onShoutboxTaskStarted; |
|||
private ShoutboxTask.OnNetworkTaskFinishedListener<Shoutbox> onShoutboxTaskFinished; |
|||
private SendShoutTask.OnTaskStartedListener onSendShoutTaskStarted; |
|||
private SendShoutTask.OnNetworkTaskFinishedListener<Void> onSendShoutTaskFinished; |
|||
|
|||
public void loadShoutbox() { |
|||
if (shoutboxTask != null && shoutboxTask.getStatus() == AsyncTask.Status.RUNNING) |
|||
shoutboxTask.cancel(true); |
|||
shoutboxTask = new ShoutboxTask(onShoutboxTaskStarted, onShoutboxTaskFinished); |
|||
shoutboxTask.execute(SessionManager.shoutboxUrl.toString()); |
|||
} |
|||
|
|||
public void sendShout(String shout) { |
|||
if (shoutboxMutableLiveData.getValue() == null) throw new IllegalStateException("Shoutbox task has not finished yet!"); |
|||
Shoutbox shoutbox = shoutboxMutableLiveData.getValue(); |
|||
new SendShoutTask(onSendShoutTaskStarted, onSendShoutTaskFinished) |
|||
.execute(shoutbox.getSendShoutUrl(), shout, shoutbox.getSc(), |
|||
shoutbox.getShoutName(), shoutbox.getShoutSend(), shoutbox.getShoutUrl()); |
|||
} |
|||
|
|||
public void setShoutbox(Shoutbox shoutbox) { |
|||
shoutboxMutableLiveData.setValue(shoutbox); |
|||
} |
|||
|
|||
public MutableLiveData<Shoutbox> getShoutboxMutableLiveData() { |
|||
return shoutboxMutableLiveData; |
|||
} |
|||
|
|||
public void setOnSendShoutTaskFinished(SendShoutTask.OnNetworkTaskFinishedListener<Void> onSendShoutTaskFinished) { |
|||
this.onSendShoutTaskFinished = onSendShoutTaskFinished; |
|||
} |
|||
|
|||
public void setOnSendShoutTaskStarted(SendShoutTask.OnTaskStartedListener onSendShoutTaskStarted) { |
|||
this.onSendShoutTaskStarted = onSendShoutTaskStarted; |
|||
} |
|||
|
|||
public void setOnShoutboxTaskFinished(ShoutboxTask.OnNetworkTaskFinishedListener<Shoutbox> onShoutboxTaskFinished) { |
|||
this.onShoutboxTaskFinished = onShoutboxTaskFinished; |
|||
} |
|||
|
|||
public void setOnShoutboxTaskStarted(ShoutboxTask.OnTaskStartedListener onShoutboxTaskStarted) { |
|||
this.onShoutboxTaskStarted = onShoutboxTaskStarted; |
|||
} |
|||
} |
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<selector xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
|
|||
<item android:color="@color/accent" android:state_selected="true" /> |
|||
<item android:color="@color/white" android:state_selected="false" /> |
|||
</selector> |
@ -0,0 +1,5 @@ |
|||
<vector android:height="24dp" android:tint="#FFFFFF" |
|||
android:viewportHeight="24.0" android:viewportWidth="24.0" |
|||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
<path android:fillColor="#FF000000" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/> |
|||
</vector> |
@ -0,0 +1,7 @@ |
|||
<vector android:height="24dp" android:viewportHeight="297" |
|||
android:viewportWidth="297" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android" |
|||
android:tint="#FFFFFF"> |
|||
<path android:fillColor="#FF000000" |
|||
android:pathData="M282.82,107.559h-25.792V10.025c0,-4.056 -2.443,-7.711 -6.19,-9.261c-3.745,-1.555 -8.059,-0.693 -10.925,2.177C195.46,47.434 157.039,68.643 132.635,78.6C106.33,89.333 90.261,89.635 90.159,89.637H14.18c-5.536,0 -10.023,4.488 -10.023,10.024v89.631c0,5.536 4.487,10.023 10.023,10.023h10.2l37.887,91.497c1.551,3.746 5.206,6.189 9.261,6.189h55.538c0.006,-0.001 0.012,-0.001 0.02,0c5.536,0 10.023,-4.488 10.023,-10.023c0,-1.588 -0.37,-3.09 -1.025,-4.424l-33.809,-81.646c22.4,4.443 73.884,21.285 137.641,85.1c1.917,1.921 4.483,2.939 7.094,2.939c0.055,0 0.109,0 0.164,0c5.468,-0.079 9.877,-4.536 9.877,-10.023c0,-0.214 -0.006,-0.428 -0.02,-0.639l-0.002,-96.896h25.792c5.536,0 10.023,-4.488 10.023,-10.024v-53.779C292.844,112.048 288.356,107.559 282.82,107.559zM24.204,109.683h55.932v69.584H24.204V109.683zM78.226,276.952l-31.139,-75.196h33.839l31.138,75.196H78.226zM100.183,180.201v-71.452c20.889,-3.123 72.28,-16.674 136.797,-75.301v84.121v0.015v53.779c0,0.008 0,0.017 0,0.025l0.002,84.111C172.466,196.876 121.072,183.326 100.183,180.201zM272.796,161.34h-15.768v-33.732h15.768V161.34z" |
|||
android:strokeColor="#ffffff" android:strokeWidth="1"/> |
|||
</vector> |
@ -0,0 +1,5 @@ |
|||
<vector android:height="24dp" android:tint="#FFFFFF" |
|||
android:viewportHeight="24.0" android:viewportWidth="24.0" |
|||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
<path android:fillColor="#FF000000" android:pathData="M20,4L4,4c-1.11,0 -1.99,0.89 -1.99,2L2,18c0,1.11 0.89,2 2,2h16c1.11,0 2,-0.89 2,-2L22,6c0,-1.11 -0.89,-2 -2,-2zM8.5,15L7.3,15l-2.55,-3.5L4.75,15L3.5,15L3.5,9h1.25l2.5,3.5L7.25,9L8.5,9v6zM13.5,10.26L11,10.26v1.12h2.5v1.26L11,12.64v1.11h2.5L13.5,15h-4L9.5,9h4v1.26zM20.5,14c0,0.55 -0.45,1 -1,1h-4c-0.55,0 -1,-0.45 -1,-1L14.5,9h1.25v4.51h1.13L16.88,9.99h1.25v3.51h1.12L19.25,9h1.25v5z"/> |
|||
</vector> |
@ -0,0 +1,5 @@ |
|||
<vector android:height="24dp" android:tint="#FFFFFF" |
|||
android:viewportHeight="24.0" android:viewportWidth="24.0" |
|||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
<path android:fillColor="#FF000000" android:pathData="M21,6h-2v9L6,15v2c0,0.55 0.45,1 1,1h11l4,4L22,7c0,-0.55 -0.45,-1 -1,-1zM17,12L17,3c0,-0.55 -0.45,-1 -1,-1L3,2c-0.55,0 -1,0.45 -1,1v14l4,-4h10c0.55,0 1,-0.45 1,-1z"/> |
|||
</vector> |
@ -0,0 +1,5 @@ |
|||
<vector android:height="24dp" android:tint="#FFFFFF" |
|||
android:viewportHeight="24.0" android:viewportWidth="24.0" |
|||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> |
|||
<path android:fillColor="#FF000000" android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/> |
|||
</vector> |
@ -0,0 +1,31 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:tools="http://schemas.android.com/tools" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
xmlns:app="http://schemas.android.com/apk/res-auto" |
|||
android:orientation="vertical"> |
|||
|
|||
<com.google.android.material.appbar.AppBarLayout |
|||
android:id="@+id/appbar" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:theme="@style/ToolbarTheme"> |
|||
|
|||
<androidx.appcompat.widget.Toolbar |
|||
android:id="@+id/toolbar" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:background="?attr/colorPrimary" |
|||
android:gravity="center" |
|||
app:popupTheme="@style/ToolbarTheme" /> |
|||
</com.google.android.material.appbar.AppBarLayout> |
|||
|
|||
<FrameLayout |
|||
android:id="@+id/container" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
tools:context=".ShoutboxActivity" /> |
|||
|
|||
</LinearLayout> |
|||
|
@ -1,5 +1,5 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<android.support.v7.widget.AppCompatImageButton |
|||
<androidx.appcompat.widget.AppCompatImageButton |
|||
xmlns:android="http://schemas.android.com/apk/res/android" |
|||
android:layout_height="wrap_content" |
|||
android:layout_width="match_parent" |
|||
|
@ -0,0 +1,40 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<LinearLayout 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_width="match_parent" |
|||
android:layout_height="match_parent" |
|||
android:orientation="vertical"> |
|||
|
|||
<me.zhanghai.android.materialprogressbar.MaterialProgressBar |
|||
android:id="@+id/progressBar" |
|||
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="@dimen/progress_bar_height" |
|||
android:indeterminate="true" |
|||
android:visibility="invisible" |
|||
app:mpb_indeterminateTint="@color/accent" |
|||
app:mpb_progressStyle="horizontal" /> |
|||
|
|||
<gr.thmmy.mthmmy.utils.CustomRecyclerView |
|||
android:id="@+id/shoutbox_recyclerview" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="0dp" |
|||
android:layout_weight="1" |
|||
tools:listitem="@layout/fragment_shoutbox_shout_row" /> |
|||
|
|||
<gr.thmmy.mthmmy.editorview.EditorView |
|||
android:id="@+id/edior_view" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginStart="8dp" |
|||
android:layout_marginEnd="8dp" |
|||
android:paddingTop="8dp" |
|||
android:visibility="gone"/> |
|||
|
|||
<gr.thmmy.mthmmy.editorview.EmojiKeyboard |
|||
android:id="@+id/emoji_keyboard" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="180dp" |
|||
android:visibility="gone" /> |
|||
</LinearLayout> |
@ -0,0 +1,72 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:card_view="http://schemas.android.com/apk/res-auto" |
|||
xmlns:tools="http://schemas.android.com/tools" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginStart="8dp" |
|||
android:layout_marginEnd="8dp" |
|||
android:foreground="?android:attr/selectableItemBackground" |
|||
android:orientation="vertical" |
|||
card_view:cardBackgroundColor="@color/card_background" |
|||
card_view:cardCornerRadius="5dp" |
|||
card_view:cardElevation="2dp" |
|||
card_view:cardPreventCornerOverlap="false" |
|||
card_view:cardUseCompatPadding="true"> |
|||
|
|||
<LinearLayout |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:orientation="vertical"> |
|||
|
|||
<TextView |
|||
android:id="@+id/author_textview" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginStart="16dp" |
|||
android:ellipsize="end" |
|||
android:maxLines="1" |
|||
android:paddingTop="9dp" |
|||
android:textColor="@color/accent" |
|||
android:textStyle="bold" |
|||
tools:text="author" /> |
|||
|
|||
<TextView |
|||
android:id="@+id/date_time_textview" |
|||
android:layout_width="wrap_content" |
|||
android:layout_height="wrap_content" |
|||
android:layout_marginStart="16dp" |
|||
android:textColor="@color/primary_text" |
|||
android:textSize="11sp" |
|||
tools:text="date & time" /> |
|||
|
|||
<View |
|||
android:id="@+id/header_body_divider" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="1dp" |
|||
android:layout_marginLeft="16dp" |
|||
android:layout_marginTop="5dp" |
|||
android:layout_marginRight="16dp" |
|||
android:layout_marginBottom="9dp" |
|||
android:background="@color/divider" /> |
|||
|
|||
<WebView |
|||
android:id="@+id/shout_content" |
|||
android:layout_width="match_parent" |
|||
android:layout_height="wrap_content" |
|||
android:layout_gravity="center" |
|||
android:layout_marginLeft="16dp" |
|||
android:layout_marginRight="16dp" |
|||
android:background="@color/card_background" |
|||
android:clickable="true" |
|||
android:focusable="true" |
|||
android:scrollbars="none" |
|||
android:text="@string/post" |
|||
tools:ignore="WebViewLayout" /> |
|||
|
|||
<View |
|||
android:layout_width="match_parent" |
|||
android:layout_height="9dp" /> |
|||
</LinearLayout> |
|||
|
|||
</androidx.cardview.widget.CardView> |
@ -0,0 +1,10 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<menu xmlns:android="http://schemas.android.com/apk/res/android" |
|||
xmlns:app="http://schemas.android.com/apk/res-auto"> |
|||
<item |
|||
android:id="@+id/menu_refresh" |
|||
android:icon="@drawable/ic_refresh_white_24dp" |
|||
app:showAsAction="ifRoom" |
|||
android:title="@string/refresh"> |
|||
</item> |
|||
</menu> |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue