diff --git a/app/build.gradle b/app/build.gradle index 1c1df3de7..25b65f9c5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -129,7 +129,7 @@ dependencies { implementation 'com.github.HITGIF:TextFieldBoxes:1.4.3' - implementation 'eu.davidea:flexible-adapter:5.0.3' + implementation 'eu.davidea:flexible-adapter:5.0.4' implementation 'eu.davidea:flexible-adapter-ui:1.0.0-b3' implementation 'com.github.bumptech.glide:glide:4.3.0' diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index ce47f5824..86c0ffcf2 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -794,38 +794,38 @@ public class CallActivity extends AppCompatActivity { } private void checkCapabilities() { - ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl)) - .subscribeOn(Schedulers.newThread()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Observer() { - @Override - public void onSubscribe(Disposable d) { + ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl)) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { - } + } - @Override - public void onNext(CapabilitiesOverall capabilitiesOverall) { - isMultiSession = capabilitiesOverall.getOcs().getData() - .getCapabilities().getSpreedCapability() != null && - capabilitiesOverall.getOcs().getData() - .getCapabilities().getSpreedCapability() - .getFeatures() != null && capabilitiesOverall.getOcs().getData() - .getCapabilities().getSpreedCapability() - .getFeatures().contains("multi-room-users"); + @Override + public void onNext(CapabilitiesOverall capabilitiesOverall) { + isMultiSession = capabilitiesOverall.getOcs().getData() + .getCapabilities().getSpreedCapability() != null && + capabilitiesOverall.getOcs().getData() + .getCapabilities().getSpreedCapability() + .getFeatures() != null && capabilitiesOverall.getOcs().getData() + .getCapabilities().getSpreedCapability() + .getFeatures().contains("multi-room-users"); - joinRoomAndCall(); - } + joinRoomAndCall(); + } - @Override - public void onError(Throwable e) { - isMultiSession = false; - } + @Override + public void onError(Throwable e) { + isMultiSession = false; + } - @Override - public void onComplete() { + @Override + public void onComplete() { - } - }); + } + }); } private void joinRoomAndCall() { diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/MenuItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/MenuItem.java index af748e2de..9079159cb 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/MenuItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/MenuItem.java @@ -91,7 +91,7 @@ public class MenuItem extends AbstractFlexibleItem holder.menuTitle.setText(spannableString); } else { holder.menuTitle.setText(title); - holder.menuTitle.setCompoundDrawablesWithIntrinsicBounds(icon,null,null,null); + holder.menuTitle.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null); holder.menuTitle.setCompoundDrawablePadding(padding); } } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java index a4730d1da..e2a8e655b 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java @@ -163,7 +163,8 @@ public class UserItem extends AbstractFlexibleItem public TextView contactDisplayName; @BindView(R.id.avatar_flip_view) public FlipView avatarFlipView; - @Nullable @BindView(R.id.secondary_text) + @Nullable + @BindView(R.id.secondary_text) public TextView contactMentionId; /** diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java index 502b5bcda..6d09d8fa0 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.java @@ -20,26 +20,48 @@ package com.nextcloud.talk.adapters.messages; +import android.text.Html; import android.text.TextUtils; import android.view.View; import android.widget.TextView; import com.nextcloud.talk.R; +import com.nextcloud.talk.application.NextcloudTalkApplication; +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.stfalcon.chatkit.messages.MessageHolders; +import java.util.HashMap; + +import javax.inject.Inject; + +import autodagger.AutoInjector; import butterknife.BindView; import butterknife.ButterKnife; +@AutoInjector(NextcloudTalkApplication.class) public class MagicIncomingTextMessageViewHolder extends MessageHolders.IncomingTextMessageViewHolder { @BindView(R.id.messageAuthor) TextView messageAuthor; + @BindView(R.id.messageText) + TextView messageText; + + @Inject + UserUtils userUtils; + + private UserEntity currentUser; + public MagicIncomingTextMessageViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); + NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this); + + currentUser = userUtils.getCurrentUser(); } @@ -52,5 +74,32 @@ public class MagicIncomingTextMessageViewHolder } else { messageAuthor.setText(R.string.nc_nick_guest); } + + HashMap> messageParameters = message.getMessageParameters(); + + String messageString = message.getText(); + + if (messageParameters != null && message.getMessageParameters().size() > 0) { + for (String key : message.getMessageParameters().keySet()) { + HashMap individualHashMap = message.getMessageParameters().get(key); + if (individualHashMap.get("type").equals("user")) { + int color; + + if (messageParameters.get(key).get("id").equals(currentUser.getUserId())) { + color = NextcloudTalkApplication.getSharedApplication().getResources().getColor(R.color + .colorAccent); + } else { + color = NextcloudTalkApplication.getSharedApplication().getResources().getColor(R.color + .colorAccentComplement); + } + + messageString = DisplayUtils.searchAndColor(messageString, + "@" + messageParameters.get(key).get("name"), color); + } + } + + } + + messageText.setText(Html.fromHtml(messageString)); } } \ No newline at end of file diff --git a/app/src/main/java/com/nextcloud/talk/api/NcApi.java b/app/src/main/java/com/nextcloud/talk/api/NcApi.java index cbf91d05b..53b6b00c2 100644 --- a/app/src/main/java/com/nextcloud/talk/api/NcApi.java +++ b/app/src/main/java/com/nextcloud/talk/api/NcApi.java @@ -261,13 +261,13 @@ public interface NcApi { @GET Observable getCapabilities(@Header("Authorization") String authorization, @Url String url); - /* - QueryMap items are as follows: - - "lookIntoFuture": int (0 or 1), - - "limit" : int, range 100-200, - - "timeout": used with look into future, 30 default, 60 at most - - "lastKnownMessageId", int, use one from X-Chat-Last-Given - */ + /* + QueryMap items are as follows: + - "lookIntoFuture": int (0 or 1), + - "limit" : int, range 100-200, + - "timeout": used with look into future, 30 default, 60 at most + - "lastKnownMessageId", int, use one from X-Chat-Last-Given + */ @GET Observable> pullChatMessages(@Header("Authorization") String authorization, @Url String url, @QueryMap Map fields); @@ -286,7 +286,7 @@ public interface NcApi { @GET Observable getMentionAutocompleteSuggestions(@Header("Authorization") String authorization, - @Url String url, @Query("search") String query, - @Nullable @Query("limit") Integer limit); + @Url String url, @Query("search") String query, + @Nullable @Query("limit") Integer limit); } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java index 3a45b8992..1c77a62db 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.java @@ -118,6 +118,7 @@ public class ChatController extends BaseController implements MessagesListAdapte private Menu globalMenu; private Autocomplete mentionAutocomplete; + /* TODO: - format mentions diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.java b/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.java index 2e88b75e9..4b0621fad 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.java @@ -99,15 +99,15 @@ public class ServerSelectionController extends BaseController { @OnClick(R.id.cert_text_view) public void onCertClick() { if (getActivity() != null) { - KeyChain.choosePrivateKeyAlias(getActivity(), alias -> { - if (alias != null) { - appPreferences.setTemporaryClientCertAlias(alias); - } else { - appPreferences.removeTemporaryClientCertAlias(); - } + KeyChain.choosePrivateKeyAlias(getActivity(), alias -> { + if (alias != null) { + appPreferences.setTemporaryClientCertAlias(alias); + } else { + appPreferences.removeTemporaryClientCertAlias(); + } - setCertTextView(); - }, new String[]{"RSA", "EC"}, null, null, -1, null); + setCertTextView(); + }, new String[]{"RSA", "EC"}, null, null, -1, null); } } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java b/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java index c4f07e8f9..6dd76e8e7 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java @@ -43,12 +43,10 @@ import autodagger.AutoInjector; @AutoInjector(NextcloudTalkApplication.class) public abstract class BaseController extends RefWatchingController { + private static final String TAG = "BaseController"; @Inject AppPreferences appPreferences; - - private static final String TAG = "BaseController"; - protected BaseController() { cleanTempCertPreference(); } @@ -72,6 +70,7 @@ public abstract class BaseController extends RefWatchingController { } } + @Override protected void onViewBound(@NonNull View view) { super.onViewBound(view); diff --git a/app/src/main/java/com/nextcloud/talk/controllers/base/bottomnavigation/BottomNavigationController.java b/app/src/main/java/com/nextcloud/talk/controllers/base/bottomnavigation/BottomNavigationController.java index 5be5019d0..b7b6b232a 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/base/bottomnavigation/BottomNavigationController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/base/bottomnavigation/BottomNavigationController.java @@ -55,9 +55,10 @@ import butterknife.BindView; * The backstack of each {@link MenuItem} is switched out, in order to maintain a separate backstack * for each {@link MenuItem} - even though that is against the Google Design Guidelines: * + * @author chris6647@gmail.com * @see Material - * Design Guidelines + * href="https://material.io/guidelines/components/bottom-navigation.html#bottom-navigation-behavior">Material + * Design Guidelines * * Internally works similarly to {@link com.bluelinelabs.conductor.support.RouterPagerAdapter}, * in the sense that it keeps track of the currently active {@link MenuItem} and the paired @@ -66,18 +67,14 @@ import butterknife.BindView; * of the Child {@link Router}, and cache it, so we have it available when we navigate to * another {@link MenuItem} and can then restore the correct Child {@link Router} * (and thus the entire backstack) - * - * @author chris6647@gmail.com */ public abstract class BottomNavigationController extends BaseController { public static final String TAG = "BottomNavigationContr"; - + public static final int INVALID_INT = -1; private static final String KEY_MENU_RESOURCE = "key_menu_resource"; private static final String KEY_STATE_ROUTER_BUNDLES = "key_state_router_bundles"; private static final String KEY_STATE_CURRENTLY_SELECTED_ID = "key_state_currently_selected_id"; - public static final int INVALID_INT = -1; - @BindView(R.id.navigation) BottomNavigationView bottomNavigationView; diff --git a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/CallMenuController.java b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/CallMenuController.java index 4df7e8ed5..8787e528b 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/CallMenuController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/CallMenuController.java @@ -24,7 +24,6 @@ import android.content.ComponentName; import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v7.widget.DividerItemDecoration; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; diff --git a/app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalJob.java b/app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalJob.java index e0a6ca8e8..f129df657 100644 --- a/app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalJob.java +++ b/app/src/main/java/com/nextcloud/talk/jobs/AccountRemovalJob.java @@ -160,21 +160,21 @@ public class AccountRemovalJob extends Job { userEntity.getBaseUrl()) .subscribeOn(Schedulers.newThread()) .subscribe(new CompletableObserver() { - @Override - public void onSubscribe(Disposable d) { + @Override + public void onSubscribe(Disposable d) { - } + } - @Override - public void onComplete() { + @Override + public void onComplete() { - } + } - @Override - public void onError(Throwable e) { + @Override + public void onError(Throwable e) { - } - }); + } + }); } } catch (IOException e) { Log.d(TAG, "Something went wrong while removing job at parsing PushConfigurationState"); @@ -182,21 +182,21 @@ public class AccountRemovalJob extends Job { userEntity.getBaseUrl()) .subscribeOn(Schedulers.newThread()) .subscribe(new CompletableObserver() { - @Override - public void onSubscribe(Disposable d) { + @Override + public void onSubscribe(Disposable d) { - } + } - @Override - public void onComplete() { + @Override + public void onComplete() { - } + } - @Override - public void onError(Throwable e) { + @Override + public void onError(Throwable e) { - } - }); + } + }); } } return Result.SUCCESS; diff --git a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java index 70d8ade7d..c2101b9a8 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java +++ b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java @@ -37,6 +37,25 @@ import lombok.Data; @JsonObject public class ChatMessage implements IMessage { String baseUrl; + @JsonField(name = "id") + int jsonMessageId; + @JsonField(name = "token") + String token; + // guests or users + @JsonField(name = "actorType") + String actorType; + @JsonField(name = "actorId") + String actorId; + // send when crafting a message + @JsonField(name = "actorDisplayName") + String actorDisplayName; + @JsonField(name = "timestamp") + long timestamp; + // send when crafting a message, max 1000 lines + @JsonField(name = "message") + String message; + @JsonField(name = "messageParameters") + HashMap> messageParameters; public String getBaseUrl() { return baseUrl; @@ -46,33 +65,6 @@ public class ChatMessage implements IMessage { this.baseUrl = baseUrl; } - @JsonField(name = "id") - int jsonMessageId; - - @JsonField(name = "token") - String token; - - // guests or users - @JsonField(name = "actorType") - String actorType; - - @JsonField(name = "actorId") - String actorId; - - // send when crafting a message - @JsonField(name = "actorDisplayName") - String actorDisplayName; - - @JsonField(name = "timestamp") - long timestamp; - - // send when crafting a message, max 1000 lines - @JsonField(name = "message") - String message; - - @JsonField(name = "messageParameters") - HashMap> messageParameters; - @Override public String getId() { return Integer.toString(jsonMessageId); diff --git a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.java b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.java index d09144094..839be5b4d 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.java +++ b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatOCS.java @@ -35,6 +35,7 @@ import lombok.Data; @Parcel @JsonObject public class ChatOCS extends GenericOCS { - @Nullable @JsonField(name = "data") + @Nullable + @JsonField(name = "data") List data; } diff --git a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java index 9fc74c2a7..c77003915 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java @@ -25,15 +25,19 @@ import android.content.Context; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Build; +import android.support.annotation.ColorInt; import android.support.annotation.ColorRes; import android.support.annotation.DrawableRes; import android.support.v7.widget.AppCompatDrawableManager; +import android.text.TextUtils; import android.util.DisplayMetrics; import android.util.Log; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class DisplayUtils { @@ -75,4 +79,28 @@ public class DisplayUtils { drawable.setTint(color); return drawable; } + + + public static String searchAndColor(String text, String searchText, @ColorInt int color) { + + if (TextUtils.isEmpty(text) || TextUtils.isEmpty(searchText)) { + return text; + } + + Matcher m = Pattern.compile(searchText, Pattern.CASE_INSENSITIVE | Pattern.LITERAL) + .matcher(text); + + StringBuffer sb = new StringBuffer(); + + while (m.find()) { + String replacement = m.group().replace( + m.group(), + "" + m.group() + "" + ); + m.appendReplacement(sb, Matcher.quoteReplacement(replacement)); + } + m.appendTail(sb); + + return sb.toString(); + } } diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index aaf82e7f0..ed615a0df 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -3,6 +3,7 @@ #0082C9 #006AA3 #007CC2 + #C34700 #D32F2F #006400