/*
* Copyright (c) 2013, Psiphon Inc.
* All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ca.psiphon.ploggy;
import java.io.File;
import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
/**
* List adapter which displays rows of messages.
*
* Includes widgets/logic for managing downloads of message attachments.
* When the message belongs to self, message attachments are treated as
* local resources, not downloads.
*
* This component has three modes:
* 1. General message list, which displays nickname and avatar.
* 2. Single friend message list, which just displays message content.
* 3. Self message list, which just displays message content.
*
*/
public class MessageAdapter extends BaseAdapter {
private static final String LOG_TAG = "Message Adapter";
// TODO: support multiple attachments
public enum Mode {ALL_MESSAGES, FRIEND_MESSAGES, SELF_MESSAGES}
private final Context mContext;
private final Mode mMode;
private List<Data.AnnotatedMessage> mAnnotatedMessages;
private final String mFriendId;
private List<Data.Message> mMessages;
public MessageAdapter(Context context, Mode mode) throws Utils.ApplicationError {
this(context, mode, null);
}
public MessageAdapter(Context context, Mode mode, String friendId) throws Utils.ApplicationError {
mContext = context;
mMode = mode;
mFriendId = friendId;
updateMessages();
}
public void updateMessages() throws Utils.ApplicationError {
switch (mMode) {
case ALL_MESSAGES:
mAnnotatedMessages = Data.getInstance().getAllMessages();
break;
case FRIEND_MESSAGES:
mMessages = Data.getInstance().getFriendStatus(mFriendId).mMessages;
break;
case SELF_MESSAGES:
mMessages = Data.getInstance().getSelfStatus().mMessages;
break;
}
notifyDataSetChanged();
}
@Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.message_list_row, null);
}
Identity.PublicIdentity publicIdentity = null;
String friendId = null;
Data.Message message = null;
Data.Download download = null;
double downloadProgress = 0.0;
Data.LocalResource localResource = null;
switch (mMode) {
case ALL_MESSAGES:
Data.AnnotatedMessage annotatedMessage = mAnnotatedMessages.get(position);
if (annotatedMessage == null) {
return view;
}
publicIdentity = annotatedMessage.mPublicIdentity;
friendId = annotatedMessage.mFriendId;
message = annotatedMessage.mMessage;
break;
case FRIEND_MESSAGES:
case SELF_MESSAGES:
message = mMessages.get(position);
if (message == null) {
return view;
}
friendId = mFriendId;
break;
}
if (message.mAttachments != null && message.mAttachments.size() > 0) {
try {
if (friendId != null) {
download = Data.getInstance().getDownload(friendId, message.mAttachments.get(0).mId);
if (download.mState == Data.Download.State.IN_PROGRESS) {
long downloadedSize = Downloads.getDownloadedSize(download);
if (download.mSize > 0) {
downloadProgress = 100.0*downloadedSize/download.mSize;
}
}
} else {
localResource = Data.getInstance().getLocalResource(message.mAttachments.get(0).mId);
}
} catch (Data.DataNotFoundError e) {
Log.addEntry(LOG_TAG, "attachment data not found");
} catch (Utils.ApplicationError e) {
Log.addEntry(LOG_TAG, "failed to load attachment data");
}
}
ImageView avatarImage = (ImageView)view.findViewById(R.id.message_avatar_image);
TextView nicknameText = (TextView)view.findViewById(R.id.message_nickname_text);
TextView contentText = (TextView)view.findViewById(R.id.message_content_text);
TextView pictureDownloadText = (TextView)view.findViewById(R.id.message_picture_download_text);
ImageView pictureThumbnailImage = (ImageView)view.findViewById(R.id.message_picture_thumbnail);
TextView timestampText = (TextView)view.findViewById(R.id.message_timestamp_text);
if (publicIdentity != null) {
Robohash.setRobohashImage(mContext, avatarImage, true, publicIdentity);
nicknameText.setText(publicIdentity.mNickname);
} else {
avatarImage.setVisibility(View.GONE);
nicknameText.setVisibility(View.GONE);
}
contentText.setText(message.mContent);
if (download != null) {
switch (download.mState) {
case IN_PROGRESS:
pictureDownloadText.setVisibility(View.VISIBLE);
pictureThumbnailImage.setVisibility(View.GONE);
pictureDownloadText.setText(mContext.getString(R.string.format_download_progress, downloadProgress));
break;
case CANCELLED:
pictureDownloadText.setVisibility(View.VISIBLE);
pictureThumbnailImage.setVisibility(View.GONE);
pictureDownloadText.setText("");
break;
case COMPLETE:
pictureDownloadText.setVisibility(View.GONE);
pictureThumbnailImage.setVisibility(View.VISIBLE);
Pictures.loadThumbnailWithClickToShowPicture(mContext, Downloads.getDownloadFile(download), pictureThumbnailImage);
break;
}
} else if (localResource != null) {
pictureDownloadText.setVisibility(View.GONE);
pictureThumbnailImage.setVisibility(View.VISIBLE);
Pictures.loadThumbnailWithClickToShowPicture(mContext, new File(localResource.mFilePath), pictureThumbnailImage);
} else {
pictureDownloadText.setVisibility(View.GONE);
pictureThumbnailImage.setVisibility(View.GONE);
}
timestampText.setText(Utils.DateFormatter.formatRelativeDatetime(mContext, message.mTimestamp, true));
return view;
}
@Override
public int getCount() {
if (mMode == Mode.ALL_MESSAGES) {
return mAnnotatedMessages.size();
} else {
return mMessages.size();
}
}
@Override
public Object getItem(int position) {
if (mMode == Mode.ALL_MESSAGES) {
return mAnnotatedMessages.get(position);
} else {
return mMessages.get(position);
}
}
@Override
public long getItemId(int position) {
return position;
}
}