Commit 3edaefce authored by Tiago Cunha's avatar Tiago Cunha

Added file upload

parent c8be3dfb
......@@ -4,7 +4,6 @@ import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.SlidingPaneLayout;
......@@ -21,6 +20,7 @@ import java.util.UUID;
import chat.rocket.android.R;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.fragment.chatroom.dialog.FileUploadProgressDialogFragment;
import chat.rocket.android.fragment.chatroom.dialog.MessageSelectionDialogFragment;
import chat.rocket.android.fragment.chatroom.dialog.UsersOfRoomDialogFragment;
import chat.rocket.android.helper.FileUploadHelper;
import chat.rocket.android.helper.LoadMoreScrollListener;
......@@ -31,6 +31,10 @@ import chat.rocket.android.layouthelper.chatroom.MessageComposerManager;
import chat.rocket.android.layouthelper.chatroom.MessageListAdapter;
import chat.rocket.android.layouthelper.chatroom.PairedMessage;
import chat.rocket.android.log.RCLog;
import chat.rocket.android.message.AudioUploadMessageSpec;
import chat.rocket.android.message.FileUploadMessageSpec;
import chat.rocket.android.message.ImageUploadMessageSpec;
import chat.rocket.android.message.VideoUploadMessageSpec;
import chat.rocket.android.model.ServerConfig;
import chat.rocket.android.model.SyncState;
import chat.rocket.android.model.ddp.Message;
......@@ -51,8 +55,6 @@ import chat.rocket.android.widget.message.MessageComposer;
public class RoomFragment extends AbstractChatRoomFragment
implements OnBackPressListener, RealmModelListAdapter.OnItemClickListener<PairedMessage> {
private static final int RC_UPL = 0x12;
private String serverConfigId;
private RealmHelper realmHelper;
private String roomId;
......@@ -64,6 +66,9 @@ public class RoomFragment extends AbstractChatRoomFragment
private RealmObjectObserver<LoadMessageProcedure> procedureObserver;
private MessageComposerManager messageComposerManager;
private MessageSelectionDialogFragment.ClickListener messageSelectionClickListener =
messageSpec -> messageSpec.onSelect(RoomFragment.this);
public RoomFragment() {
}
......@@ -148,7 +153,6 @@ public class RoomFragment extends AbstractChatRoomFragment
setupSideMenu();
setupMessageComposer();
setupFileUploader();
}
@Override
......@@ -225,30 +229,24 @@ public class RoomFragment extends AbstractChatRoomFragment
.put("rid", roomId)
.put("msg", messageText))));
messageComposerManager.setExtrasPickerListener(() -> {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture to Upload"),
RC_UPL);
});
}
MessageSelectionDialogFragment fragment = MessageSelectionDialogFragment.create();
fragment.addMessageSpec(new ImageUploadMessageSpec());
fragment.addMessageSpec(new AudioUploadMessageSpec());
fragment.addMessageSpec(new VideoUploadMessageSpec());
private void setupFileUploader() {
// change this to a more actions chooser
// uses bottom sheet to list options
// starts with only file upload (we already have it)
// rootView.findViewById(R.id.fab_upload_file).setOnClickListener(view -> {
// Intent intent = new Intent();
// intent.setType("image/*");
// intent.setAction(Intent.ACTION_GET_CONTENT);
// startActivityForResult(Intent.createChooser(intent, "Select Picture to Upload"), RC_UPL);
// });
fragment.setListener(messageSelectionClickListener);
fragment.show(getFragmentManager(), MessageSelectionDialogFragment.TAG);
closeSideMenuIfNeeded();
});
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode != RC_UPL || resultCode != Activity.RESULT_OK) {
if (requestCode != FileUploadMessageSpec.RC_UPL || resultCode != Activity.RESULT_OK) {
return;
}
......
......@@ -10,7 +10,7 @@ import android.support.design.widget.BottomSheetDialogFragment;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmStore;
abstract class AbstractChatroomDialogFragment extends BottomSheetDialogFragment {
abstract class AbstractChatRoomDialogFragment extends BottomSheetDialogFragment {
protected RealmHelper realmHelper;
protected String roomId;
......
......@@ -17,7 +17,7 @@ import chat.rocket.android.renderer.FileUploadingRenderer;
/**
* dialog fragment to display progress of file uploading.
*/
public class FileUploadProgressDialogFragment extends AbstractChatroomDialogFragment {
public class FileUploadProgressDialogFragment extends AbstractChatRoomDialogFragment {
private String uplId;
private RealmObjectObserver<FileUploading> fileUploadingObserver;
......
package chat.rocket.android.fragment.chatroom.dialog;
import android.support.v7.widget.RecyclerView;
import chat.rocket.android.R;
import chat.rocket.android.layouthelper.chatroom.dialog.MessageSelectionAdapter;
import chat.rocket.android.message.MessageSpec;
public class MessageSelectionDialogFragment extends AbstractChatRoomDialogFragment {
public static final String TAG = "MessageSelectionDialogFragment";
private MessageSelectionAdapter adapter;
private ClickListener listener;
public static MessageSelectionDialogFragment create() {
return new MessageSelectionDialogFragment();
}
public MessageSelectionDialogFragment() {
adapter = new MessageSelectionAdapter();
adapter.setListener(messageSpec -> {
if (listener != null) {
listener.onClick(messageSpec);
}
dismiss();
});
}
public void addMessageSpec(MessageSpec messageSpec) {
adapter.addMessageSpec(messageSpec);
}
public void setListener(ClickListener listener) {
this.listener = listener;
}
@Override
protected int getLayout() {
return R.layout.dialog_message_selection;
}
@Override
protected void onSetupDialog() {
RecyclerView messageSpecList = (RecyclerView) getDialog().findViewById(R.id.message_spec_list);
messageSpecList.setAdapter(adapter);
}
public interface ClickListener {
void onClick(MessageSpec messageSpec);
}
}
......@@ -25,7 +25,7 @@ import chat.rocket.android.service.RocketChatService;
/**
* Dialog to show members in a room.
*/
public class UsersOfRoomDialogFragment extends AbstractChatroomDialogFragment {
public class UsersOfRoomDialogFragment extends AbstractChatRoomDialogFragment {
private String hostname;
private RealmObjectObserver<GetUsersOfRoomsProcedure> procedureObserver;
......@@ -113,13 +113,13 @@ public class UsersOfRoomDialogFragment extends AbstractChatroomDialogFragment {
return;
}
int syncstate = procedure.getSyncState();
if (previousSyncState != syncstate) {
onSyncStateUpdated(syncstate);
previousSyncState = syncstate;
int syncState = procedure.getSyncState();
if (previousSyncState != syncState) {
onSyncStateUpdated(syncState);
previousSyncState = syncState;
}
if (syncstate == SyncState.SYNCED) {
if (syncState == SyncState.SYNCED) {
onRenderTotalCount(procedure.getTotal());
try {
......@@ -138,8 +138,8 @@ public class UsersOfRoomDialogFragment extends AbstractChatroomDialogFragment {
/**
* called only if prevSyncstate != newSyncstate.
*/
private void onSyncStateUpdated(int newSyncstate) {
boolean show = newSyncstate == SyncState.NOT_SYNCED || newSyncstate == SyncState.SYNCING;
private void onSyncStateUpdated(int newSyncState) {
boolean show = newSyncState == SyncState.NOT_SYNCED || newSyncState == SyncState.SYNCING;
getDialog().findViewById(R.id.waiting).setVisibility(show ? View.VISIBLE : View.GONE);
}
......
......@@ -9,7 +9,7 @@ import chat.rocket.android.widget.message.RocketChatMessageLayout;
import chat.rocket.android.widget.message.RocketChatMessageUrlsLayout;
/**
* View holder of NORMAL chat message.
* ViewData holder of NORMAL chat message.
*/
public class MessageNormalViewHolder extends AbstractMessageViewHolder {
private final RocketChatMessageLayout body;
......
......@@ -7,7 +7,7 @@ import chat.rocket.android.R;
import chat.rocket.android.renderer.MessageRenderer;
/**
* View holder of NORMAL chat message.
* ViewData holder of NORMAL chat message.
*/
public class MessageSystemViewHolder extends AbstractMessageViewHolder {
private final TextView body;
......
......@@ -4,7 +4,7 @@ import chat.rocket.android.helper.DateTime;
import chat.rocket.android.model.ddp.Message;
/**
* View Model for messages in chatroom.
* ViewData Model for messages in chatroom.
*/
public class PairedMessage {
public final Message target;
......
package chat.rocket.android.layouthelper.chatroom.dialog;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import chat.rocket.android.R;
import chat.rocket.android.message.MessageSpec;
public class MessageSelectionAdapter
extends RecyclerView.Adapter<MessageSelectionViewHolder> {
private List<MessageSpec> messageSpecs = new ArrayList<>();
private ClickListener listener;
public void setListener(ClickListener listener) {
this.listener = listener;
}
public void addMessageSpec(MessageSpec messageSpec) {
messageSpecs.add(messageSpec);
notifyDataSetChanged();
}
@Override
public MessageSelectionViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.dialog_message_selection_item, parent, false);
itemView.setOnClickListener(v -> {
if (listener != null) {
listener.onClick((MessageSpec) itemView.getTag());
}
});
return new MessageSelectionViewHolder(itemView);
}
@Override
public void onBindViewHolder(MessageSelectionViewHolder holder,
int position) {
holder.onBind(messageSpecs.get(position));
}
@Override
public int getItemCount() {
return messageSpecs.size();
}
public interface ClickListener {
void onClick(MessageSpec messageSpec);
}
}
package chat.rocket.android.layouthelper.chatroom.dialog;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import chat.rocket.android.R;
import chat.rocket.android.message.MessageSpec;
public class MessageSelectionViewHolder extends RecyclerView.ViewHolder {
private ImageView messageSpecIcon;
private TextView messageSpecTitle;
public MessageSelectionViewHolder(View itemView) {
super(itemView);
messageSpecIcon = (ImageView) itemView.findViewById(R.id.message_spec_icon);
messageSpecTitle = (TextView) itemView.findViewById(R.id.message_spec_title);
}
public void onBind(MessageSpec messageSpec) {
itemView.setTag(messageSpec);
MessageSpec.ViewData viewData = messageSpec.getViewData();
setIconBackgroundColorTint(viewData.getBackgroundTint());
setIcon(viewData.getIcon());
setTitle(viewData.getTitle());
}
public void setIconBackgroundColorTint(@ColorRes int color) {
// Drawable background = DrawableCompat.wrap(messageSpecIcon.getBackground());
DrawableCompat.setTint(messageSpecIcon.getBackground(),
ContextCompat.getColor(messageSpecIcon.getContext(), color));
}
public void setIcon(@DrawableRes int icon) {
messageSpecIcon.setImageResource(icon);
}
public void setTitle(@StringRes int title) {
messageSpecTitle.setText(title);
}
}
......@@ -11,7 +11,7 @@ import chat.rocket.android.fragment.oauth.GoogleOAuthFragment;
import chat.rocket.android.fragment.oauth.TwitterOAuthFragment;
/**
* View model for OAuth login button.
* ViewData model for OAuth login button.
*/
public class OAuthProviderInfo {
private static final ArrayList<OAuthProviderInfo> _LIST = new ArrayList<OAuthProviderInfo>() {
......
package chat.rocket.android.message;
import android.content.Intent;
import chat.rocket.android.R;
public class AudioUploadMessageSpec extends FileUploadMessageSpec {
@Override
protected Intent getIntent() {
Intent intent = new Intent();
intent.setType("audio/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
return Intent.createChooser(intent, "Select Audio to Upload");
}
@Override
public ViewData getSpecificViewData() {
return new AudioUploadViewData();
}
private static class AudioUploadViewData implements MessageSpec.ViewData {
@Override
public int getBackgroundTint() {
return R.color.colorAccent;
}
@Override
public int getIcon() {
return R.drawable.ic_audiotrack_white_24dp;
}
@Override
public int getTitle() {
return R.string.audio_upload_message_spec_title;
}
}
}
package chat.rocket.android.message;
import android.app.Activity;
import android.support.v4.app.Fragment;
import android.content.Intent;
public abstract class FileUploadMessageSpec extends MessageSpec {
public static final int RC_UPL = 0x12;
private ViewData viewData;
@Override
public ViewData getViewData() {
if (viewData == null) {
viewData = getSpecificViewData();
}
return viewData;
}
@Override
public void onSelect(Activity activity) {
activity.startActivityForResult(getIntent(), RC_UPL);
}
@Override
public void onSelect(Fragment fragment) {
fragment.startActivityForResult(getIntent(), RC_UPL);
}
protected abstract Intent getIntent();
protected abstract ViewData getSpecificViewData();
}
package chat.rocket.android.message;
import android.content.Intent;
import chat.rocket.android.R;
public class ImageUploadMessageSpec extends FileUploadMessageSpec {
@Override
public ViewData getSpecificViewData() {
return new ImageUploadViewData();
}
@Override
protected Intent getIntent() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
return Intent.createChooser(intent, "Select Picture to Upload");
}
private static class ImageUploadViewData implements MessageSpec.ViewData {
@Override
public int getBackgroundTint() {
return R.color.colorAccent;
}
@Override
public int getIcon() {
return R.drawable.ic_insert_photo_white_24dp;
}
@Override
public int getTitle() {
return R.string.image_upload_message_spec_title;
}
}
}
package chat.rocket.android.message;
import android.app.Activity;
import android.support.v4.app.Fragment;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.StringRes;
public abstract class MessageSpec {
public abstract ViewData getViewData();
public abstract void onSelect(Activity activity);
public abstract void onSelect(Fragment fragment);
public interface ViewData {
@ColorRes
int getBackgroundTint();
@DrawableRes
int getIcon();
@StringRes
int getTitle();
}
}
package chat.rocket.android.message;
import android.content.Intent;
import chat.rocket.android.R;
public class VideoUploadMessageSpec extends FileUploadMessageSpec {
@Override
public ViewData getSpecificViewData() {
return new VideoUploadViewData();
}
@Override
protected Intent getIntent() {
Intent intent = new Intent();
intent.setType("video/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
return Intent.createChooser(intent, "Select Video to Upload");
}
private static class VideoUploadViewData implements MessageSpec.ViewData {
@Override
public int getBackgroundTint() {
return R.color.colorAccent;
}
@Override
public int getIcon() {
return R.drawable.ic_video_call_white_24dp;
}
@Override
public int getTitle() {
return R.string.video_upload_message_spec_title;
}
}
}
......@@ -4,7 +4,7 @@ import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
/**
* View model for notification.
* ViewData model for notification.
*/
public class NotificationItem extends RealmObject {
@PrimaryKey private String roomId;
......
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/black" />
</shape>
\ No newline at end of file
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M12,3v9.28c-0.47,-0.17 -0.97,-0.28 -1.5,-0.28C8.01,12 6,14.01 6,16.5S8.01,21 10.5,21c2.31,0 4.2,-1.75 4.45,-4H15V6h4V3h-7z"
android:fillColor="#FFFFFF"/>
</vector>
......@@ -2,9 +2,8 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:alpha="0.78">
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z" />
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4zM14,13h-3v3H9v-3H6v-2h3V8h2v3h3v2z"
android:fillColor="#FFFFFF"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<chat.rocket.android.widget.AutofitRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/message_spec_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="80dp"
tools:listitem="@layout/dialog_message_selection_item"
android:clipToPadding="false">
</chat.rocket.android.widget.AutofitRecyclerView>
\ No newline at end of file
<?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:orientation="vertical"
android:layout_width="80dp"
android:layout_height="wrap_content"
android:padding="@dimen/margin_8">
<ImageView
android:id="@+id/message_spec_icon"
android:layout_width="64dp"
android:layout_height="64dp"
android:padding="@dimen/margin_16"
tools:src="@drawable/ic_insert_photo_white_24dp"
android:layout_marginBottom="4dp"
android:background="@drawable/circle_black" />
<TextView
android:id="@+id/message_spec_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
tools:text="Attach file" />
</LinearLayout>
\ No newline at end of file
......@@ -18,7 +18,7 @@
<string name="resend">Resend</string>
<string name="discard">Discard</string>
<string name="file_uploading_title">Uploading...</string>
<string name="file_uploading_title">Uploading</string>
<string name="dialog_user_registration_email">Email</string>
<string name="dialog_user_registration_username">Username</string>
......@@ -34,4 +34,9 @@
<string name="server_config_activity_authenticating">Authenticating…</string>
<string name="home_fragment_title">Rocket.Chat - Home</string>
<string name="fragment_sidebar_main_unread_rooms_title">UNREAD ROOMS</string>
<string name="doc_upload_message_spec_title">Attach file</string>
<string name="image_upload_message_spec_title">Attach image</string>
<string name="audio_upload_message_spec_title">Attach audio</string>
<string name="video_upload_message_spec_title">Attach video</string>
</resources>
package chat.rocket.android.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
/**
* Chiu-Ki Chan's autofit recycler view
*
* Available at: https://github.com/chiuki/android-recyclerview/blob/master/app/src/main/java/com/sqisland/android/recyclerview/AutofitRecyclerView.java
*/
public class AutofitRecyclerView extends RecyclerView {
private GridLayoutManager manager;
private int columnWidth = -1;
public AutofitRecyclerView(Context context) {
super(context);
init(context, null);
}
public AutofitRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public AutofitRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
int[] attrsArray = {
android.R.attr.columnWidth
};
TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
columnWidth = array.getDimensionPixelSize(0, -1);
array.recycle();
}
manager = new GridLayoutManager(getContext(), 1);
setLayoutManager(manager);
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
if (columnWidth > 0) {
int spanCount = Math.max(1, getMeasuredWidth() / columnWidth);
manager.setSpanCount(spanCount);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment