mirror of
https://github.com/nextcloud/talk-android
synced 2025-01-31 11:32:00 +00:00
Merge branch '2.2-work'
This commit is contained in:
commit
09ed036513
@ -19,6 +19,8 @@ android {
|
||||
versionName "2.1.0"
|
||||
|
||||
flavorDimensions "default"
|
||||
renderscriptTargetApi 19
|
||||
renderscriptSupportModeEnabled true
|
||||
|
||||
productFlavors {
|
||||
// used for f-droid
|
||||
@ -152,7 +154,7 @@ dependencies {
|
||||
|
||||
implementation 'com.github.wooplr:Spotlight:1.2.3'
|
||||
|
||||
implementation 'com.github.stfalcon:chatkit:0.2.2'
|
||||
implementation 'com.github.stfalcon:chatkit:0.3.0'
|
||||
implementation 'com.otaliastudios:autocomplete:1.1.0'
|
||||
|
||||
implementation 'com.github.Kennyc1012:BottomSheet:2.4.0'
|
||||
|
@ -28,4 +28,9 @@ public class ClosedInterfaceImpl implements ClosedInterface {
|
||||
public void providerInstallerInstallIfNeededAsync() {
|
||||
// does absolutely nothing :)
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGooglePlayServicesAvailable() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -20,12 +20,16 @@
|
||||
|
||||
package com.nextcloud.talk.adapters.messages;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.google.android.flexbox.FlexboxLayout;
|
||||
import com.kevalpatel2106.emoticongifkeyboard.widget.EmoticonTextView;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
@ -33,7 +37,9 @@ import com.nextcloud.talk.models.database.UserEntity;
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage;
|
||||
import com.nextcloud.talk.utils.DisplayUtils;
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||
import com.nextcloud.talk.utils.emoticons.EmoticonUtils;
|
||||
import com.stfalcon.chatkit.messages.MessageHolders;
|
||||
import com.stfalcon.chatkit.utils.ShapeImageView;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@ -53,16 +59,24 @@ public class MagicIncomingTextMessageViewHolder
|
||||
@BindView(R.id.messageText)
|
||||
EmoticonTextView messageText;
|
||||
|
||||
@BindView(R.id.messageUserAvatar)
|
||||
ShapeImageView messageUserAvatarView;
|
||||
|
||||
@BindView(R.id.messageTime)
|
||||
TextView messageTimeView;
|
||||
|
||||
@Inject
|
||||
UserUtils userUtils;
|
||||
|
||||
private UserEntity currentUser;
|
||||
private View itemView;
|
||||
|
||||
public MagicIncomingTextMessageViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
|
||||
|
||||
this.itemView = itemView;
|
||||
currentUser = userUtils.getCurrentUser();
|
||||
}
|
||||
|
||||
@ -77,8 +91,23 @@ public class MagicIncomingTextMessageViewHolder
|
||||
messageAuthor.setText(R.string.nc_nick_guest);
|
||||
}
|
||||
|
||||
if (message.getActorType().equals("guests")) {
|
||||
TextDrawable drawable = TextDrawable.builder().beginConfig().bold()
|
||||
.endConfig().buildRound(String.valueOf(messageAuthor.getText().charAt(0)), NextcloudTalkApplication
|
||||
.getSharedApplication().getResources().getColor(R.color.nc_grey));
|
||||
messageUserAvatarView.setVisibility(View.VISIBLE);
|
||||
messageUserAvatarView.setImageDrawable(drawable);
|
||||
}
|
||||
|
||||
HashMap<String, HashMap<String, String>> messageParameters = message.getMessageParameters();
|
||||
|
||||
Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
|
||||
itemView.setSelected(false);
|
||||
messageTimeView.setTextColor(context.getResources().getColor(R.color.warm_grey_four));
|
||||
|
||||
FlexboxLayout.LayoutParams layoutParams = (FlexboxLayout.LayoutParams) messageTimeView.getLayoutParams();
|
||||
layoutParams.setWrapBefore(false);
|
||||
|
||||
Spannable messageString = new SpannableString(message.getText());
|
||||
|
||||
if (messageParameters != null && message.getMessageParameters().size() > 0) {
|
||||
@ -100,8 +129,14 @@ public class MagicIncomingTextMessageViewHolder
|
||||
}
|
||||
}
|
||||
|
||||
} else if (EmoticonUtils.isMessageWithSingleEmoticonOnly(context, message.getText())) {
|
||||
messageString.setSpan(new RelativeSizeSpan(2.5f), 0, messageString.length(),
|
||||
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
layoutParams.setWrapBefore(true);
|
||||
itemView.setSelected(true);
|
||||
}
|
||||
|
||||
messageTimeView.setLayoutParams(layoutParams);
|
||||
messageText.setText(messageString);
|
||||
}
|
||||
}
|
@ -20,10 +20,14 @@
|
||||
|
||||
package com.nextcloud.talk.adapters.messages;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.RelativeSizeSpan;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.android.flexbox.FlexboxLayout;
|
||||
import com.kevalpatel2106.emoticongifkeyboard.widget.EmoticonTextView;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
@ -31,6 +35,7 @@ import com.nextcloud.talk.models.database.UserEntity;
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage;
|
||||
import com.nextcloud.talk.utils.DisplayUtils;
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||
import com.nextcloud.talk.utils.emoticons.EmoticonUtils;
|
||||
import com.stfalcon.chatkit.messages.MessageHolders;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -46,16 +51,22 @@ public class MagicOutcomingTextMessageViewHolder extends MessageHolders.Outcomin
|
||||
@BindView(R.id.messageText)
|
||||
EmoticonTextView messageText;
|
||||
|
||||
@BindView(R.id.messageTime)
|
||||
TextView messageTimeView;
|
||||
|
||||
@Inject
|
||||
UserUtils userUtils;
|
||||
|
||||
private UserEntity currentUser;
|
||||
|
||||
private View itemView;
|
||||
|
||||
public MagicOutcomingTextMessageViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
ButterKnife.bind(this, itemView);
|
||||
NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
|
||||
|
||||
this.itemView = itemView;
|
||||
currentUser = userUtils.getCurrentUser();
|
||||
}
|
||||
|
||||
@ -67,6 +78,13 @@ public class MagicOutcomingTextMessageViewHolder extends MessageHolders.Outcomin
|
||||
|
||||
Spannable messageString = new SpannableString(message.getText());
|
||||
|
||||
Context context = NextcloudTalkApplication.getSharedApplication().getApplicationContext();
|
||||
itemView.setSelected(false);
|
||||
messageTimeView.setTextColor(context.getResources().getColor(R.color.white60));
|
||||
|
||||
FlexboxLayout.LayoutParams layoutParams = (FlexboxLayout.LayoutParams) messageTimeView.getLayoutParams();
|
||||
layoutParams.setWrapBefore(false);
|
||||
|
||||
if (messageParameters != null && message.getMessageParameters().size() > 0) {
|
||||
for (String key : message.getMessageParameters().keySet()) {
|
||||
HashMap<String, String> individualHashMap = message.getMessageParameters().get(key);
|
||||
@ -80,9 +98,15 @@ public class MagicOutcomingTextMessageViewHolder extends MessageHolders.Outcomin
|
||||
}
|
||||
}
|
||||
|
||||
} else if (EmoticonUtils.isMessageWithSingleEmoticonOnly(context, message.getText())) {
|
||||
messageString.setSpan(new RelativeSizeSpan(2.5f), 0, messageString.length(),
|
||||
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
||||
layoutParams.setWrapBefore(true);
|
||||
messageTimeView.setTextColor(context.getResources().getColor(R.color.warm_grey_four));
|
||||
itemView.setSelected(true);
|
||||
}
|
||||
|
||||
messageTimeView.setLayoutParams(layoutParams);
|
||||
messageText.setText(messageString);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -289,4 +289,13 @@ public interface NcApi {
|
||||
@Url String url, @Query("search") String query,
|
||||
@Nullable @Query("limit") Integer limit);
|
||||
|
||||
// Url is: /api/{apiVersion}/room/{token}/favorite
|
||||
@POST
|
||||
Observable<GenericOverall> addConversationToFavorites(@Header("Authorization") String authorization,
|
||||
@Url String url);
|
||||
|
||||
// Url is: /api/{apiVersion}/room/{token}/favorite
|
||||
@DELETE
|
||||
Observable<GenericOverall> removeConversationFromFavorites(@Header("Authorization") String authorization,
|
||||
@Url String url);
|
||||
}
|
||||
|
@ -46,10 +46,11 @@ import com.nextcloud.talk.models.json.generic.Status;
|
||||
import com.nextcloud.talk.models.json.rooms.RoomsOverall;
|
||||
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall;
|
||||
import com.nextcloud.talk.utils.ApiUtils;
|
||||
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder;
|
||||
import com.nextcloud.talk.utils.ClosedInterfaceImpl;
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences;
|
||||
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
@ -261,7 +262,13 @@ public class AccountVerificationController extends BaseController {
|
||||
public void onNext(UserEntity userEntity) {
|
||||
internalAccountId = userEntity.getId();
|
||||
|
||||
registerForPush();
|
||||
if (new ClosedInterfaceImpl().isGooglePlayServicesAvailable()) {
|
||||
registerForPush();
|
||||
} else {
|
||||
getActivity().runOnUiThread(() -> progressText.setText(progressText.getText().toString() + "\n" +
|
||||
getResources().getString(R.string.nc_push_disabled)));
|
||||
fetchAndStoreCapabilities();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -598,13 +598,7 @@ public class CallController extends BaseController {
|
||||
public void onEnableSpeakerphoneClick() {
|
||||
if (audioManager != null) {
|
||||
audioManager.toggleUseSpeakerphone();
|
||||
if (audioManager.isSpeakerphoneAutoOn()) {
|
||||
callControlEnableSpeaker.getFrontImageView().setImageDrawable(getResources().getDrawable(R.drawable
|
||||
.ic_speaker_white_24dp));
|
||||
} else {
|
||||
callControlEnableSpeaker.getFrontImageView().setImageDrawable(getResources().getDrawable(R.drawable
|
||||
.ic_hearing_white_24dp));
|
||||
}
|
||||
callControlEnableSpeaker.flipSilently(!callControlEnableSpeaker.isFlipped());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,10 +21,17 @@
|
||||
package com.nextcloud.talk.controllers;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.media.MediaPlayer;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.renderscript.Allocation;
|
||||
import android.renderscript.Element;
|
||||
import android.renderscript.RenderScript;
|
||||
import android.renderscript.ScriptIntrinsicBlur;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.constraint.ConstraintLayout;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
@ -40,7 +47,10 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||
import com.bumptech.glide.load.model.GlideUrl;
|
||||
import com.bumptech.glide.load.model.LazyHeaders;
|
||||
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.TransformationUtils;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.nextcloud.talk.R;
|
||||
import com.nextcloud.talk.api.NcApi;
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||
@ -96,6 +106,9 @@ public class CallNotificationController extends BaseController {
|
||||
@BindView(R.id.callAnswerCameraView)
|
||||
MagicFlipView callAnswerCameraView;
|
||||
|
||||
@BindView(R.id.constraintLayout)
|
||||
ConstraintLayout constraintLayout;
|
||||
|
||||
private List<Disposable> disposablesList = new ArrayList<>();
|
||||
private Bundle originalBundle;
|
||||
private String roomId;
|
||||
@ -104,6 +117,7 @@ public class CallNotificationController extends BaseController {
|
||||
private Room currentRoom;
|
||||
private MediaPlayer mediaPlayer;
|
||||
private boolean leavingScreen = false;
|
||||
private RenderScript renderScript;
|
||||
|
||||
public CallNotificationController(Bundle args) {
|
||||
super(args);
|
||||
@ -249,6 +263,7 @@ public class CallNotificationController extends BaseController {
|
||||
protected void onViewBound(@NonNull View view) {
|
||||
super.onViewBound(view);
|
||||
|
||||
renderScript = RenderScript.create(getActivity());
|
||||
handleFromNotification();
|
||||
|
||||
String callRingtonePreferenceString = appPreferences.getCallRingtoneUri();
|
||||
@ -296,8 +311,27 @@ public class CallNotificationController extends BaseController {
|
||||
.load(glideUrl)
|
||||
.centerInside()
|
||||
.override(avatarSize, avatarSize)
|
||||
.apply(RequestOptions.bitmapTransform(new CircleCrop()))
|
||||
.into(avatarImageView);
|
||||
.into(new SimpleTarget<Bitmap>() {
|
||||
@Override
|
||||
public void onResourceReady(Bitmap resource, Transition<? super Bitmap> transition) {
|
||||
if (getActivity() != null) {
|
||||
avatarImageView.setImageBitmap(TransformationUtils.circleCrop(GlideApp.get
|
||||
(getActivity()).getBitmapPool(), resource, avatarSize, avatarSize));
|
||||
}
|
||||
|
||||
final Allocation input = Allocation.createFromBitmap(renderScript, resource);
|
||||
final Allocation output = Allocation.createTyped(renderScript, input.getType());
|
||||
final ScriptIntrinsicBlur script = ScriptIntrinsicBlur.create(renderScript, Element
|
||||
.U8_4(renderScript));
|
||||
script.setRadius(15f);
|
||||
script.setInput(input);
|
||||
script.forEach(output);
|
||||
output.copyTo(resource);
|
||||
|
||||
constraintLayout.setBackground(new BitmapDrawable(resource));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
break;
|
||||
case ROOM_GROUP_CALL:
|
||||
|
@ -46,6 +46,9 @@ import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.amulyakhare.textdrawable.TextDrawable;
|
||||
import com.bumptech.glide.load.DataSource;
|
||||
@ -86,6 +89,7 @@ import com.otaliastudios.autocomplete.AutocompletePresenter;
|
||||
import com.otaliastudios.autocomplete.CharPolicy;
|
||||
import com.stfalcon.chatkit.commons.ImageLoader;
|
||||
import com.stfalcon.chatkit.commons.models.IMessage;
|
||||
import com.stfalcon.chatkit.messages.MessageHolders;
|
||||
import com.stfalcon.chatkit.messages.MessageInput;
|
||||
import com.stfalcon.chatkit.messages.MessagesList;
|
||||
import com.stfalcon.chatkit.messages.MessagesListAdapter;
|
||||
@ -107,6 +111,7 @@ import javax.inject.Inject;
|
||||
|
||||
import autodagger.AutoInjector;
|
||||
import butterknife.BindView;
|
||||
import butterknife.OnClick;
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
@ -133,6 +138,12 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
MessageInput messageInputView;
|
||||
@BindView(R.id.popupBubbleView)
|
||||
PopupBubble popupBubble;
|
||||
@BindView(R.id.emptyLayout)
|
||||
RelativeLayout emptyLayout;
|
||||
@BindView(R.id.sendHiTextView)
|
||||
TextView sendHiTextView;
|
||||
@BindView(R.id.progressBar)
|
||||
ProgressBar loadingProgressBar;
|
||||
private List<Disposable> disposableList = new ArrayList<>();
|
||||
private String conversationName;
|
||||
private String roomToken;
|
||||
@ -158,6 +169,9 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
private String roomId;
|
||||
private boolean voiceOnly;
|
||||
|
||||
private boolean isFirstMessagesProcessing = true;
|
||||
private boolean isHelloClicked;
|
||||
|
||||
public ChatController(Bundle args) {
|
||||
super(args);
|
||||
setHasOptionsMenu(true);
|
||||
@ -286,9 +300,13 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
getActionBar().show();
|
||||
boolean adapterWasNull = false;
|
||||
|
||||
sendHiTextView.setText(String.format(getResources().getString(R.string.nc_chat_empty), getResources()
|
||||
.getString(R.string.nc_hello)));
|
||||
|
||||
if (adapter == null) {
|
||||
|
||||
loadingProgressBar.setVisibility(View.VISIBLE);
|
||||
|
||||
try {
|
||||
cache.evictAll();
|
||||
} catch (IOException e) {
|
||||
@ -297,13 +315,11 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
|
||||
adapterWasNull = true;
|
||||
|
||||
MessagesListAdapter.HoldersConfig holdersConfig = new MessagesListAdapter.HoldersConfig();
|
||||
holdersConfig.setIncoming(MagicIncomingTextMessageViewHolder.class,
|
||||
R.layout.item_custom_incoming_text_message);
|
||||
holdersConfig.setOutcoming(MagicOutcomingTextMessageViewHolder.class,
|
||||
R.layout.item_custom_outcoming_text_message);
|
||||
MessageHolders messageHolders = new MessageHolders();
|
||||
messageHolders.setIncomingTextConfig(MagicIncomingTextMessageViewHolder.class, R.layout.item_custom_incoming_text_message);
|
||||
messageHolders.setOutcomingTextConfig(MagicOutcomingTextMessageViewHolder.class, R.layout.item_custom_outcoming_text_message);
|
||||
|
||||
adapter = new MessagesListAdapter<>(conversationUser.getUserId(), holdersConfig, new ImageLoader() {
|
||||
adapter = new MessagesListAdapter<>(conversationUser.getUserId(), messageHolders, new ImageLoader() {
|
||||
@Override
|
||||
public void loadImage(ImageView imageView, String url) {
|
||||
GlideApp.with(NextcloudTalkApplication.getSharedApplication().getApplicationContext())
|
||||
@ -317,7 +333,6 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
@Override
|
||||
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
|
||||
TextDrawable drawable = TextDrawable.builder().beginConfig().bold()
|
||||
.width(imageView.getMeasuredWidth()).height(imageView.getMeasuredHeight())
|
||||
.endConfig().buildRound("?", getResources().getColor(R.color.nc_grey));
|
||||
imageView.setImageDrawable(drawable);
|
||||
return true;
|
||||
@ -331,6 +346,12 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
.into(imageView);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (adapter.getItemCount() == 0) {
|
||||
emptyLayout.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
messagesListView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -480,6 +501,14 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
|
||||
}
|
||||
|
||||
@OnClick(R.id.emptyLayout)
|
||||
public void sendHello() {
|
||||
if (!isHelloClicked) {
|
||||
isHelloClicked = true;
|
||||
sendMessage(getResources().getString(R.string.nc_hello) + " 👋", 1);
|
||||
}
|
||||
}
|
||||
|
||||
private void joinRoomWithPassword() {
|
||||
|
||||
if (currentCall == null) {
|
||||
@ -697,7 +726,26 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
ChatOverall chatOverall = (ChatOverall) response.body();
|
||||
List<ChatMessage> chatMessageList = chatOverall.getOcs().getData();
|
||||
|
||||
if (isFirstMessagesProcessing) {
|
||||
isFirstMessagesProcessing = false;
|
||||
loadingProgressBar.setVisibility(View.GONE);
|
||||
|
||||
if (chatMessageList.size() == 0) {
|
||||
emptyLayout.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
messagesListView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
if (emptyLayout.getVisibility() != View.GONE) {
|
||||
emptyLayout.setVisibility(View.GONE);
|
||||
}
|
||||
if (messagesListView.getVisibility() != View.VISIBLE) {
|
||||
messagesListView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isFromTheFuture) {
|
||||
|
||||
for (int i = 0; i < chatMessageList.size(); i++) {
|
||||
chatMessageList.get(i).setBaseUrl(conversationUser.getBaseUrl());
|
||||
if (globalLastKnownPastMessageId == -1 || chatMessageList.get(i).getJsonMessageId() <
|
||||
@ -712,8 +760,10 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
adapter.addToEnd(chatMessageList, false);
|
||||
|
||||
|
||||
} else {
|
||||
for (int i = 0; i < chatMessageList.size(); i++) {
|
||||
chatMessageList.get(i).setBaseUrl(conversationUser.getBaseUrl());
|
||||
@ -754,6 +804,15 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
pullChatMessages(1);
|
||||
}
|
||||
} else if (response.code() == 304 && !isFromTheFuture) {
|
||||
if (isFirstMessagesProcessing) {
|
||||
isFirstMessagesProcessing = false;
|
||||
loadingProgressBar.setVisibility(View.GONE);
|
||||
|
||||
if (emptyLayout.getVisibility() != View.VISIBLE) {
|
||||
emptyLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
historyRead = true;
|
||||
|
||||
if (!lookingIntoFuture) {
|
||||
@ -794,7 +853,6 @@ public class ChatController extends BaseController implements MessagesListAdapte
|
||||
case android.R.id.home:
|
||||
onDestroy();
|
||||
return true;
|
||||
|
||||
case R.id.conversation_video_call:
|
||||
startACall(false);
|
||||
return true;
|
||||
|
@ -28,7 +28,6 @@ import android.os.Handler;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.BottomNavigationView;
|
||||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
@ -43,7 +42,6 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.Button;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.bluelinelabs.conductor.RouterTransaction;
|
||||
@ -68,7 +66,6 @@ import com.nextcloud.talk.models.json.rooms.RoomOverall;
|
||||
import com.nextcloud.talk.models.json.sharees.Sharee;
|
||||
import com.nextcloud.talk.models.json.sharees.ShareesOverall;
|
||||
import com.nextcloud.talk.utils.ApiUtils;
|
||||
import com.nextcloud.talk.utils.animations.ViewHidingBehaviourAnimation;
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
||||
|
||||
@ -130,16 +127,9 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
@BindView(R.id.swipe_refresh_layout)
|
||||
SwipeRefreshLayout swipeRefreshLayout;
|
||||
|
||||
@BindView(R.id.bottom_buttons_layout)
|
||||
CoordinatorLayout bottomButtonsLinearLayout;
|
||||
|
||||
@BindView(R.id.fast_scroller)
|
||||
FastScroller fastScroller;
|
||||
|
||||
@Nullable
|
||||
@BindView(R.id.clear_button)
|
||||
Button clearButton;
|
||||
|
||||
private UserEntity currentUser;
|
||||
private Disposable contactsQueryDisposable;
|
||||
private Disposable cacheQueryDisposable;
|
||||
@ -165,6 +155,8 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
private boolean canFetchFurther = true;
|
||||
private boolean canFetchSearchFurther = true;
|
||||
|
||||
private MenuItem doneMenuItem;
|
||||
|
||||
public ContactsController() {
|
||||
super();
|
||||
setHasOptionsMenu(true);
|
||||
@ -195,7 +187,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
if (isNewConversationView) {
|
||||
toggleNewCallHeaderVisibility(!isPublicCall);
|
||||
|
||||
checkAndHandleBottomButtons();
|
||||
checkAndHandleDoneMenuItem();
|
||||
|
||||
if (getActionBar() != null) {
|
||||
getActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
@ -257,29 +249,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
adapter.addListener(this);
|
||||
}
|
||||
|
||||
@Optional
|
||||
@OnClick(R.id.clear_button)
|
||||
public void onClearButtonClick() {
|
||||
if (adapter != null) {
|
||||
List<Integer> selectedPositions = adapter.getSelectedPositions();
|
||||
for (Integer position : selectedPositions) {
|
||||
if (adapter.getItem(position) instanceof UserItem) {
|
||||
UserItem userItem = (UserItem) adapter.getItem(position);
|
||||
adapter.toggleSelection(position);
|
||||
if (userItem != null) {
|
||||
userItem.flipItemSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkAndHandleBottomButtons();
|
||||
}
|
||||
|
||||
@Optional
|
||||
@OnClick(R.id.done_button)
|
||||
public void onDoneButtonClick() {
|
||||
|
||||
private void selectionDone() {
|
||||
if (!isPublicCall && adapter.getSelectedPositions().size() == 1) {
|
||||
RetrofitBucket retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser.getBaseUrl(), "1",
|
||||
((UserItem) adapter.getItem(adapter.getSelectedPositions().get(0))).getModel().getUserId(), null);
|
||||
@ -411,6 +381,9 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
case android.R.id.home:
|
||||
getRouter().popCurrentController();
|
||||
return true;
|
||||
case R.id.contacts_selection_done:
|
||||
selectionDone();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
@ -421,7 +394,9 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
inflater.inflate(R.menu.menu_conversation_plus_filter, menu);
|
||||
searchItem = menu.findItem(R.id.action_search);
|
||||
doneMenuItem = menu.findItem(R.id.contacts_selection_done);
|
||||
menu.findItem(R.id.action_new_conversation).setVisible(false);
|
||||
|
||||
initSearchView();
|
||||
}
|
||||
|
||||
@ -576,7 +551,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
}
|
||||
|
||||
if (isNewConversationView) {
|
||||
checkAndHandleBottomButtons();
|
||||
checkAndHandleDoneMenuItem();
|
||||
}
|
||||
}
|
||||
;
|
||||
@ -648,9 +623,6 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) bottomButtonsLinearLayout.getLayoutParams();
|
||||
layoutParams.setBehavior(new ViewHidingBehaviourAnimation());
|
||||
}
|
||||
|
||||
private void dispose(@Nullable Disposable disposable) {
|
||||
@ -725,23 +697,18 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
return onQueryTextChange(query);
|
||||
}
|
||||
|
||||
private void checkAndHandleBottomButtons() {
|
||||
if (adapter != null && bottomButtonsLinearLayout != null && clearButton != null) {
|
||||
private void checkAndHandleDoneMenuItem() {
|
||||
if (adapter != null && doneMenuItem != null) {
|
||||
if (adapter.getSelectedItemCount() > 0 || isPublicCall) {
|
||||
if (bottomButtonsLinearLayout.getVisibility() != View.VISIBLE) {
|
||||
bottomButtonsLinearLayout.setVisibility(View.VISIBLE);
|
||||
if (!doneMenuItem.isVisible()) {
|
||||
doneMenuItem.setVisible(true);
|
||||
}
|
||||
|
||||
if (adapter.getSelectedItemCount() == 0) {
|
||||
clearButton.setVisibility(View.GONE);
|
||||
} else {
|
||||
clearButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
bottomButtonsLinearLayout.setVisibility(View.GONE);
|
||||
doneMenuItem.setVisible(false);
|
||||
}
|
||||
} else if (bottomButtonsLinearLayout != null) {
|
||||
bottomButtonsLinearLayout.setVisibility(View.GONE);
|
||||
} else if (doneMenuItem != null) {
|
||||
doneMenuItem.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -865,7 +832,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
((UserItem) adapter.getItem(position)).flipItemSelection();
|
||||
adapter.toggleSelection(position);
|
||||
|
||||
checkAndHandleBottomButtons();
|
||||
checkAndHandleDoneMenuItem();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -876,7 +843,7 @@ public class ContactsController extends BaseController implements SearchView.OnQ
|
||||
void toggleCallHeader() {
|
||||
toggleNewCallHeaderVisibility(isPublicCall);
|
||||
isPublicCall = !isPublicCall;
|
||||
checkAndHandleBottomButtons();
|
||||
checkAndHandleDoneMenuItem();
|
||||
}
|
||||
|
||||
private void toggleNewCallHeaderVisibility(boolean showInitialLayout) {
|
||||
|
@ -125,14 +125,9 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
|
||||
|
||||
if (menuType.equals(MenuType.REGULAR)) {
|
||||
if (!TextUtils.isEmpty(room.getDisplayName())) {
|
||||
menuItems.add(new MenuItem(
|
||||
getResources().getString(
|
||||
R.string.nc_configure_named_room, room.getDisplayName()), 0, null)
|
||||
);
|
||||
menuItems.add(new MenuItem(room.getDisplayName(), 0, null));
|
||||
} else if (!TextUtils.isEmpty(room.getName())) {
|
||||
menuItems.add(new MenuItem(getResources().getString(
|
||||
R.string.nc_configure_named_room, room.getName()), 0, null)
|
||||
);
|
||||
menuItems.add(new MenuItem(room.getName(), 0, null));
|
||||
} else {
|
||||
menuItems.add(new MenuItem(getResources().getString(R.string.nc_configure_room), 0, null));
|
||||
}
|
||||
|
@ -184,6 +184,10 @@ public class EntryMenuController extends BaseController {
|
||||
super.onViewBound(view);
|
||||
NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
|
||||
|
||||
if (room != null && operationCode == 2) {
|
||||
editText.setText(room.getName());
|
||||
}
|
||||
|
||||
editText.setOnEditorActionListener((v, actionId, event) -> {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE && proceedButton != null && proceedButton.isEnabled()) {
|
||||
proceedButton.callOnClick();
|
||||
|
@ -242,7 +242,7 @@ public class NotificationJob extends Job {
|
||||
if (notificationManager != null) {
|
||||
notificationManager.notify((int) crc32.getValue(), notificationBuilder.build());
|
||||
|
||||
if (soundUri != null) {
|
||||
if (soundUri != null & !ApplicationWideCurrentRoomHolder.getInstance().isInCall()) {
|
||||
MediaPlayer mediaPlayer = MediaPlayer.create(context, soundUri);
|
||||
mediaPlayer.start();
|
||||
mediaPlayer.setOnCompletionListener(MediaPlayer::release);
|
||||
|
@ -91,7 +91,11 @@ public class ChatMessage implements IMessage {
|
||||
|
||||
@Override
|
||||
public String getAvatar() {
|
||||
return ApiUtils.getUrlForAvatarWithName(getBaseUrl(), actorId, R.dimen.avatar_size);
|
||||
if (getActorType().equals("users")) {
|
||||
return ApiUtils.getUrlForAvatarWithName(getBaseUrl(), actorId, R.dimen.avatar_size);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -63,6 +63,8 @@ public class Room {
|
||||
@JsonField(name = "sessionId")
|
||||
public String sessionId;
|
||||
public String password;
|
||||
@JsonField(name = "isFavorite")
|
||||
public boolean isFavorite;
|
||||
|
||||
public boolean isPublic() {
|
||||
return (RoomType.ROOM_PUBLIC_CALL.equals(type));
|
||||
|
@ -187,4 +187,8 @@ public class ApiUtils {
|
||||
return NextcloudTalkApplication.getSharedApplication().
|
||||
getApplicationContext().getResources().getString(R.string.nc_push_server_url) + "/devices";
|
||||
}
|
||||
|
||||
public static String getUrlForConversationFavorite(String baseUrl, String roomToken) {
|
||||
return baseUrl + ocsApiVersion + "/room/" + roomToken + "/favorite";
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2017 Keval Patel.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.utils.emoticons;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.support.v7.content.res.AppCompatResources;
|
||||
import android.text.style.DynamicDrawableSpan;
|
||||
import android.text.style.ImageSpan;
|
||||
|
||||
/**
|
||||
* Created by Keval Patel on 20/08/17.
|
||||
* The {@link ImageSpan} to display custom emoticon icon based on the unicode.
|
||||
*
|
||||
* @author 'https://github.com/kevalpatel2106'
|
||||
* @see <a href='https://github.com/rockerhieu/emojicon/blob/master/library/src/main/java/io/github/rockerhieu/emojicon/EmojiconSpan.java>EmojiconSpan.java</a>
|
||||
*/
|
||||
|
||||
final class EmoticonSpan extends DynamicDrawableSpan {
|
||||
private final float mEmoticonSize;
|
||||
private final Context mContext;
|
||||
private final int mEmoticonIcon;
|
||||
private Drawable mDeferredDrawable;
|
||||
|
||||
EmoticonSpan(final Context context, final int emoticonIcon, final float size) {
|
||||
this.mContext = context;
|
||||
this.mEmoticonIcon = emoticonIcon;
|
||||
this.mEmoticonSize = size;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Override
|
||||
public Drawable getDrawable() {
|
||||
if (mDeferredDrawable == null) {
|
||||
mDeferredDrawable = AppCompatResources.getDrawable(mContext, mEmoticonIcon);
|
||||
mDeferredDrawable.setBounds(0, 0, (int) mEmoticonSize, (int) mEmoticonSize);
|
||||
}
|
||||
return mDeferredDrawable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(final Paint paint, final CharSequence text, final int start,
|
||||
final int end, final Paint.FontMetricsInt fontMetrics) {
|
||||
if (fontMetrics != null) {
|
||||
final Paint.FontMetrics paintFontMetrics = paint.getFontMetrics();
|
||||
final float fontHeight = paintFontMetrics.descent - paintFontMetrics.ascent;
|
||||
final float centerY = paintFontMetrics.ascent + fontHeight / 2;
|
||||
|
||||
fontMetrics.ascent = (int) (centerY - mEmoticonSize / 2);
|
||||
fontMetrics.top = fontMetrics.ascent;
|
||||
fontMetrics.bottom = (int) (centerY + mEmoticonSize / 2);
|
||||
fontMetrics.descent = fontMetrics.bottom;
|
||||
}
|
||||
|
||||
return (int) mEmoticonSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(final Canvas canvas, final CharSequence text, final int start,
|
||||
final int end, final float x, final int top, final int y,
|
||||
final int bottom, final Paint paint) {
|
||||
final Drawable drawable = getDrawable();
|
||||
final Paint.FontMetrics paintFontMetrics = paint.getFontMetrics();
|
||||
final float fontHeight = paintFontMetrics.descent - paintFontMetrics.ascent;
|
||||
final float centerY = y + paintFontMetrics.descent - fontHeight / 2;
|
||||
final float transitionY = centerY - mEmoticonSize / 2;
|
||||
|
||||
canvas.save();
|
||||
canvas.translate(x, transitionY);
|
||||
drawable.draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright 2017 Keval Patel.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* Modified by Mario Danic (mario@lovelyhq.com) - Copyright 2018
|
||||
*/
|
||||
|
||||
package com.nextcloud.talk.utils.emoticons;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.Spannable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.kevalpatel2106.emoticongifkeyboard.R;
|
||||
import com.kevalpatel2106.emoticongifkeyboard.emoticons.Emoticon;
|
||||
import com.kevalpatel2106.emoticongifkeyboard.emoticons.EmoticonProvider;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created by Keval Patel on 20/08/17.
|
||||
* Utils to find emoticons from the string.
|
||||
*
|
||||
* @author 'https://github.com/kevalpatel2106'
|
||||
*/
|
||||
|
||||
public final class EmoticonUtils {
|
||||
/**
|
||||
* {@link Pattern} to find the supported emoticons unicodes.
|
||||
*/
|
||||
private static Pattern sRegexPattern;
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
*/
|
||||
private EmoticonUtils() {
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the system emoticons with the provided custom emoticons drawable. This will find the
|
||||
* unicodes with supported emoticons in the provided text and will replace the emoticons with
|
||||
* appropriate images.
|
||||
*
|
||||
* @param context instance of caller.
|
||||
* @param text Text to replace
|
||||
* @param emoticonProvider {@link EmoticonProvider} for emoticons images
|
||||
* @param emoticonSize Size of the emoticons in dp
|
||||
* @return Modified text.
|
||||
*/
|
||||
public static void replaceWithImages(@NonNull final Context context,
|
||||
@NonNull final Spannable text,
|
||||
@NonNull final EmoticonProvider emoticonProvider,
|
||||
final int emoticonSize) {
|
||||
|
||||
final EmoticonSpan[] existingSpans = text.getSpans(0, text.length(), EmoticonSpan.class);
|
||||
final ArrayList<Integer> existingSpanPositions = new ArrayList<>(existingSpans.length);
|
||||
for (EmoticonSpan existingSpan : existingSpans)
|
||||
existingSpanPositions.add(text.getSpanStart(existingSpan));
|
||||
|
||||
//Get location and unicode of all emoticons.
|
||||
final List<EmoticonRange> findAllEmojis = findAllEmoticons(context, text, emoticonProvider);
|
||||
|
||||
//Replace all the emoticons with their relatives.
|
||||
for (int i = 0; i < findAllEmojis.size(); i++) {
|
||||
final EmoticonRange location = findAllEmojis.get(i);
|
||||
if (!existingSpanPositions.contains(location.mStartPos)) {
|
||||
text.setSpan(new EmoticonSpan(context, location.mEmoticon.getIcon(), emoticonSize),
|
||||
location.mStartPos,
|
||||
location.mEndPos,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all the unicodes that represents emoticons and location of starting and ending point of that emoticon.
|
||||
*
|
||||
* @param context Instance of caller.
|
||||
* @param text Text to replace
|
||||
* @param emoticonProvider {@link EmoticonProvider} for emoticons images
|
||||
* @return List of {@link EmoticonRange}.
|
||||
* @see EmoticonRange
|
||||
*/
|
||||
@NonNull
|
||||
private static List<EmoticonRange> findAllEmoticons(@NonNull final Context context,
|
||||
@Nullable final CharSequence text,
|
||||
@NonNull final EmoticonProvider emoticonProvider) {
|
||||
final List<EmoticonRange> result = new ArrayList<>();
|
||||
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
final Matcher matcher = getRegex(context).matcher(text);
|
||||
while (matcher.find()) {
|
||||
String unicode = text.subSequence(matcher.start(), matcher.end()).toString();
|
||||
if (emoticonProvider.hasEmoticonIcon(unicode)) { //Check if the the emoticon has icon?
|
||||
final Emoticon found = new Emoticon(unicode, emoticonProvider.getIcon(unicode));
|
||||
|
||||
//Add this emoticon to change list.
|
||||
result.add(new EmoticonRange(matcher.start(), matcher.end(), found));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static boolean isMessageWithSingleEmoticonOnly(@NonNull final Context context,
|
||||
@Nullable final CharSequence text) {
|
||||
final List<EmoticonRange> result = new ArrayList<>();
|
||||
|
||||
if (!TextUtils.isEmpty(text)) {
|
||||
|
||||
// Regexp acquired from https://gist.github.com/sergeychilingaryan/94902985a636658496cb69c300bba05f
|
||||
String unicode10regexString = "(?:[\\u2700-\\u27bf]|" +
|
||||
|
||||
"(?:[\\ud83c\\udde6-\\ud83c\\uddff]){2}|" +
|
||||
"[\\ud800\\udc00-\\uDBFF\\uDFFF]|[\\u2600-\\u26FF])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|[\\ud83c\\udffb-\\ud83c\\udfff])?" +
|
||||
|
||||
"(?:\\u200d(?:[^\\ud800-\\udfff]|" +
|
||||
|
||||
"(?:[\\ud83c\\udde6-\\ud83c\\uddff]){2}|" +
|
||||
"[\\ud800\\udc00-\\uDBFF\\uDFFF]|[\\u2600-\\u26FF])[\\ufe0e\\ufe0f]?(?:[\\u0300-\\u036f\\ufe20-\\ufe23\\u20d0-\\u20f0]|[\\ud83c\\udffb-\\ud83c\\udfff])?)*|" +
|
||||
|
||||
"[\\u0023-\\u0039]\\ufe0f?\\u20e3|\\u3299|\\u3297|\\u303d|\\u3030|\\u24c2|[\\ud83c\\udd70-\\ud83c\\udd71]|[\\ud83c\\udd7e-\\ud83c\\udd7f]|\\ud83c\\udd8e|[\\ud83c\\udd91-\\ud83c\\udd9a]|[\\ud83c\\udde6-\\ud83c\\uddff]|[\\ud83c\\ude01-\\ud83c\\ude02]|\\ud83c\\ude1a|\\ud83c\\ude2f|[\\ud83c\\ude32-\\ud83c\\ude3a]|[\\ud83c\\ude50-\\ud83c\\ude51]|\\u203c|\\u2049|[\\u25aa-\\u25ab]|\\u25b6|\\u25c0|[\\u25fb-\\u25fe]|\\u00a9|\\u00ae|\\u2122|\\u2139|\\ud83c\\udc04|[\\u2600-\\u26FF]|\\u2b05|\\u2b06|\\u2b07|\\u2b1b|\\u2b1c|\\u2b50|\\u2b55|\\u231a|\\u231b|\\u2328|\\u23cf|[\\u23e9-\\u23f3]|[\\u23f8-\\u23fa]|\\ud83c\\udccf|\\u2934|\\u2935|[\\u2190-\\u21ff]";
|
||||
|
||||
final Matcher matcher = Pattern.compile(unicode10regexString, Pattern.UNICODE_CASE).matcher(text);
|
||||
while (matcher.find()) {
|
||||
String unicode = text.subSequence(matcher.start(), matcher.end()).toString();
|
||||
// quick hack
|
||||
final Emoticon found = new Emoticon(unicode, R.drawable.emoji_food);
|
||||
//Add this emoticon to change list.
|
||||
result.add(new EmoticonRange(matcher.start(), matcher.end(), found));
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return result.size() == 1 && result.get(0).mStartPos == 0 && text.length() == result.get(0).mEndPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the regex to parse unicode from the shared preference if {@link #sRegexPattern} is not
|
||||
* loaded.
|
||||
*
|
||||
* @param context Instance.
|
||||
* @return Regex to find emoticon unicode from string.
|
||||
*/
|
||||
@NonNull
|
||||
private static Pattern getRegex(@NonNull final Context context) {
|
||||
if (sRegexPattern == null) {
|
||||
String regex = readTextFile(context, R.raw.regex);
|
||||
sRegexPattern = Pattern.compile(regex);
|
||||
}
|
||||
return sRegexPattern;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static String readTextFile(@NonNull Context context, int rowResource) {
|
||||
InputStream inputStream = context.getResources().openRawResource(rowResource); // getting json
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
try {
|
||||
String sCurrentLine;
|
||||
while ((sCurrentLine = br.readLine()) != null) builder.append(sCurrentLine);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
try {
|
||||
inputStream.close();
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Range of the emoticons unicode.
|
||||
*/
|
||||
private static final class EmoticonRange {
|
||||
|
||||
/**
|
||||
* Start portion of the emoticon in string.
|
||||
*/
|
||||
final int mStartPos;
|
||||
|
||||
/**
|
||||
* End portion of the emoticon in string.
|
||||
*/
|
||||
final int mEndPos;
|
||||
|
||||
/**
|
||||
* {@link Emoticon}.
|
||||
*/
|
||||
final Emoticon mEmoticon;
|
||||
|
||||
/**
|
||||
* Private constructor.
|
||||
*
|
||||
* @param start Start portion of the emoticon in string.
|
||||
* @param end End portion of the emoticon in string.
|
||||
* @param emoticon {@link Emoticon}
|
||||
*/
|
||||
private EmoticonRange(final int start,
|
||||
final int end,
|
||||
@NonNull final Emoticon emoticon) {
|
||||
this.mStartPos = start;
|
||||
this.mEndPos = end;
|
||||
this.mEmoticon = emoticon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
final EmoticonRange that = (EmoticonRange) o;
|
||||
return mStartPos == that.mStartPos
|
||||
&& mEndPos == that.mEndPos
|
||||
&& mEmoticon.equals(that.mEmoticon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = mStartPos;
|
||||
result = 31 * result + mEndPos;
|
||||
result = 31 * result + mEmoticon.hashCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
~
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<vector android:autoMirrored="true" 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,20c-0.29,0 -0.56,-0.06 -0.76,-0.15 -0.71,-0.37 -1.21,-0.88 -1.71,-2.38 -0.51,-1.56 -1.47,-2.29 -2.39,-3 -0.79,-0.61 -1.61,-1.24 -2.32,-2.53C9.29,10.98 9,9.93 9,9c0,-2.8 2.2,-5 5,-5s5,2.2 5,5h2c0,-3.93 -3.07,-7 -7,-7S7,5.07 7,9c0,1.26 0.38,2.65 1.07,3.9 0.91,1.65 1.98,2.48 2.85,3.15 0.81,0.62 1.39,1.07 1.71,2.05 0.6,1.82 1.37,2.84 2.73,3.55 0.51,0.23 1.07,0.35 1.64,0.35 2.21,0 4,-1.79 4,-4h-2c0,1.1 -0.9,2 -2,2zM7.64,2.64L6.22,1.22C4.23,3.21 3,5.96 3,9s1.23,5.79 3.22,7.78l1.41,-1.41C6.01,13.74 5,11.49 5,9s1.01,-4.74 2.64,-6.36zM11.5,9c0,1.38 1.12,2.5 2.5,2.5s2.5,-1.12 2.5,-2.5 -1.12,-2.5 -2.5,-2.5 -2.5,1.12 -2.5,2.5z"/>
|
||||
</vector>
|
@ -21,6 +21,5 @@
|
||||
<vector android:autoMirrored="true" 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="#FFFFFF"
|
||||
android:pathData="M17,2L7,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,1.99 2,1.99L17,22c1.1,0 2,-0.9 2,-2L19,4c0,-1.1 -0.9,-2 -2,-2zM12,4c1.1,0 2,0.9 2,2s-0.9,2 -2,2c-1.11,0 -2,-0.9 -2,-2s0.89,-2 2,-2zM12,20c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,12c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
|
||||
<path android:fillColor="#FFFFFF" android:pathData="M3,9v6h4l5,5L12,4L7,9L3,9zM16.5,12c0,-1.77 -1.02,-3.29 -2.5,-4.03v8.05c1.48,-0.73 2.5,-2.25 2.5,-4.02zM14,3.23v2.06c2.89,0.86 5,3.54 5,6.71s-2.11,5.85 -5,6.71v2.06c4.01,-0.91 7,-4.49 7,-8.77s-2.99,-7.86 -7,-8.77z"/>
|
||||
</vector>
|
28
app/src/main/res/drawable/incoming_gradient.xml
Normal file
28
app/src/main/res/drawable/incoming_gradient.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
~
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:angle="-90"
|
||||
android:endColor="@color/transparent"
|
||||
android:startColor="#323232"/>
|
||||
</shape>
|
33
app/src/main/res/drawable/shape_grouped_incoming_message.xml
Normal file
33
app/src/main/res/drawable/shape_grouped_incoming_message.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
~
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners
|
||||
android:topLeftRadius="@dimen/message_bubble_corners_radius"
|
||||
android:bottomRightRadius="@dimen/message_bubble_corners_radius"
|
||||
android:bottomLeftRadius="@dimen/message_bubble_corners_radius"
|
||||
android:topRightRadius="@dimen/message_bubble_corners_radius" />
|
||||
|
||||
<solid android:color="@color/white" />
|
||||
|
||||
</shape>
|
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
~
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners
|
||||
android:bottomLeftRadius="@dimen/message_bubble_corners_radius"
|
||||
android:topRightRadius="@dimen/message_bubble_corners_radius"
|
||||
android:topLeftRadius="@dimen/message_bubble_corners_radius"
|
||||
android:bottomRightRadius="@dimen/message_bubble_corners_radius" />
|
||||
|
||||
<solid android:color="@color/white" />
|
||||
|
||||
</shape>
|
33
app/src/main/res/drawable/shape_incoming_message.xml
Normal file
33
app/src/main/res/drawable/shape_incoming_message.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
~
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners
|
||||
android:topLeftRadius="0dp"
|
||||
android:bottomRightRadius="@dimen/message_bubble_corners_radius"
|
||||
android:bottomLeftRadius="@dimen/message_bubble_corners_radius"
|
||||
android:topRightRadius="@dimen/message_bubble_corners_radius" />
|
||||
|
||||
<solid android:color="@color/white" />
|
||||
|
||||
</shape>
|
33
app/src/main/res/drawable/shape_outcoming_message.xml
Normal file
33
app/src/main/res/drawable/shape_outcoming_message.xml
Normal file
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
~
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<corners
|
||||
android:bottomLeftRadius="@dimen/message_bubble_corners_radius"
|
||||
android:topRightRadius="0dp"
|
||||
android:topLeftRadius="@dimen/message_bubble_corners_radius"
|
||||
android:bottomRightRadius="@dimen/message_bubble_corners_radius" />
|
||||
|
||||
<solid android:color="@color/white" />
|
||||
|
||||
</shape>
|
@ -1,59 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
~
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/bottom_buttons_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="bottom"
|
||||
android:animateLayoutChanges="true"
|
||||
android:gravity="bottom"
|
||||
android:orientation="horizontal"
|
||||
android:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/clear_button"
|
||||
style="?android:attr/borderlessButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.6"
|
||||
android:background="@color/nc_darkRed"
|
||||
android:text="@string/nc_contacts_clear"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@android:color/white"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/done_button"
|
||||
style="?android:attr/borderlessButtonStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.4"
|
||||
android:background="@color/nc_darkGreen"
|
||||
android:text="@string/nc_contacts_done"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@android:color/white"/>
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.design.widget.CoordinatorLayout>
|
@ -151,7 +151,10 @@
|
||||
android:visibility="gone"
|
||||
app:enableInitialAnimation="false"
|
||||
app:frontBackgroundColor="@color/colorPrimary"
|
||||
app:frontImage="@drawable/ic_hearing_white_24dp"/>
|
||||
app:animateRearImage="false"
|
||||
app:rearBackgroundColor="@color/colorPrimaryDark"
|
||||
app:frontImage="@drawable/ic_volume_up_white_24dp"
|
||||
app:rearImage="@drawable/ic_volume_up_white_24dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -21,33 +21,42 @@
|
||||
<android.support.constraint.ConstraintLayout 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:id="@+id/constraintLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/grey950">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/incomingCallTextView"
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/nc_incoming_call"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/white30"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
android:background="@drawable/incoming_gradient">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conversationNameTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="28sp"
|
||||
app:layout_constraintTop_toBottomOf="@+id/incomingCallTextView"
|
||||
tools:text="Victor Gregorius Magnus"/>
|
||||
<TextView
|
||||
android:id="@+id/incomingCallTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/nc_incoming_call"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/white30"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conversationNameTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="28sp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_below="@+id/incomingCallTextView"
|
||||
tools:text="Victor Gregorius Magnus"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatarImageView"
|
||||
|
@ -24,45 +24,84 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="@dimen/item_height"
|
||||
android:layout_height="@dimen/item_height"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginEnd="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginLeft="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/activity_horizontal_margin"
|
||||
android:layout_marginStart="@dimen/activity_horizontal_margin"
|
||||
android:indeterminate="true"
|
||||
android:indeterminateTint="@color/colorPrimary"
|
||||
android:indeterminateTintMode="src_in"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/emptyLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/wawingTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="👋"
|
||||
android:textAlignment="center"
|
||||
android:textSize="72sp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sendHiTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/wawingTextView"
|
||||
android:layout_margin="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<com.stfalcon.chatkit.messages.MessagesList
|
||||
android:id="@+id/messagesListView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingBottom="16dp"
|
||||
android:layout_above="@+id/messageInputView"
|
||||
android:paddingBottom="16dp"
|
||||
android:visibility="gone"
|
||||
app:dateHeaderTextSize="13sp"
|
||||
app:incomingBubblePaddingBottom="@dimen/message_bubble_corners_padding"
|
||||
app:incomingBubblePaddingLeft="@dimen/message_bubble_corners_padding"
|
||||
app:incomingBubblePaddingRight="@dimen/message_bubble_corners_padding"
|
||||
app:incomingBubblePaddingTop="@dimen/message_bubble_corners_padding"
|
||||
app:incomingDefaultBubbleColor="@color/white_two"
|
||||
app:incomingDefaultBubblePressedColor="@color/white_two"
|
||||
app:incomingDefaultBubbleSelectedColor="@color/colorPrimaryDark"
|
||||
app:incomingDefaultBubbleSelectedColor="@color/transparent"
|
||||
app:incomingTextColor="@color/nc_incoming_text_default"
|
||||
app:incomingTextLinkColor="@color/nc_incoming_text_default"
|
||||
app:incomingTextSize="@dimen/chat_text_size"
|
||||
app:incomingTimeTextSize="12sp"
|
||||
app:incomingBubblePaddingTop="@dimen/message_bubble_corners_padding"
|
||||
app:incomingBubblePaddingBottom="@dimen/message_bubble_corners_padding"
|
||||
app:incomingBubblePaddingLeft="@dimen/message_bubble_corners_padding"
|
||||
app:incomingBubblePaddingRight="@dimen/message_bubble_corners_padding"
|
||||
app:outcomingBubblePaddingTop="@dimen/message_bubble_corners_padding"
|
||||
app:outcomingBubblePaddingBottom="@dimen/message_bubble_corners_padding"
|
||||
app:outcomingBubblePaddingLeft="@dimen/message_bubble_corners_padding"
|
||||
app:outcomingBubblePaddingRight="@dimen/message_bubble_corners_padding"
|
||||
app:outcomingBubblePaddingTop="@dimen/message_bubble_corners_padding"
|
||||
app:outcomingDefaultBubbleColor="@color/colorPrimary"
|
||||
app:outcomingDefaultBubblePressedColor="@color/colorPrimary"
|
||||
app:outcomingDefaultBubbleSelectedColor="@color/colorPrimaryDark"
|
||||
app:outcomingDefaultBubbleSelectedColor="@color/transparent"
|
||||
app:outcomingTextColor="@color/nc_outcoming_text_default"
|
||||
app:outcomingTextLinkColor="@color/nc_outcoming_text_default"
|
||||
app:outcomingTextSize="@dimen/chat_text_size"
|
||||
app:outcomingTimeTextColor="@color/warm_grey_four"
|
||||
app:outcomingTimeTextSize="12sp"
|
||||
app:dateHeaderTextSize="13sp"
|
||||
app:textAutoLink="all"/>
|
||||
|
||||
<com.webianks.library.PopupBubble
|
||||
android:id="@+id/popupBubbleView"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/separator"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_margin="16dp"
|
||||
android:paddingEnd="8dp"
|
||||
app:pb_backgroundColor="@color/colorPrimary"
|
||||
app:pb_icon="@drawable/ic_baseline_arrow_downward_24px"
|
||||
|
@ -45,9 +45,5 @@
|
||||
|
||||
</android.support.v4.widget.SwipeRefreshLayout>
|
||||
|
||||
<include
|
||||
layout="@layout/bottom_buttons"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<include layout="@layout/fast_scroller"/>
|
||||
</android.support.design.widget.CoordinatorLayout>
|
||||
|
@ -33,7 +33,7 @@
|
||||
android:id="@id/messageUserAvatar"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginEnd="8dp"/>
|
||||
|
||||
<com.google.android.flexbox.FlexboxLayout
|
||||
@ -64,14 +64,13 @@
|
||||
app:layout_wrapBefore="true"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@id/messageTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/messageText"
|
||||
android:layout_marginStart="8dp"
|
||||
app:layout_alignSelf="center"/>
|
||||
|
||||
</com.google.android.flexbox.FlexboxLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@id/messageTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignEnd="@id/bubble"
|
||||
android:layout_below="@id/bubble"
|
||||
android:layout_marginStart="16dp"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
@ -47,14 +47,14 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignWithParentIfMissing="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@id/messageTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/messageText"
|
||||
android:layout_marginStart="8dp"
|
||||
app:layout_alignSelf="center"/>
|
||||
|
||||
</com.google.android.flexbox.FlexboxLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@id/messageTime"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignEnd="@id/bubble"
|
||||
android:layout_below="@id/bubble"
|
||||
android:layout_marginStart="16dp"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
47
app/src/main/res/layout/library_fast_scroller_layout.xml
Normal file
47
app/src/main/res/layout/library_fast_scroller_layout.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<View
|
||||
android:id="@+id/fast_scroller_bar"
|
||||
android:layout_width="7dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:background="@color/transparent"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fast_scroller_bubble"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginEnd="0dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:layout_toStartOf="@+id/fast_scroller_handle"
|
||||
android:background="@drawable/fast_scroller_bubble"
|
||||
android:gravity="center"
|
||||
android:textColor="?android:attr/textColorPrimaryInverse"
|
||||
android:textSize="38sp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:text="A" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/fast_scroller_handle"
|
||||
android:alpha="0.5"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:paddingStart="6dp"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/fast_scroller_handle"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</merge>
|
30
app/src/main/res/menu/menu_contacts.xml
Normal file
30
app/src/main/res/menu/menu_contacts.xml
Normal file
@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Nextcloud Talk application
|
||||
~
|
||||
~ @author Mario Danic
|
||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
~
|
||||
~ 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/>.
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/contacts_selection_done"
|
||||
android:title="@string/nc_contacts_done"
|
||||
app:showAsAction="always"
|
||||
android:visible="false"/>
|
||||
</menu>
|
@ -35,4 +35,11 @@
|
||||
android:title="@string/nc_new_conversation"
|
||||
android:icon="@drawable/ic_add_white_24px"
|
||||
app:showAsAction="ifRoom"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/contacts_selection_done"
|
||||
android:title="@string/nc_contacts_done"
|
||||
app:showAsAction="always"
|
||||
android:visible="false"/>
|
||||
|
||||
</menu>
|
||||
|
@ -17,7 +17,7 @@
|
||||
<dimen name="avatar_size">40dp</dimen>
|
||||
<dimen name="avatar_size_big">80dp</dimen>
|
||||
<dimen name="avatar_size_very_big">@dimen/avatar_fetching_size_very_big</dimen>
|
||||
<dimen name="avatar_fetching_size_very_big">140dp</dimen>
|
||||
<dimen name="avatar_fetching_size_very_big">180dp</dimen>
|
||||
<dimen name="avatar_corner_radius">20dp</dimen>
|
||||
|
||||
<dimen name="chat_text_size">14sp</dimen>
|
||||
|
@ -85,7 +85,6 @@
|
||||
<!-- Room menu -->
|
||||
<string name="nc_start_conversation">Start a conversation</string>
|
||||
<string name="nc_configure_room">Configure conversation</string>
|
||||
<string name="nc_configure_named_room">%1$s</string>
|
||||
<string name="nc_leave">Leave conversation</string>
|
||||
<string name="nc_rename">Rename conversation</string>
|
||||
<string name="nc_set_password">Set a password</string>
|
||||
@ -145,7 +144,6 @@
|
||||
<string name="nc_share_text_pass">\nPassword: %1$s</string>
|
||||
|
||||
<!-- Magical stuff -->
|
||||
<string name="nc_empty"></string>
|
||||
<string name="nc_push_to_talk">Push-to-talk</string>
|
||||
<string name="nc_push_to_talk_desc">With microphone disabled, click&hold to use Push-to-talk</string>
|
||||
<string name="nc_store_short_desc">Have private video calls and chat using your own server.</string>
|
||||
@ -197,4 +195,8 @@ Find Nextcloud on https://nextcloud.com</string>
|
||||
<string name="nc_description_more_menu_group">Menu for public conversation %1$s</string>
|
||||
<string name="nc_description_send_message_button">Send message</string>
|
||||
|
||||
<!-- Chat empty state -->
|
||||
<string name="nc_chat_empty">Click to be the first to say %1$s!</string>
|
||||
<string name="nc_hello">Hello</string>
|
||||
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user