package com.mistareader;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.app.Fragment;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.mistareader.TextProcessors.JSONProcessor;
import com.mistareader.TextProcessors.S;
import com.mistareader.WebIteraction.RequestResult;
import java.util.ArrayList;
public class Messages_Fragment extends Fragment implements Forum.iOnPOSTRequestExecuted {
OnContextMenuListener mOnContextMenuCallback;
public interface OnContextMenuListener {
public void onContextMenySelected(Message selectedMessage, long currentTopicId);
}
ListView lvMain;
View rootView;
public Messages_Adapter messages_sAdapter;
private View message_Header;
public Topic currentTopic;
private long currentTopicId;
private String mAccount;
private final int prefetchMessagesFactor = 10;
Forum forum;
public boolean modeMovePositionToLastMessage;
public boolean modeMovePositionToFirstMessage;
public int movePositionToMessage;
private String URL;
private boolean messages_isLoading = false;
ImageView imgFastScrollDown;
ImageView imgFastScrollUp;
boolean up = false;
boolean allowArrowChange = true;
boolean allowArrowShow;
boolean focusLast;
int focusOn;
boolean topicMarkedAsReaded = false;
int answ;
public long getCurrentTopicId() {
return currentTopicId;
}
@Override
public void onAttach(Activity activity) {
try {
mOnContextMenuCallback = (OnContextMenuListener) activity;
}
catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnContextMenuListener");
}
super.onAttach(activity);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (container == null) {
return null;
}
rootView = inflater.inflate(R.layout.fragment_main, container, false);
imgFastScrollDown = (ImageView) rootView.findViewById(R.id.imgFastScrollDown);
imgFastScrollDown.setVisibility(View.INVISIBLE);
imgFastScrollUp = (ImageView) rootView.findViewById(R.id.imgFastScrollUp);
imgFastScrollUp.setVisibility(View.INVISIBLE);
imgFastScrollDown.setOnClickListener(onArrowClick);
imgFastScrollUp.setOnClickListener(onArrowClick);
// в ответе сервера "темы с моим участием" нет этого флага.
// if (currentTopic.is_voting == 1) {
getTopicInfo();
// }
if (focusLast) {
modeMovePositionToLastMessage = true;
focusLastMessage(true);
}
else {
if (focusOn > 0)
movePositionToMessage = focusOn;
if (currentTopic.messages == null) {
loadMessagesFrom(focusOn - prefetchMessagesFactor);
}
else {
drawMessages();
}
}
return rootView;
}
private void getTopicInfo() {
URL = API.getTopicInfo(currentTopicId);
new RequestAsyncTopicInfo(null, forum.sessionCookies).execute(URL);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
int itemId = item.getItemId();
if (itemId == R.id.menu_ReplyToThis) {
mOnContextMenuCallback.onContextMenySelected(messages_sAdapter.getItem(info.position - 1), currentTopicId);
return true;
}
else {
return super.onContextItemSelected(item);
}
}
View.OnClickListener onArrowClick = new View.OnClickListener() {
@Override
public void onClick(View v) {
if (up) {
imgFastScrollUp.setVisibility(View.INVISIBLE);
focusFirstMessage();
}
else {
imgFastScrollDown.setVisibility(View.INVISIBLE);
focusLastMessage(false);
}
}
};
private final Handler fadeOutHandler = new Handler();
private final Handler allowArrowChangeHandler = new Handler();
private final Runnable allowArrowChangeTimer = new Runnable() {
public void run() {
allowArrowChange = true;
}
};
private final Runnable fadeOutAnimation = new Runnable() {
@Override
public void run() {
if (!up) {
imgFastScrollDown.animate().alpha(0f).setDuration(700)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
imgFastScrollDown.setVisibility(View.INVISIBLE);
}
});
}
else
{
imgFastScrollUp.animate().alpha(0f).setDuration(700).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
imgFastScrollUp.setVisibility(View.INVISIBLE);
}
});
}
}
};
private void onUp(int firstVisibleItem, int visibleItemCount) {
onScrollUpLoadMessages(firstVisibleItem, visibleItemCount);
if (!allowArrowChange || !allowArrowShow)
return;
allowArrowChange = false;
allowArrowChangeHandler.postDelayed(allowArrowChangeTimer, 500);
imgFastScrollDown.setVisibility(View.INVISIBLE);
imgFastScrollUp.animate().cancel();
imgFastScrollUp.setAlpha(1f);
imgFastScrollUp.setVisibility(View.VISIBLE);
fadeOutHandler.postDelayed(fadeOutAnimation, 1000);
up = true;
}
private void onScrollUpLoadMessages(int firstVisibleItem, int visibleItemCount) {
if (messages_isLoading) {
return;
}
messages_isLoading = true;
int prevMessageN = firstVisibleItem - prefetchMessagesFactor;
if (prevMessageN < 0) {
messages_isLoading = false;
return;
}
Message curMessage = currentTopic.messages.get(prevMessageN);
if (curMessage.isLoaded) {
messages_isLoading = false;
return;
}
loadMessagesBefore(prevMessageN);
}
private void onScrollDownLoadMessages(int firstVisibleItem, int visibleItemCount) {
if (messages_isLoading) {
return;
}
messages_isLoading = true;
int nextMessageN = firstVisibleItem + visibleItemCount + prefetchMessagesFactor;
if (nextMessageN > answ) {
messages_isLoading = false;
return;
}
Message curMessage = currentTopic.messages.get(nextMessageN);
if (curMessage.isLoaded) {
messages_isLoading = false;
return;
}
loadMessagesFrom(nextMessageN);
}
private void loadMessagesFrom(int nextMessageN) {
int messages_from;
int messages_to;
messages_from = nextMessageN;
messages_to = nextMessageN + 20;
int mathMin = 0;
if (answ > 20 && ((answ - messages_from) < 20)) {
mathMin = answ - 20;
}
messages_from = Math.max(mathMin, 0);
URL = API.getMessages(currentTopicId, messages_from, messages_to);
new RequestAsyncMessages(messages_from, messages_to, forum.sessionCookies).execute(URL);
}
private void loadMessagesBefore(int firstMessageN) {
int messages_from;
int messages_to;
messages_from = firstMessageN - 20;
messages_to = firstMessageN;
URL = API.getMessages(currentTopicId, messages_from, messages_to);
new RequestAsyncMessages(messages_from, messages_to, forum.sessionCookies).execute(URL);
}
private void onDown(int firstVisibleItem, int visibleItemCount) {
onScrollDownLoadMessages(firstVisibleItem, visibleItemCount);
if (!allowArrowChange || !allowArrowShow)
return;
allowArrowChange = false;
allowArrowChangeHandler.postDelayed(allowArrowChangeTimer, 500);
imgFastScrollUp.setVisibility(View.INVISIBLE);
imgFastScrollDown.animate().cancel();
imgFastScrollDown.setAlpha(1f);
imgFastScrollDown.setVisibility(View.VISIBLE);
fadeOutHandler.postDelayed(fadeOutAnimation, 1000);
up = false;
}
private class messagesScrollListener implements OnScrollListener {
int lastFirstVisibleItem;
int lastTop;
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemsInList) {
View v = view.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
if (firstVisibleItem == lastFirstVisibleItem) {
if (top > lastTop) {
onUp(firstVisibleItem, visibleItemCount);
}
else if (top < lastTop) {
onDown(firstVisibleItem, visibleItemCount);
}
}
else {
if (firstVisibleItem > lastFirstVisibleItem) {
onDown(firstVisibleItem, visibleItemCount);
}
else {
onUp(firstVisibleItem, visibleItemCount);
}
}
lastFirstVisibleItem = firstVisibleItem;
lastTop = top;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
switch (scrollState) {
case 1:
case 2:
allowArrowShow = true;
break;
default:
allowArrowShow = false;
break;
}
}
}
private void drawHeader() {
if (message_Header == null) {
return;
}
((TextView) message_Header.findViewById(R.id.mess_headerText)).setText(Html.fromHtml(currentTopic.text));
if (currentTopic.votes != null) {
RelativeLayout RL = (RelativeLayout) message_Header.findViewById(R.id.RL1);
RL.setVisibility(View.VISIBLE);
TextView twVote1 = (TextView) message_Header.findViewById(R.id.mess_headerVote1);
TextView twVote2 = (TextView) message_Header.findViewById(R.id.mess_headerVote2);
TextView twVote3 = (TextView) message_Header.findViewById(R.id.mess_headerVote3);
TextView twVote4 = (TextView) message_Header.findViewById(R.id.mess_headerVote4);
TextView twVote5 = (TextView) message_Header.findViewById(R.id.mess_headerVote5);
Topic.Votes vote = currentTopic.votes.get(0);
if (!vote.voteName.isEmpty()) {
twVote1.setText("1. " + vote.voteName + ": " + vote.voteCount);
twVote1.setVisibility(View.VISIBLE);
}
vote = currentTopic.votes.get(1);
if (!vote.voteName.isEmpty()) {
twVote2.setText("2. " + vote.voteName + ": " + vote.voteCount);
twVote2.setVisibility(View.VISIBLE);
}
vote = currentTopic.votes.get(2);
if (!vote.voteName.isEmpty()) {
twVote3.setText("3. " + vote.voteName + ": " + vote.voteCount);
twVote3.setVisibility(View.VISIBLE);
}
vote = currentTopic.votes.get(3);
if (!vote.voteName.isEmpty()) {
twVote4.setText("4. " + vote.voteName + ": " + vote.voteCount);
twVote4.setVisibility(View.VISIBLE);
}
vote = currentTopic.votes.get(4);
if (!vote.voteName.isEmpty()) {
twVote5.setText("5. " + vote.voteName + ": " + vote.voteCount);
twVote5.setVisibility(View.VISIBLE);
}
}
}
private void drawMessages() {
if (messages_sAdapter == null) {
try {
lvMain = (ListView) rootView.findViewById(R.id.lvMain);
lvMain.setDivider(null);
Activity activity = getActivity();
if (activity == null) {
return;
}
messages_sAdapter = new Messages_Adapter(activity, currentTopic, mAccount, R.layout.message_row);
message_Header = activity.getLayoutInflater().inflate(R.layout.message_header, null);
drawHeader();
lvMain.addHeaderView(message_Header);
lvMain.setAdapter(messages_sAdapter);
lvMain.setOnScrollListener(new messagesScrollListener());
registerForContextMenu(lvMain);
}
catch (Exception e) {
S.L("drawMessages: " + Log.getStackTraceString(e));
}
}
else {
messages_sAdapter.notifyDataSetChanged();
}
if (modeMovePositionToFirstMessage) {
lvMain.setSelection(0);
imgFastScrollUp.setVisibility(View.INVISIBLE);
modeMovePositionToFirstMessage = false;
}
if (modeMovePositionToLastMessage) {
lvMain.setSelection(currentTopic.messages.size());
imgFastScrollDown.setVisibility(View.INVISIBLE);
modeMovePositionToLastMessage = false;
}
if (movePositionToMessage > 0) {
lvMain.setSelection(movePositionToMessage);
movePositionToMessage = 0;
}
}
public class RequestAsyncMessages extends AsyncTask<String, Integer, RequestResult> {
private int mMessages_from;
private int mMessages_to;
private String mSessionCookies;
public RequestAsyncMessages(int messages_from, int messages_to, String sessionCookies) {
mMessages_from = Math.max(messages_from, 0);
mMessages_to = Math.min(messages_to, answ);
mSessionCookies = sessionCookies;
}
@Override
protected void onPreExecute() {
messages_isLoading = true;
}
protected RequestResult doInBackground(String... urls) {
return WebIteraction.doServerRequest(urls[0], mSessionCookies);
}
protected void onPostExecute(RequestResult result) {
if (!result.cookie.isEmpty()) {
forum.sessionCookies = result.cookie;
}
currentTopic.addNewMessages(result.result, mMessages_from, mMessages_to);
drawMessages();
messages_isLoading = false;
}
}
@Override
public void onDestroy() {
if (forum.mainDB != null && lvMain != null) {
forum.mainDB.addLastPositionToMessage(currentTopicId, lvMain.getLastVisiblePosition());
}
super.onDestroy();
}
@Override
public void onCreate(Bundle savedInstanceState) {
modeMovePositionToLastMessage = false;
modeMovePositionToFirstMessage = false;
forum = Forum.getInstance();
Bundle args = getArguments();
if (args != null) {
currentTopicId = args.getLong("topicId");
currentTopic = forum.getTopicByid(currentTopicId);
answ = currentTopic.answ;
mAccount = forum.accountName;
focusLast = args.getBoolean("focusLast", false);
focusOn = args.getInt("focusOn", 0);
}
super.onCreate(savedInstanceState);
}
public class RequestAsyncTopicInfo extends AsyncTask<String, Integer, RequestResult> {
iOnLoadTopicInfoFinished mCallBack;
String mSessionCookies;
public RequestAsyncTopicInfo(iOnLoadTopicInfoFinished callBackOnLoadTopicInfoFinished, String sessionCookies) {
mCallBack = callBackOnLoadTopicInfoFinished;
mSessionCookies = sessionCookies;
}
protected RequestResult doInBackground(String... urls) {
return WebIteraction.doServerRequest(urls[0] , mSessionCookies);
}
protected void onPostExecute(RequestResult result) {
if (!result.cookie.isEmpty()) {
forum.sessionCookies = result.cookie;
}
updateTopicInfo(JSONProcessor.ParseTopicInfo(result.result));
if (mCallBack != null) {
mCallBack.onLoadTopicInfoFinished();
}
}
}
private void updateTopicInfo(Topic refreshedTopic) {
if (refreshedTopic.id == currentTopicId) {
currentTopic.answ = refreshedTopic.answ;
currentTopic.closed = refreshedTopic.closed;
currentTopic.deleted = refreshedTopic.deleted;
currentTopic.down = refreshedTopic.down;
currentTopic.text = refreshedTopic.text;
currentTopic.is_voting = refreshedTopic.is_voting;
if (refreshedTopic.votes != null) {
if (currentTopic.votes == null) currentTopic.votes = new ArrayList<Topic.Votes>(5);
else currentTopic.votes.clear();
currentTopic.votes.addAll(refreshedTopic.votes);
}
if (answ != refreshedTopic.answ) {
if (refreshedTopic.answ > answ && currentTopic.messages != null) {
for (int i = 0; i < (refreshedTopic.answ - answ); i++) {
Message newMessage = new Message();
currentTopic.messages.add(newMessage);
}
}
currentTopic.answ = refreshedTopic.answ;
answ = refreshedTopic.answ;
}
}
}
public interface iOnLoadTopicInfoFinished {
void onLoadTopicInfoFinished();
}
public void reLoad(final boolean newMessageMode) {
if (newMessageMode) {
movePositionToMessage = currentTopic.answ + 1;
}
URL = API.getTopicInfo(currentTopicId);
iOnLoadTopicInfoFinished callBackOnLoadTopicInfoFinished = new iOnLoadTopicInfoFinished() {
@Override
public void onLoadTopicInfoFinished() {
if (currentTopic.is_voting == 1) {
drawHeader();
}
if (newMessageMode) {
if (forum.mainDB.isTopicInSubscriptions(currentTopicId)) forum.mainDB.markTopicAsReaded(currentTopicId, currentTopic.answ);
loadMessagesFrom(currentTopic.answ - 10);
} else {
int pos = lvMain.getLastVisiblePosition();
if (pos >= lvMain.getCount() - 1) {
movePositionToMessage = pos + 1;
loadMessagesFrom(pos);
} else {
focusFirstMessage();
}
}
}
};
new RequestAsyncTopicInfo(callBackOnLoadTopicInfoFinished, forum.sessionCookies).execute(URL);
}
public void focusFirstMessage() {
if (currentTopic.messages.get(0).isLoaded) {
lvMain.setSelection(0);
return;
}
modeMovePositionToFirstMessage = true;
loadMessagesFrom(0);
}
public void focusLastMessage(boolean force) {
if (!force && currentTopic.messages.get(answ).isLoaded) {
lvMain.setSelection(answ);
return;
}
modeMovePositionToLastMessage = true;
loadMessagesFrom(currentTopic.answ - 20);
}
@Override
public void onPOSTRequestExecuted(String result) {
}
}