浏览代码

Partly implement mention highlight

Signed-off-by: Mario Danic <mario@lovelyhq.com>
Mario Danic 7 年之前
父节点
当前提交
08f44a04e1

+ 1 - 1
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'

+ 27 - 27
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<CapabilitiesOverall>() {
-                        @Override
-                        public void onSubscribe(Disposable d) {
+        ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
+                .subscribeOn(Schedulers.newThread())
+                .observeOn(AndroidSchedulers.mainThread())
+                .subscribe(new Observer<CapabilitiesOverall>() {
+                    @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");
-
-                            joinRoomAndCall();
-                        }
+                    @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();
+                    }
 
-                        @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() {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/adapters/items/MenuItem.java

@@ -91,7 +91,7 @@ public class MenuItem extends AbstractFlexibleItem<MenuItem.MenuItemViewHolder>
             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);
         }
     }

+ 2 - 1
app/src/main/java/com/nextcloud/talk/adapters/items/UserItem.java

@@ -163,7 +163,8 @@ public class UserItem extends AbstractFlexibleItem<UserItem.UserItemViewHolder>
         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;
 
         /**

+ 49 - 0
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<ChatMessage> {
 
     @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<String, HashMap<String, String>> messageParameters = message.getMessageParameters();
+
+        String messageString = message.getText();
+
+        if (messageParameters != null && message.getMessageParameters().size() > 0) {
+            for (String key : message.getMessageParameters().keySet()) {
+                HashMap<String, String> 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));
     }
 }

+ 9 - 9
app/src/main/java/com/nextcloud/talk/api/NcApi.java

@@ -261,13 +261,13 @@ public interface NcApi {
     @GET
     Observable<CapabilitiesOverall> 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<Response<ChatOverall>> pullChatMessages(@Header("Authorization") String authorization, @Url String url,
                                                        @QueryMap Map<String, Integer> fields);
@@ -286,7 +286,7 @@ public interface NcApi {
 
     @GET
     Observable<MentionOverall> 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);
 
 }

+ 1 - 0
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

+ 8 - 8
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);
         }
     }
 

+ 2 - 3
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);

+ 4 - 7
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 <a
- *     href="https://material.io/guidelines/components/bottom-navigation.html#bottom-navigation-behavior">Material
- *     Design Guidelines</a>
+ * href="https://material.io/guidelines/components/bottom-navigation.html#bottom-navigation-behavior">Material
+ * Design Guidelines</a>
  *
  * 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;
 

+ 0 - 1
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;

+ 20 - 20
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;

+ 8 - 16
app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.java

@@ -37,42 +37,34 @@ import lombok.Data;
 @JsonObject
 public class ChatMessage implements IMessage {
     String baseUrl;
-
-    public String getBaseUrl() {
-        return baseUrl;
-    }
-
-    public void setBaseUrl(String baseUrl) {
-        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<String, HashMap<String, String>> messageParameters;
 
+    public String getBaseUrl() {
+        return baseUrl;
+    }
+
+    public void setBaseUrl(String baseUrl) {
+        this.baseUrl = baseUrl;
+    }
+
     @Override
     public String getId() {
         return Integer.toString(jsonMessageId);

+ 2 - 1
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<ChatMessage> data;
 }

+ 28 - 0
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(),
+                    "<font color='" + color + "'><b>" + m.group() + "</b></font>"
+            );
+            m.appendReplacement(sb, Matcher.quoteReplacement(replacement));
+        }
+        m.appendTail(sb);
+
+        return sb.toString();
+    }
 }

+ 1 - 0
app/src/main/res/values/colors.xml

@@ -3,6 +3,7 @@
     <color name="colorPrimary">#0082C9</color>
     <color name="colorPrimaryDark">#006AA3</color>
     <color name="colorAccent">#007CC2</color>
+    <color name="colorAccentComplement">#C34700</color>
 
     <color name="nc_darkRed">#D32F2F</color>
     <color name="nc_darkGreen">#006400</color>