Browse Source

Add initial capabilities support

Signed-off-by: Mario Danic <mario@lovelyhq.com>
Mario Danic 7 years ago
parent
commit
ea35890f7e
23 changed files with 374 additions and 14 deletions
  1. 1 1
      app/build.gradle
  2. 1 1
      app/src/main/java/com/nextcloud/talk/activities/CallActivity.java
  3. 3 0
      app/src/main/java/com/nextcloud/talk/api/NcApi.java
  4. 17 1
      app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java
  5. 12 3
      app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java
  6. 1 1
      app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java
  7. 1 1
      app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java
  8. 1 1
      app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java
  9. 5 0
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/CallMenuController.java
  10. 1 1
      app/src/main/java/com/nextcloud/talk/dagger/modules/DatabaseModule.java
  11. 95 0
      app/src/main/java/com/nextcloud/talk/jobs/CapabilitiesJob.java
  12. 4 0
      app/src/main/java/com/nextcloud/talk/jobs/NotificationJob.java
  13. 3 0
      app/src/main/java/com/nextcloud/talk/jobs/creator/MagicJobCreator.java
  14. 22 0
      app/src/main/java/com/nextcloud/talk/models/database/User.java
  15. 36 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/Capabilities.java
  16. 36 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/CapabilitiesList.java
  17. 36 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/CapabilitiesOCS.java
  18. 35 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/CapabilitiesOverall.java
  19. 38 0
      app/src/main/java/com/nextcloud/talk/models/json/capabilities/SpreedCapability.java
  20. 4 0
      app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java
  21. 1 1
      app/src/main/java/com/nextcloud/talk/utils/PushUtils.java
  22. 1 0
      app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.java
  23. 20 3
      app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java

+ 1 - 1
app/build.gradle

@@ -123,7 +123,7 @@ dependencies {
     implementation 'org.webrtc:google-webrtc:1.0.21217'
     implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlinVersion}"
 
-    implementation 'com.evernote:android-job:1.2.0'
+    implementation 'com.evernote:android-job:1.2.4'
 
     implementation "com.google.android.gms:play-services-gcm:${googleLibraryVersion}"
     implementation "com.google.firebase:firebase-messaging:${googleLibraryVersion}"

+ 1 - 1
app/src/main/java/com/nextcloud/talk/activities/CallActivity.java

@@ -253,7 +253,7 @@ public class CallActivity extends AppCompatActivity {
         if (!userEntity.getCurrent()) {
             userUtils.createOrUpdateUser(null,
                     null, null, null,
-                    null, true, null, userEntity.getId())
+                    null, true, null, userEntity.getId(), null)
                     .subscribe(new Observer<UserEntity>() {
                         @Override
                         public void onSubscribe(Disposable d) {

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

@@ -23,6 +23,7 @@ package com.nextcloud.talk.api;
 import android.support.annotation.Nullable;
 
 import com.nextcloud.talk.models.json.call.CallOverall;
+import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall;
 import com.nextcloud.talk.models.json.generic.GenericOverall;
 import com.nextcloud.talk.models.json.generic.Status;
 import com.nextcloud.talk.models.json.participants.AddParticipantOverall;
@@ -253,4 +254,6 @@ public interface NcApi {
     Observable<GenericOverall> setPassword(@Header("Authorization") String authorization, @Url String url,
                                            @Field("password") String password);
 
+    @GET
+    Observable<CapabilitiesOverall> getCapabilities(@Header("Authorization") String authorization, @Url String url);
 }

+ 17 - 1
app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.java

@@ -36,6 +36,7 @@ import com.nextcloud.talk.dagger.modules.ContextModule;
 import com.nextcloud.talk.dagger.modules.DatabaseModule;
 import com.nextcloud.talk.dagger.modules.RestModule;
 import com.nextcloud.talk.jobs.AccountRemovalJob;
+import com.nextcloud.talk.jobs.CapabilitiesJob;
 import com.nextcloud.talk.jobs.PushRegistrationJob;
 import com.nextcloud.talk.jobs.creator.MagicJobCreator;
 import com.nextcloud.talk.utils.DisplayUtils;
@@ -49,6 +50,7 @@ import org.webrtc.voiceengine.WebRtcAudioManager;
 import org.webrtc.voiceengine.WebRtcAudioUtils;
 
 import java.security.GeneralSecurityException;
+import java.util.concurrent.TimeUnit;
 
 import javax.inject.Singleton;
 
@@ -132,7 +134,21 @@ public class NextcloudTalkApplication extends MultiDexApplication implements Pro
 
         new JobRequest.Builder(PushRegistrationJob.TAG).setUpdateCurrent(true).startNow().build().schedule();
         new JobRequest.Builder(AccountRemovalJob.TAG).setUpdateCurrent(true).startNow().build().schedule();
-
+        
+        boolean periodicJobFound = false;
+        for (JobRequest jobRequest : JobManager.instance().getAllJobRequestsForTag(CapabilitiesJob.TAG)) {
+            if (jobRequest.isPeriodic()) {
+                periodicJobFound = true;
+                break;
+            }
+        }
+        
+        if (!periodicJobFound) {
+            new JobRequest.Builder(CapabilitiesJob.TAG).setUpdateCurrent(true)
+                    .setPeriodic(TimeUnit.DAYS.toMillis(1), TimeUnit.HOURS.toMillis(1))
+                    .build().scheduleAsync();
+        }
+        new JobRequest.Builder(CapabilitiesJob.TAG).setUpdateCurrent(false).startNow().build().schedule();
     }
 
     @Override

+ 12 - 3
app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.java

@@ -34,10 +34,12 @@ import android.widget.TextView;
 import com.bluelinelabs.conductor.RouterTransaction;
 import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
 import com.evernote.android.job.JobRequest;
+import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.nextcloud.talk.R;
 import com.nextcloud.talk.api.NcApi;
 import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.controllers.base.BaseController;
+import com.nextcloud.talk.jobs.CapabilitiesJob;
 import com.nextcloud.talk.jobs.PushRegistrationJob;
 import com.nextcloud.talk.utils.ApiUtils;
 import com.nextcloud.talk.utils.ApplicationWideMessageHolder;
@@ -196,7 +198,7 @@ public class AccountVerificationController extends BaseController {
                                 if (!TextUtils.isEmpty(displayName)) {
                                     dbQueryDisposable = userUtils.createOrUpdateUser(username, token,
                                             baseUrl, displayName, null, true,
-                                            userProfileOverall.getOcs().getData().getUserId(), null)
+                                            userProfileOverall.getOcs().getData().getUserId(), null, null)
                                             .subscribeOn(Schedulers.newThread())
                                             .observeOn(AndroidSchedulers.mainThread())
                                             .subscribe(userEntity -> {
@@ -208,11 +210,18 @@ public class AccountVerificationController extends BaseController {
                                                         new JobRequest.Builder(PushRegistrationJob.TAG).
                                                                 setUpdateCurrent(true).startNow().build().schedule();
 
+                                                        PersistableBundleCompat persistableBundleCompat = new
+                                                                PersistableBundleCompat();
+                                                        persistableBundleCompat.putLong(BundleKeys
+                                                                .KEY_INTERNAL_USER_ID, userEntity.getId());
+
+                                                        new JobRequest.Builder(CapabilitiesJob.TAG).setUpdateCurrent
+                                                                (false).addExtras(persistableBundleCompat).startNow()
+                                                                .build().schedule();
+
                                                         cookieManager.getCookieStore().removeAll();
                                                         userUtils.disableAllUsersWithoutId(userEntity.getId());
 
-                                                        new JobRequest.Builder(PushRegistrationJob.TAG).setUpdateCurrent(true).startNow().build().schedule();
-
                                                         if (userUtils.getUsers().size() == 1) {
                                                             getRouter().setRoot(RouterTransaction.with(new
                                                                     MagicBottomNavigationController())

+ 1 - 1
app/src/main/java/com/nextcloud/talk/controllers/SettingsController.java

@@ -300,7 +300,7 @@ public class SettingsController extends BaseController {
                             dbQueryDisposable = userUtils.createOrUpdateUser(null,
                                     null,
                                     null, displayName, null, true,
-                                    userProfileOverall.getOcs().getData().getUserId(), userEntity.getId())
+                                    userProfileOverall.getOcs().getData().getUserId(), userEntity.getId(), null)
                                     .subscribeOn(Schedulers.newThread())
                                     .observeOn(AndroidSchedulers.mainThread())
                                     .subscribe(userEntityResult -> {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.java

@@ -99,7 +99,7 @@ public class SwitchAccountController extends BaseController {
                         UserEntity userEntity = ((AdvancedUserItem) userItems.get(position)).getEntity();
                         userUtils.createOrUpdateUser(null,
                                 null, null, null,
-                                null, true, null, userEntity.getId())
+                                null, true, null, userEntity.getId(), null)
                                 .subscribe(new Observer<UserEntity>() {
                                     @Override
                                     public void onSubscribe(Disposable d) {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.java

@@ -312,7 +312,7 @@ public class WebViewLoginController extends BaseController {
                         if (currentUser != null) {
                             userQueryDisposable = userUtils.createOrUpdateUser(null, null,
                                     null, null, null, true,
-                                    null, currentUser.getId()).
+                                    null, currentUser.getId(), null).
                                     subscribe(userEntity -> {
                                                 if (finalMessageType != null) {
                                                     ApplicationWideMessageHolder.getInstance().setMessageType(finalMessageType);

+ 5 - 0
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/CallMenuController.java

@@ -41,6 +41,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.controllers.ContactsController;
 import com.nextcloud.talk.controllers.base.BaseController;
 import com.nextcloud.talk.events.BottomSheetLockEvent;
+import com.nextcloud.talk.models.database.UserEntity;
 import com.nextcloud.talk.models.json.rooms.Room;
 import com.nextcloud.talk.utils.ShareUtils;
 import com.nextcloud.talk.utils.bundle.BundleKeys;
@@ -77,6 +78,8 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
     private FlexibleAdapter<AbstractFlexibleItem> adapter;
     private MenuType menuType;
     private Intent shareIntent;
+
+    private UserEntity currentUser;
     public CallMenuController(Bundle args) {
         super(args);
         this.room = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM));
@@ -94,6 +97,8 @@ public class CallMenuController extends BaseController implements FlexibleAdapte
     protected void onViewBound(@NonNull View view) {
         super.onViewBound(view);
         NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+
+        currentUser = userUtils.getCurrentUser();
         prepareViews();
     }
 

+ 1 - 1
app/src/main/java/com/nextcloud/talk/dagger/modules/DatabaseModule.java

@@ -49,7 +49,7 @@ public class DatabaseModule {
         return new SqlCipherDatabaseSource(context, Models.DEFAULT,
                 context.getResources().getString(R.string.nc_app_name).toLowerCase()
                         .replace(" ", "_").trim() + ".sqlite",
-                context.getString(R.string.nc_talk_database_encryption_key), 2);
+                context.getString(R.string.nc_talk_database_encryption_key), 3);
     }
 
     @Provides

+ 95 - 0
app/src/main/java/com/nextcloud/talk/jobs/CapabilitiesJob.java

@@ -0,0 +1,95 @@
+/*
+ * 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/>.
+ */
+
+package com.nextcloud.talk.jobs;
+
+import android.support.annotation.NonNull;
+
+import com.bluelinelabs.logansquare.LoganSquare;
+import com.evernote.android.job.Job;
+import com.nextcloud.talk.api.NcApi;
+import com.nextcloud.talk.application.NextcloudTalkApplication;
+import com.nextcloud.talk.models.database.UserEntity;
+import com.nextcloud.talk.utils.ApiUtils;
+import com.nextcloud.talk.utils.bundle.BundleKeys;
+import com.nextcloud.talk.utils.database.user.UserUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import autodagger.AutoInjector;
+import io.reactivex.schedulers.Schedulers;
+import okhttp3.JavaNetCookieJar;
+import okhttp3.OkHttpClient;
+import retrofit2.Retrofit;
+
+@AutoInjector(NextcloudTalkApplication.class)
+public class CapabilitiesJob extends Job {
+    public static final String TAG = "CapabilitiesJob";
+
+    @Inject
+    UserUtils userUtils;
+
+    @Inject
+    Retrofit retrofit;
+
+    @Inject
+    OkHttpClient okHttpClient;
+
+    NcApi ncApi;
+
+    @NonNull
+    @Override
+    protected Result onRunJob(Params params) {
+        NextcloudTalkApplication.getSharedApplication().getComponentApplication().inject(this);
+
+        long internalUserId = getParams().getExtras().getLong(BundleKeys.KEY_INTERNAL_USER_ID, -1);
+
+        UserEntity userEntity;
+        List userEntityObjectList = new ArrayList();
+
+        if (internalUserId == -1 || (userEntity = userUtils.getUserWithInternalId(internalUserId)) == null) {
+            userEntityObjectList = userUtils.getUsers();
+        } else {
+            userEntityObjectList.add(userEntity);
+        }
+
+        for (Object userEntityObject : userEntityObjectList) {
+            UserEntity internalUserEntity = (UserEntity) userEntityObject;
+
+            ncApi = retrofit.newBuilder().client(okHttpClient.newBuilder().cookieJar(new
+                    JavaNetCookieJar(new java.net.CookieManager())).build()).build().create(NcApi.class);
+
+            ncApi.getCapabilities(ApiUtils.getCredentials(internalUserEntity.getUsername(),
+                    internalUserEntity.getToken()), ApiUtils.getUrlForCapabilities(internalUserEntity.getBaseUrl()))
+                    .subscribeOn(Schedulers.newThread())
+                    .subscribe(capabilitiesOverall -> userUtils.createOrUpdateUser(null, null,
+                            null, null,
+                            null, null, null, internalUserEntity.getId(),
+                            LoganSquare.serialize(capabilitiesOverall.getOcs().getData().getCapabilities()))
+                            .subscribeOn(Schedulers.newThread())
+                            .subscribe());
+        }
+
+        return Result.SUCCESS;
+    }
+}

+ 4 - 0
app/src/main/java/com/nextcloud/talk/jobs/NotificationJob.java

@@ -41,6 +41,7 @@ import com.evernote.android.job.Job;
 import com.evernote.android.job.util.support.PersistableBundleCompat;
 import com.nextcloud.talk.R;
 import com.nextcloud.talk.activities.CallActivity;
+import com.nextcloud.talk.application.NextcloudTalkApplication;
 import com.nextcloud.talk.models.SignatureVerification;
 import com.nextcloud.talk.models.json.push.DecryptedPushMessage;
 import com.nextcloud.talk.models.json.push.PushMessage;
@@ -59,6 +60,9 @@ import java.util.zip.CRC32;
 import javax.crypto.Cipher;
 import javax.crypto.NoSuchPaddingException;
 
+import autodagger.AutoInjector;
+
+@AutoInjector(NextcloudTalkApplication.class)
 public class NotificationJob extends Job {
     public static final String TAG = "NotificationJob";
 

+ 3 - 0
app/src/main/java/com/nextcloud/talk/jobs/creator/MagicJobCreator.java

@@ -26,6 +26,7 @@ import android.support.annotation.Nullable;
 import com.evernote.android.job.Job;
 import com.evernote.android.job.JobCreator;
 import com.nextcloud.talk.jobs.AccountRemovalJob;
+import com.nextcloud.talk.jobs.CapabilitiesJob;
 import com.nextcloud.talk.jobs.NotificationJob;
 import com.nextcloud.talk.jobs.PushRegistrationJob;
 
@@ -42,6 +43,8 @@ public class MagicJobCreator implements JobCreator {
                 return new AccountRemovalJob();
             case NotificationJob.TAG:
                 return new NotificationJob();
+            case CapabilitiesJob.TAG:
+                return new CapabilitiesJob();
             default:
                 return null;
         }

+ 22 - 0
app/src/main/java/com/nextcloud/talk/models/database/User.java

@@ -20,7 +20,12 @@
 package com.nextcloud.talk.models.database;
 
 import android.os.Parcelable;
+import android.util.Log;
 
+import com.bluelinelabs.logansquare.LoganSquare;
+import com.nextcloud.talk.models.json.capabilities.Capabilities;
+
+import java.io.IOException;
 import java.io.Serializable;
 
 import io.requery.Entity;
@@ -30,6 +35,8 @@ import io.requery.Persistable;
 
 @Entity
 public interface User extends Parcelable, Persistable, Serializable {
+    static final String TAG = "UserEntity";
+
     @Key
     @Generated
     long getId();
@@ -46,7 +53,22 @@ public interface User extends Parcelable, Persistable, Serializable {
 
     String getPushConfigurationState();
 
+    String getCapabilities();
+
     boolean getCurrent();
 
     boolean getScheduledForDeletion();
+
+    default boolean checkForSpreedCapability(String capabilityName) {
+        try {
+            Capabilities capabilities = LoganSquare.parse(this.getCapabilities(), Capabilities.class);
+            if (capabilities.getSpreedCapability() != null && capabilities.getSpreedCapability().getFeatures() != null) {
+                return capabilities.getSpreedCapability().getFeatures().contains(capabilityName);
+            }
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to get capabilities for the user");
+        }
+
+        return false;
+    }
 }

+ 36 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/Capabilities.java

@@ -0,0 +1,36 @@
+/*
+ * 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/>.
+ */
+
+package com.nextcloud.talk.models.json.capabilities;
+
+import com.bluelinelabs.logansquare.annotation.JsonField;
+import com.bluelinelabs.logansquare.annotation.JsonObject;
+
+import org.parceler.Parcel;
+
+import lombok.Data;
+
+@Parcel
+@Data
+@JsonObject
+public class Capabilities {
+    @JsonField(name = "spreed")
+    SpreedCapability spreedCapability;
+}

+ 36 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/CapabilitiesList.java

@@ -0,0 +1,36 @@
+/*
+ * 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/>.
+ */
+
+package com.nextcloud.talk.models.json.capabilities;
+
+import com.bluelinelabs.logansquare.annotation.JsonField;
+import com.bluelinelabs.logansquare.annotation.JsonObject;
+
+import org.parceler.Parcel;
+
+import lombok.Data;
+
+@Parcel
+@Data
+@JsonObject
+public class CapabilitiesList {
+    @JsonField(name = "capabilities")
+    Capabilities capabilities;
+}

+ 36 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/CapabilitiesOCS.java

@@ -0,0 +1,36 @@
+/*
+ * 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/>.
+ */
+package com.nextcloud.talk.models.json.capabilities;
+
+import com.bluelinelabs.logansquare.annotation.JsonField;
+import com.bluelinelabs.logansquare.annotation.JsonObject;
+import com.nextcloud.talk.models.json.generic.GenericOCS;
+
+import org.parceler.Parcel;
+
+import lombok.Data;
+
+@Data
+@Parcel
+@JsonObject
+public class CapabilitiesOCS extends GenericOCS {
+    @JsonField(name = "data")
+    CapabilitiesList data;
+}

+ 35 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/CapabilitiesOverall.java

@@ -0,0 +1,35 @@
+/*
+ * 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/>.
+ */
+package com.nextcloud.talk.models.json.capabilities;
+
+import com.bluelinelabs.logansquare.annotation.JsonField;
+import com.bluelinelabs.logansquare.annotation.JsonObject;
+
+import org.parceler.Parcel;
+
+import lombok.Data;
+
+@Data
+@Parcel
+@JsonObject
+public class CapabilitiesOverall {
+    @JsonField(name = "ocs")
+    CapabilitiesOCS ocs;
+}

+ 38 - 0
app/src/main/java/com/nextcloud/talk/models/json/capabilities/SpreedCapability.java

@@ -0,0 +1,38 @@
+/*
+ * 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/>.
+ */
+
+package com.nextcloud.talk.models.json.capabilities;
+
+import com.bluelinelabs.logansquare.annotation.JsonField;
+import com.bluelinelabs.logansquare.annotation.JsonObject;
+
+import org.parceler.Parcel;
+
+import java.util.List;
+
+import lombok.Data;
+
+@Parcel
+@Data
+@JsonObject
+public class SpreedCapability {
+    @JsonField(name = "features")
+    List<String> features;
+}

+ 4 - 0
app/src/main/java/com/nextcloud/talk/utils/ApiUtils.java

@@ -61,6 +61,10 @@ public class ApiUtils {
         return getRoom(baseUrl, token) + "/participants/active";
     }
 
+    public static String getUrlForCapabilities(String baseUrl) {
+        return baseUrl + ocsApiVersion + "/cloud/capabilities";
+    }
+
     public static String getUrlForGetRooms(String baseUrl) {
         return baseUrl + ocsApiVersion + spreedApiVersion + "/room";
     }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/utils/PushUtils.java

@@ -304,7 +304,7 @@ public class PushUtils {
                                                                 null, null,
                                                                 userEntity.getDisplayName(),
                                                                 LoganSquare.serialize(pushConfigurationState), null,
-                                                                null, userEntity.getId())
+                                                                null, userEntity.getId(), null)
                                                                 .subscribe(new Consumer<UserEntity>() {
                                                                     @Override
                                                                     public void accept(UserEntity userEntity) throws Exception {

+ 1 - 0
app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.java

@@ -42,4 +42,5 @@ public class BundleKeys {
     public static final String KEY_MODIFIED_BASE_URL = "KEY_MODIFIED_BASE_URL";
     public static final String KEY_NOTIFICATION_SUBJECT = "KEY_NOTIFICATION_SUBJECT";
     public static final String KEY_NOTIFICATION_SIGNATURE = "KEY_NOTIFICATION_SIGNATURE";
+    public static final String KEY_INTERNAL_USER_ID = "KEY_INTERNAL_USER_ID";
 }

+ 20 - 3
app/src/main/java/com/nextcloud/talk/utils/database/user/UserUtils.java

@@ -124,6 +124,14 @@ public class UserUtils {
 
     }
 
+    public UserEntity getUserWithInternalId(long internalId) {
+        Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.ID.eq(internalId)
+                .and(UserEntity.SCHEDULED_FOR_DELETION.notEqual(true)))
+                .limit(1).get();
+
+        return (UserEntity) findUserQueryResult.firstOrNull();
+    }
+
     public boolean getIfUserWithUsernameAndServer(String username, String server) {
         Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.USERNAME.eq(username)
                 .and(UserEntity.BASE_URL.eq(server)))
@@ -147,13 +155,14 @@ public class UserUtils {
 
     }
 
-    public Observable<UserEntity> createOrUpdateUser(@Nullable String username, @Nullable String token, @Nullable String
-            serverUrl,
+    public Observable<UserEntity> createOrUpdateUser(@Nullable String username, @Nullable String token,
+                                                     @Nullable String serverUrl,
                                                      @Nullable String displayName,
                                                      @Nullable String pushConfigurationState,
                                                      @Nullable Boolean currentUser,
                                                      @Nullable String userId,
-                                                     @Nullable Long internalId) {
+                                                     @Nullable Long internalId,
+                                                     @Nullable String capabilities) {
         Result findUserQueryResult;
         if (internalId == null) {
             findUserQueryResult = dataStore.select(User.class).where(UserEntity.USERNAME.eq(username).
@@ -182,6 +191,10 @@ public class UserUtils {
                 user.setUserId(userId);
             }
 
+            if (!TextUtils.isEmpty(capabilities)) {
+                user.setCapabilities(capabilities);
+            }
+
             user.setCurrent(true);
 
         } else {
@@ -202,6 +215,10 @@ public class UserUtils {
                 user.setPushConfigurationState(pushConfigurationState);
             }
 
+            if (capabilities != null && !capabilities.equals(user.getCapabilities())) {
+                user.setCapabilities(capabilities);
+            }
+
             if (currentUser != null) {
                 user.setCurrent(currentUser);
             }