mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-14 16:25:05 +01:00
Compiles again
This commit is contained in:
parent
243fa2aad9
commit
ebe96f1f99
@ -2,7 +2,7 @@
|
|||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"identityHash": "95ddaea30271abd3160e1cdc8ab404d5",
|
"identityHash": "26585a95894baebb7d811a80f3811b85",
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"tableName": "conversations",
|
"tableName": "conversations",
|
||||||
@ -261,7 +261,16 @@
|
|||||||
],
|
],
|
||||||
"autoGenerate": false
|
"autoGenerate": false
|
||||||
},
|
},
|
||||||
"indices": [],
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_messages_conversation_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"conversation_id"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX IF NOT EXISTS `index_messages_conversation_id` ON `${TABLE_NAME}` (`conversation_id`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
"foreignKeys": [
|
"foreignKeys": [
|
||||||
{
|
{
|
||||||
"table": "conversations",
|
"table": "conversations",
|
||||||
@ -360,7 +369,7 @@
|
|||||||
"views": [],
|
"views": [],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '95ddaea30271abd3160e1cdc8ab404d5')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '26585a95894baebb7d811a80f3811b85')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,7 +26,6 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import autodagger.AutoInjector
|
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.ButterKnife
|
import butterknife.ButterKnife
|
||||||
import com.bluelinelabs.conductor.Conductor
|
import com.bluelinelabs.conductor.Conductor
|
||||||
@ -40,7 +39,6 @@ import com.nextcloud.talk.controllers.CallNotificationController
|
|||||||
import com.nextcloud.talk.events.ConfigurationChangeEvent
|
import com.nextcloud.talk.events.ConfigurationChangeEvent
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
class MagicCallActivity : BaseActivity() {
|
class MagicCallActivity : BaseActivity() {
|
||||||
|
|
||||||
@BindView(R.id.controller_container)
|
@BindView(R.id.controller_container)
|
||||||
@ -50,7 +48,6 @@ class MagicCallActivity : BaseActivity() {
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
|
||||||
|
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
window.addFlags(
|
window.addFlags(
|
||||||
|
@ -30,7 +30,6 @@ import coil.api.load
|
|||||||
import coil.transform.CircleCropTransformation
|
import coil.transform.CircleCropTransformation
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
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.models.json.chat.ChatMessage
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.ONE_TO_ONE_CONVERSATION
|
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.ONE_TO_ONE_CONVERSATION
|
||||||
|
@ -1,344 +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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.components.filebrowser.controllers;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.work.Data;
|
|
||||||
import androidx.work.OneTimeWorkRequest;
|
|
||||||
import androidx.work.WorkManager;
|
|
||||||
import autodagger.AutoInjector;
|
|
||||||
import butterknife.BindView;
|
|
||||||
import butterknife.OnClick;
|
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationItemView;
|
|
||||||
import com.nextcloud.talk.R;
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
|
||||||
import com.nextcloud.talk.components.filebrowser.adapters.items.BrowserFileItem;
|
|
||||||
import com.nextcloud.talk.components.filebrowser.interfaces.ListingInterface;
|
|
||||||
import com.nextcloud.talk.components.filebrowser.models.BrowserFile;
|
|
||||||
import com.nextcloud.talk.components.filebrowser.models.DavResponse;
|
|
||||||
import com.nextcloud.talk.components.filebrowser.operations.DavListing;
|
|
||||||
import com.nextcloud.talk.components.filebrowser.operations.ListingAbstractClass;
|
|
||||||
import com.nextcloud.talk.controllers.base.BaseController;
|
|
||||||
import com.nextcloud.talk.interfaces.SelectionInterface;
|
|
||||||
import com.nextcloud.talk.jobs.ShareOperationWorker;
|
|
||||||
import com.nextcloud.talk.models.database.UserEntity;
|
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity;
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
|
||||||
import eu.davidea.fastscroller.FastScroller;
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
|
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
|
|
||||||
import eu.davidea.flexibleadapter.items.IFlexible;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import org.parceler.Parcel;
|
|
||||||
import org.parceler.Parcels;
|
|
||||||
|
|
||||||
public class BrowserController extends BaseController implements ListingInterface,
|
|
||||||
FlexibleAdapter.OnItemClickListener, SelectionInterface {
|
|
||||||
private final Set<String> selectedPaths;
|
|
||||||
@BindView(R.id.recyclerView)
|
|
||||||
RecyclerView recyclerView;
|
|
||||||
@BindView(R.id.fast_scroller)
|
|
||||||
FastScroller fastScroller;
|
|
||||||
@BindView(R.id.action_back)
|
|
||||||
BottomNavigationItemView backMenuItem;
|
|
||||||
@BindView(R.id.action_refresh)
|
|
||||||
BottomNavigationItemView actionRefreshMenuItem;
|
|
||||||
@Inject
|
|
||||||
OkHttpClient okHttpClient;
|
|
||||||
|
|
||||||
private MenuItem filesSelectionDoneMenuItem;
|
|
||||||
private RecyclerView.LayoutManager layoutManager;
|
|
||||||
|
|
||||||
private FlexibleAdapter<AbstractFlexibleItem> adapter;
|
|
||||||
private List<AbstractFlexibleItem> recyclerViewItems = new ArrayList<>();
|
|
||||||
|
|
||||||
private ListingAbstractClass listingAbstractClass;
|
|
||||||
private BrowserType browserType;
|
|
||||||
private String currentPath;
|
|
||||||
private UserNgEntity activeUser;
|
|
||||||
private String roomToken;
|
|
||||||
|
|
||||||
public BrowserController(Bundle args) {
|
|
||||||
super();
|
|
||||||
setHasOptionsMenu(true);
|
|
||||||
browserType = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_BROWSER_TYPE()));
|
|
||||||
activeUser = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY()));
|
|
||||||
roomToken = args.getString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN());
|
|
||||||
|
|
||||||
currentPath = "/";
|
|
||||||
if (BrowserType.DAV_BROWSER.equals(browserType)) {
|
|
||||||
listingAbstractClass = new DavListing(this);
|
|
||||||
} else {
|
|
||||||
//listingAbstractClass = new LocalListing(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedPaths = Collections.synchronizedSet(new TreeSet<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
|
||||||
return inflater.inflate(R.layout.controller_browser, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onViewBound(@NonNull View view) {
|
|
||||||
super.onViewBound(view);
|
|
||||||
if (adapter == null) {
|
|
||||||
adapter = new FlexibleAdapter<>(recyclerViewItems, context, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
changeEnabledStatusForBarItems(true);
|
|
||||||
prepareViews();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onFileSelectionDone() {
|
|
||||||
synchronized (selectedPaths) {
|
|
||||||
Iterator<String> iterator = selectedPaths.iterator();
|
|
||||||
|
|
||||||
List<String> paths = new ArrayList<>();
|
|
||||||
Data data;
|
|
||||||
OneTimeWorkRequest shareWorker;
|
|
||||||
|
|
||||||
while (iterator.hasNext()) {
|
|
||||||
String path = iterator.next();
|
|
||||||
paths.add(path);
|
|
||||||
iterator.remove();
|
|
||||||
if (paths.size() == 10 || !iterator.hasNext()) {
|
|
||||||
data = new Data.Builder()
|
|
||||||
.putLong(BundleKeys.INSTANCE.getKEY_INTERNAL_USER_ID(), activeUser.getId())
|
|
||||||
.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), roomToken)
|
|
||||||
.putStringArray(BundleKeys.INSTANCE.getKEY_FILE_PATHS(), paths.toArray(new String[0]))
|
|
||||||
.build();
|
|
||||||
shareWorker = new OneTimeWorkRequest.Builder(ShareOperationWorker.class)
|
|
||||||
.setInputData(data)
|
|
||||||
.build();
|
|
||||||
WorkManager.getInstance().enqueue(shareWorker);
|
|
||||||
paths = new ArrayList<>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getRouter().popCurrentController();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
|
||||||
inflater.inflate(R.menu.menu_share_files, menu);
|
|
||||||
filesSelectionDoneMenuItem = menu.findItem(R.id.files_selection_done);
|
|
||||||
filesSelectionDoneMenuItem.setVisible(selectedPaths.size() > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case R.id.files_selection_done:
|
|
||||||
onFileSelectionDone();
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onAttach(@NonNull View view) {
|
|
||||||
super.onAttach(view);
|
|
||||||
refreshCurrentPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
listingAbstractClass.tearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTitle() {
|
|
||||||
return currentPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.action_back)
|
|
||||||
void goBack() {
|
|
||||||
fetchPath(new File(currentPath).getParent());
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.action_refresh)
|
|
||||||
void refreshCurrentPath() {
|
|
||||||
fetchPath(currentPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("RestrictedApi")
|
|
||||||
private void changeEnabledStatusForBarItems(boolean shouldBeEnabled) {
|
|
||||||
if (actionRefreshMenuItem != null) {
|
|
||||||
actionRefreshMenuItem.setEnabled(shouldBeEnabled);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (backMenuItem != null) {
|
|
||||||
backMenuItem.setEnabled(shouldBeEnabled && !currentPath.equals("/"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fetchPath(String path) {
|
|
||||||
listingAbstractClass.cancelAllJobs();
|
|
||||||
changeEnabledStatusForBarItems(false);
|
|
||||||
|
|
||||||
listingAbstractClass.getFiles(path, activeUser,
|
|
||||||
BrowserType.DAV_BROWSER.equals(browserType) ? okHttpClient : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void listingResult(DavResponse davResponse) {
|
|
||||||
adapter.clear();
|
|
||||||
List<AbstractFlexibleItem> fileBrowserItems = new ArrayList<>();
|
|
||||||
if (davResponse.getData() != null) {
|
|
||||||
final List<BrowserFile> objectList = (List<BrowserFile>) davResponse.getData();
|
|
||||||
|
|
||||||
currentPath = objectList.get(0).getPath();
|
|
||||||
|
|
||||||
if (getActivity() != null) {
|
|
||||||
getActivity().runOnUiThread(() -> setTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i < objectList.size(); i++) {
|
|
||||||
fileBrowserItems.add(new BrowserFileItem(objectList.get(i), activeUser, this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.addItems(0, fileBrowserItems);
|
|
||||||
|
|
||||||
if (getActivity() != null) {
|
|
||||||
getActivity().runOnUiThread(() -> {
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
changeEnabledStatusForBarItems(true);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean shouldPathBeSelectedDueToParent(String currentPath) {
|
|
||||||
if (selectedPaths.size() > 0) {
|
|
||||||
File file = new File(currentPath);
|
|
||||||
if (!file.getParent().equals("/")) {
|
|
||||||
while (file.getParent() != null) {
|
|
||||||
String parent = file.getParent();
|
|
||||||
if (new File(file.getParent()).getParent() != null) {
|
|
||||||
parent += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedPaths.contains(parent)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
file = new File(file.getParent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkAndRemoveAnySelectedParents(String currentPath) {
|
|
||||||
File file = new File(currentPath);
|
|
||||||
selectedPaths.remove(currentPath);
|
|
||||||
while (file.getParent() != null) {
|
|
||||||
selectedPaths.remove(file.getParent() + "/");
|
|
||||||
file = new File(file.getParent());
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onItemClick(View view, int position) {
|
|
||||||
BrowserFile browserFile = ((BrowserFileItem) adapter.getItem(position)).getModel();
|
|
||||||
if ("inode/directory".equals((browserFile.getMimeType()))) {
|
|
||||||
fetchPath(browserFile.getPath());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareViews() {
|
|
||||||
if (getActivity() != null) {
|
|
||||||
layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
|
|
||||||
recyclerView.setLayoutManager(layoutManager);
|
|
||||||
recyclerView.setHasFixedSize(true);
|
|
||||||
recyclerView.setAdapter(adapter);
|
|
||||||
|
|
||||||
adapter.setFastScroller(fastScroller);
|
|
||||||
adapter.addListener(this);
|
|
||||||
|
|
||||||
fastScroller.setBubbleTextCreator(position -> {
|
|
||||||
IFlexible abstractFlexibleItem = adapter.getItem(position);
|
|
||||||
if (abstractFlexibleItem instanceof BrowserFileItem) {
|
|
||||||
return String.valueOf(
|
|
||||||
((BrowserFileItem) adapter.getItem(position)).getModel().getDisplayName().charAt(0));
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("RestrictedApi")
|
|
||||||
@Override
|
|
||||||
public void toggleBrowserItemSelection(String path) {
|
|
||||||
if (selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path)) {
|
|
||||||
checkAndRemoveAnySelectedParents(path);
|
|
||||||
} else {
|
|
||||||
// TOOD: if it's a folder, remove all the children we added manually
|
|
||||||
selectedPaths.add(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
filesSelectionDoneMenuItem.setVisible(selectedPaths.size() > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isPathSelected(String path) {
|
|
||||||
return (selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Parcel
|
|
||||||
public enum BrowserType {
|
|
||||||
FILE_BROWSER,
|
|
||||||
DAV_BROWSER,
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,313 @@
|
|||||||
|
/*
|
||||||
|
* 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.components.filebrowser.controllers
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.*
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.work.Data
|
||||||
|
import androidx.work.OneTimeWorkRequest
|
||||||
|
import androidx.work.WorkManager
|
||||||
|
import butterknife.BindView
|
||||||
|
import butterknife.OnClick
|
||||||
|
import com.google.android.material.bottomnavigation.BottomNavigationItemView
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.components.filebrowser.adapters.items.BrowserFileItem
|
||||||
|
import com.nextcloud.talk.components.filebrowser.interfaces.ListingInterface
|
||||||
|
import com.nextcloud.talk.components.filebrowser.models.BrowserFile
|
||||||
|
import com.nextcloud.talk.components.filebrowser.models.DavResponse
|
||||||
|
import com.nextcloud.talk.components.filebrowser.operations.DavListing
|
||||||
|
import com.nextcloud.talk.components.filebrowser.operations.ListingAbstractClass
|
||||||
|
import com.nextcloud.talk.controllers.base.BaseController
|
||||||
|
import com.nextcloud.talk.interfaces.SelectionInterface
|
||||||
|
import com.nextcloud.talk.jobs.ShareOperationWorker
|
||||||
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
|
import eu.davidea.fastscroller.FastScroller
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import org.koin.android.ext.android.inject
|
||||||
|
import org.parceler.Parcel
|
||||||
|
import org.parceler.Parcels
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class BrowserController(args: Bundle) : BaseController(), ListingInterface, FlexibleAdapter.OnItemClickListener, SelectionInterface {
|
||||||
|
private val selectedPaths: MutableSet<String>
|
||||||
|
@JvmField @BindView(R.id.recyclerView)
|
||||||
|
internal var recyclerView: RecyclerView? = null
|
||||||
|
@JvmField @BindView(R.id.fast_scroller)
|
||||||
|
internal var fastScroller: FastScroller? = null
|
||||||
|
@JvmField @BindView(R.id.action_back)
|
||||||
|
internal var backMenuItem: BottomNavigationItemView? = null
|
||||||
|
@JvmField @BindView(R.id.action_refresh)
|
||||||
|
internal var actionRefreshMenuItem: BottomNavigationItemView? = null
|
||||||
|
|
||||||
|
val okHttpClient:OkHttpClient by inject()
|
||||||
|
|
||||||
|
private var filesSelectionDoneMenuItem: MenuItem? = null
|
||||||
|
private var layoutManager: RecyclerView.LayoutManager? = null
|
||||||
|
|
||||||
|
private var adapter: FlexibleAdapter<AbstractFlexibleItem<*>>? = null
|
||||||
|
private val recyclerViewItems = ArrayList<AbstractFlexibleItem<*>>()
|
||||||
|
|
||||||
|
private var listingAbstractClass: ListingAbstractClass? = null
|
||||||
|
private val browserType: BrowserType
|
||||||
|
private var currentPath: String? = null
|
||||||
|
private val activeUser: UserNgEntity
|
||||||
|
private val roomToken: String?
|
||||||
|
|
||||||
|
init {
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
browserType = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_BROWSER_TYPE))
|
||||||
|
activeUser = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_USER_ENTITY))
|
||||||
|
roomToken = args.getString(BundleKeys.KEY_ROOM_TOKEN)
|
||||||
|
|
||||||
|
currentPath = "/"
|
||||||
|
if (BrowserType.DAV_BROWSER == browserType) {
|
||||||
|
listingAbstractClass = DavListing(this)
|
||||||
|
} else {
|
||||||
|
//listingAbstractClass = new LocalListing(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedPaths = Collections.synchronizedSet(TreeSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||||
|
return inflater.inflate(R.layout.controller_browser, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewBound(view: View) {
|
||||||
|
super.onViewBound(view)
|
||||||
|
if (adapter == null) {
|
||||||
|
adapter = FlexibleAdapter(recyclerViewItems, context, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
changeEnabledStatusForBarItems(true)
|
||||||
|
prepareViews()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onFileSelectionDone() {
|
||||||
|
synchronized(selectedPaths) {
|
||||||
|
val iterator = selectedPaths.iterator()
|
||||||
|
|
||||||
|
var paths: MutableList<String> = ArrayList()
|
||||||
|
var data: Data
|
||||||
|
var shareWorker: OneTimeWorkRequest
|
||||||
|
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
val path = iterator.next()
|
||||||
|
paths.add(path)
|
||||||
|
iterator.remove()
|
||||||
|
if (paths.size == 10 || !iterator.hasNext()) {
|
||||||
|
data = Data.Builder()
|
||||||
|
.putLong(BundleKeys.KEY_INTERNAL_USER_ID, activeUser.id!!)
|
||||||
|
.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken)
|
||||||
|
.putStringArray(BundleKeys.KEY_FILE_PATHS, paths.toTypedArray())
|
||||||
|
.build()
|
||||||
|
shareWorker = OneTimeWorkRequest.Builder(ShareOperationWorker::class.java)
|
||||||
|
.setInputData(data)
|
||||||
|
.build()
|
||||||
|
WorkManager.getInstance().enqueue(shareWorker)
|
||||||
|
paths = ArrayList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
router.popCurrentController()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||||
|
super.onCreateOptionsMenu(menu, inflater)
|
||||||
|
inflater.inflate(R.menu.menu_share_files, menu)
|
||||||
|
filesSelectionDoneMenuItem = menu.findItem(R.id.files_selection_done)
|
||||||
|
filesSelectionDoneMenuItem!!.isVisible = selectedPaths.size > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.files_selection_done -> {
|
||||||
|
onFileSelectionDone()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else -> return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAttach(view: View) {
|
||||||
|
super.onAttach(view)
|
||||||
|
refreshCurrentPath()
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
listingAbstractClass!!.tearDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTitle(): String? {
|
||||||
|
return currentPath
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.action_back)
|
||||||
|
internal fun goBack() {
|
||||||
|
fetchPath(File(currentPath!!).parent)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.action_refresh)
|
||||||
|
internal fun refreshCurrentPath() {
|
||||||
|
fetchPath(currentPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
|
private fun changeEnabledStatusForBarItems(shouldBeEnabled: Boolean) {
|
||||||
|
if (actionRefreshMenuItem != null) {
|
||||||
|
actionRefreshMenuItem!!.isEnabled = shouldBeEnabled
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backMenuItem != null) {
|
||||||
|
backMenuItem!!.isEnabled = shouldBeEnabled && currentPath != "/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchPath(path: String?) {
|
||||||
|
listingAbstractClass!!.cancelAllJobs()
|
||||||
|
changeEnabledStatusForBarItems(false)
|
||||||
|
|
||||||
|
listingAbstractClass!!.getFiles(path, activeUser,
|
||||||
|
if (BrowserType.DAV_BROWSER == browserType) okHttpClient else null)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun listingResult(davResponse: DavResponse) {
|
||||||
|
adapter!!.clear()
|
||||||
|
val fileBrowserItems = ArrayList<AbstractFlexibleItem<*>>()
|
||||||
|
if (davResponse.data != null) {
|
||||||
|
val objectList = davResponse.data as List<BrowserFile>
|
||||||
|
|
||||||
|
currentPath = objectList[0].path
|
||||||
|
|
||||||
|
if (activity != null) {
|
||||||
|
activity!!.runOnUiThread { setTitle() }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i in 1 until objectList.size) {
|
||||||
|
fileBrowserItems.add(BrowserFileItem(objectList[i], activeUser, this))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter!!.addItems(0, fileBrowserItems)
|
||||||
|
|
||||||
|
if (activity != null) {
|
||||||
|
activity!!.runOnUiThread {
|
||||||
|
adapter!!.notifyDataSetChanged()
|
||||||
|
changeEnabledStatusForBarItems(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shouldPathBeSelectedDueToParent(currentPath: String): Boolean {
|
||||||
|
if (selectedPaths.size > 0) {
|
||||||
|
var file = File(currentPath)
|
||||||
|
if (file.parent != "/") {
|
||||||
|
while (file.parent != null) {
|
||||||
|
var parent = file.parent
|
||||||
|
if (File(file.parent!!).parent != null) {
|
||||||
|
parent += "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedPaths.contains(parent)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
file = File(file.parent!!)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkAndRemoveAnySelectedParents(currentPath: String) {
|
||||||
|
var file = File(currentPath)
|
||||||
|
selectedPaths.remove(currentPath)
|
||||||
|
while (file.parent != null) {
|
||||||
|
selectedPaths.remove(file.parent!! + "/")
|
||||||
|
file = File(file.parent!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter!!.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClick(view: View, position: Int): Boolean {
|
||||||
|
val browserFile = (adapter!!.getItem(position) as BrowserFileItem).model
|
||||||
|
if ("inode/directory" == browserFile.mimeType) {
|
||||||
|
fetchPath(browserFile.path)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepareViews() {
|
||||||
|
if (activity != null) {
|
||||||
|
layoutManager = SmoothScrollLinearLayoutManager(activity!!)
|
||||||
|
recyclerView!!.layoutManager = layoutManager
|
||||||
|
recyclerView!!.setHasFixedSize(true)
|
||||||
|
recyclerView!!.adapter = adapter
|
||||||
|
|
||||||
|
adapter!!.setFastScroller(fastScroller)
|
||||||
|
adapter!!.addListener(this)
|
||||||
|
|
||||||
|
fastScroller!!.setBubbleTextCreator { position ->
|
||||||
|
val abstractFlexibleItem = adapter!!.getItem(position)
|
||||||
|
if (abstractFlexibleItem is BrowserFileItem) {
|
||||||
|
(adapter!!.getItem(position) as BrowserFileItem).model.displayName.toCharArray()[0].toString()
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
|
override fun toggleBrowserItemSelection(path: String) {
|
||||||
|
if (selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path)) {
|
||||||
|
checkAndRemoveAnySelectedParents(path)
|
||||||
|
} else {
|
||||||
|
// TOOD: if it's a folder, remove all the children we added manually
|
||||||
|
selectedPaths.add(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
filesSelectionDoneMenuItem!!.isVisible = selectedPaths.size > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isPathSelected(path: String): Boolean {
|
||||||
|
return selectedPaths.contains(path) || shouldPathBeSelectedDueToParent(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parcel
|
||||||
|
enum class BrowserType {
|
||||||
|
FILE_BROWSER,
|
||||||
|
DAV_BROWSER
|
||||||
|
}
|
||||||
|
}
|
@ -22,8 +22,8 @@ package com.nextcloud.talk.components.filebrowser.webdav;
|
|||||||
|
|
||||||
import com.nextcloud.talk.components.filebrowser.models.BrowserFile;
|
import com.nextcloud.talk.components.filebrowser.models.BrowserFile;
|
||||||
import com.nextcloud.talk.components.filebrowser.models.DavResponse;
|
import com.nextcloud.talk.components.filebrowser.models.DavResponse;
|
||||||
import com.nextcloud.talk.dagger.modules.RestModule;
|
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity;
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity;
|
||||||
|
import com.nextcloud.talk.newarch.utils.NetworkUtils;
|
||||||
import com.nextcloud.talk.utils.ApiUtils;
|
import com.nextcloud.talk.utils.ApiUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -49,7 +49,7 @@ public class ReadFilesystemOperation {
|
|||||||
OkHttpClient.Builder okHttpClientBuilder = okHttpClient.newBuilder();
|
OkHttpClient.Builder okHttpClientBuilder = okHttpClient.newBuilder();
|
||||||
okHttpClientBuilder.followRedirects(false);
|
okHttpClientBuilder.followRedirects(false);
|
||||||
okHttpClientBuilder.followSslRedirects(false);
|
okHttpClientBuilder.followSslRedirects(false);
|
||||||
okHttpClientBuilder.authenticator(new RestModule.MagicAuthenticator(
|
okHttpClientBuilder.authenticator(new NetworkUtils.MagicAuthenticator(
|
||||||
ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()),
|
ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()),
|
||||||
"Authorization"));
|
"Authorization"));
|
||||||
this.okHttpClient = okHttpClientBuilder.build();
|
this.okHttpClient = okHttpClientBuilder.build();
|
||||||
|
@ -151,7 +151,7 @@ class AccountVerificationController(args: Bundle?) : BaseController(), KoinCompo
|
|||||||
queryUrl = "http://" + baseUrl + ApiUtils.getUrlPostfixForStatus()
|
queryUrl = "http://" + baseUrl + ApiUtils.getUrlPostfixForStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
ncApi!!.getServerStatus(queryUrl)
|
ncApi.getServerStatus(queryUrl)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.`as`<ObservableSubscribeProxy<Status>>(AutoDispose.autoDisposable(scopeProvider))
|
.`as`<ObservableSubscribeProxy<Status>>(AutoDispose.autoDisposable(scopeProvider))
|
||||||
@ -194,7 +194,7 @@ class AccountVerificationController(args: Bundle?) : BaseController(), KoinCompo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun findServerTalkApp(credentials: String?) {
|
private fun findServerTalkApp(credentials: String?) {
|
||||||
ncApi!!.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
|
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.`as`<ObservableSubscribeProxy<RoomsOverall>>(AutoDispose.autoDisposable(scopeProvider))
|
.`as`<ObservableSubscribeProxy<RoomsOverall>>(AutoDispose.autoDisposable(scopeProvider))
|
||||||
.subscribe(object : Observer<RoomsOverall> {
|
.subscribe(object : Observer<RoomsOverall> {
|
||||||
@ -250,7 +250,7 @@ class AccountVerificationController(args: Bundle?) : BaseController(), KoinCompo
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchProfile(credentials: String?) {
|
private fun fetchProfile(credentials: String?) {
|
||||||
ncApi!!.getUserProfile(credentials,
|
ncApi.getUserProfile(credentials,
|
||||||
ApiUtils.getUrlForUserProfile(baseUrl))
|
ApiUtils.getUrlForUserProfile(baseUrl))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.`as`<ObservableSubscribeProxy<UserProfileOverall>>(AutoDispose.autoDisposable(scopeProvider))
|
.`as`<ObservableSubscribeProxy<UserProfileOverall>>(AutoDispose.autoDisposable(scopeProvider))
|
||||||
|
@ -46,7 +46,7 @@ import android.widget.ProgressBar
|
|||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import autodagger.AutoInjector
|
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.OnClick
|
import butterknife.OnClick
|
||||||
import butterknife.OnLongClick
|
import butterknife.OnLongClick
|
||||||
@ -110,7 +110,6 @@ import java.util.HashMap
|
|||||||
import java.util.HashSet
|
import java.util.HashSet
|
||||||
import java.util.Objects
|
import java.util.Objects
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
|
||||||
import me.zhanghai.android.effortlesspermissions.AfterPermissionDenied
|
import me.zhanghai.android.effortlesspermissions.AfterPermissionDenied
|
||||||
import me.zhanghai.android.effortlesspermissions.EffortlessPermissions
|
import me.zhanghai.android.effortlesspermissions.EffortlessPermissions
|
||||||
import me.zhanghai.android.effortlesspermissions.OpenAppDetailsDialogFragment
|
import me.zhanghai.android.effortlesspermissions.OpenAppDetailsDialogFragment
|
||||||
@ -393,7 +392,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleFromNotification() {
|
private fun handleFromNotification() {
|
||||||
ncApi!!.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
|
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
|
||||||
.retry(3)
|
.retry(3)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -943,7 +942,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchSignalingSettings() {
|
private fun fetchSignalingSettings() {
|
||||||
ncApi!!.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(baseUrl))
|
ncApi.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(baseUrl))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.retry(3)
|
.retry(3)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -1046,7 +1045,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkCapabilities() {
|
private fun checkCapabilities() {
|
||||||
ncApi!!.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
|
ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
|
||||||
.retry(3)
|
.retry(3)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -1092,7 +1091,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun joinRoomAndCall() {
|
private fun joinRoomAndCall() {
|
||||||
ncApi!!.joinRoom(
|
ncApi.joinRoom(
|
||||||
credentials, ApiUtils.getUrlForSettingMyselfAsActiveParticipant(
|
credentials, ApiUtils.getUrlForSettingMyselfAsActiveParticipant(
|
||||||
baseUrl,
|
baseUrl,
|
||||||
roomToken
|
roomToken
|
||||||
@ -1131,7 +1130,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun performCall() {
|
private fun performCall() {
|
||||||
ncApi!!.joinCall(
|
ncApi.joinCall(
|
||||||
credentials,
|
credentials,
|
||||||
ApiUtils.getUrlForCall(baseUrl, roomToken)
|
ApiUtils.getUrlForCall(baseUrl, roomToken)
|
||||||
)
|
)
|
||||||
@ -1148,7 +1147,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
setCallState(CallStatus.ESTABLISHED)
|
setCallState(CallStatus.ESTABLISHED)
|
||||||
|
|
||||||
if (needsPing) {
|
if (needsPing) {
|
||||||
ncApi!!.pingCall(credentials, ApiUtils.getUrlForCallPing(baseUrl, roomToken))
|
ncApi.pingCall(credentials, ApiUtils.getUrlForCallPing(baseUrl, roomToken))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.repeatWhen { observable -> observable.delay(5000, TimeUnit.MILLISECONDS) }
|
.repeatWhen { observable -> observable.delay(5000, TimeUnit.MILLISECONDS) }
|
||||||
@ -1193,7 +1192,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!hasExternalSignalingServer) {
|
if (!hasExternalSignalingServer) {
|
||||||
ncApi!!.pullSignalingMessages(
|
ncApi.pullSignalingMessages(
|
||||||
credentials,
|
credentials,
|
||||||
ApiUtils.getUrlForSignaling(baseUrl, urlToken)
|
ApiUtils.getUrlForSignaling(baseUrl, urlToken)
|
||||||
)
|
)
|
||||||
@ -1393,7 +1392,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (magicPeerConnectionWrapper.peerConnection != null) {
|
if (magicPeerConnectionWrapper.peerConnection != null) {
|
||||||
magicPeerConnectionWrapper.peerConnection
|
magicPeerConnectionWrapper.peerConnection!!
|
||||||
.setRemoteDescription(
|
.setRemoteDescription(
|
||||||
magicPeerConnectionWrapper
|
magicPeerConnectionWrapper
|
||||||
.magicSdpObserver, sessionDescriptionWithPreferredCodec
|
.magicSdpObserver, sessionDescriptionWithPreferredCodec
|
||||||
@ -1474,7 +1473,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun hangupNetworkCalls(shutDownView: Boolean) {
|
private fun hangupNetworkCalls(shutDownView: Boolean) {
|
||||||
ncApi!!.leaveCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
|
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(object : Observer<GenericOverall> {
|
.subscribe(object : Observer<GenericOverall> {
|
||||||
@ -1509,7 +1508,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun leaveRoom(shutDownView: Boolean) {
|
private fun leaveRoom(shutDownView: Boolean) {
|
||||||
ncApi!!.leaveRoom(
|
ncApi.leaveRoom(
|
||||||
credentials,
|
credentials,
|
||||||
ApiUtils.getUrlForSettingMyselfAsActiveParticipant(baseUrl, roomToken)
|
ApiUtils.getUrlForSettingMyselfAsActiveParticipant(baseUrl, roomToken)
|
||||||
)
|
)
|
||||||
@ -1603,7 +1602,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getPeersForCall() {
|
private fun getPeersForCall() {
|
||||||
ncApi!!.getPeersForCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
|
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe(object : Observer<ParticipantsOverall> {
|
.subscribe(object : Observer<ParticipantsOverall> {
|
||||||
override fun onSubscribe(d: Disposable) {
|
override fun onSubscribe(d: Disposable) {
|
||||||
@ -1660,25 +1659,25 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
if (hasMCU && publisher) {
|
if (hasMCU && publisher) {
|
||||||
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
||||||
peerConnectionFactory!!,
|
peerConnectionFactory!!,
|
||||||
iceServers, sdpConstraintsForMCU, sessionId, callSession, localMediaStream, true, true,
|
iceServers, sdpConstraintsForMCU!!, sessionId, callSession, localMediaStream, true, true,
|
||||||
type
|
type
|
||||||
)
|
)
|
||||||
} else if (hasMCU) {
|
} else if (hasMCU) {
|
||||||
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
||||||
peerConnectionFactory!!,
|
peerConnectionFactory!!,
|
||||||
iceServers, sdpConstraints, sessionId, callSession, null, false, true, type
|
iceServers, sdpConstraints!!, sessionId, callSession, null, false, true, type
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if ("screen" != type) {
|
if ("screen" != type) {
|
||||||
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
||||||
peerConnectionFactory!!,
|
peerConnectionFactory!!,
|
||||||
iceServers, sdpConstraints, sessionId, callSession, localMediaStream, false, false,
|
iceServers, sdpConstraints!!, sessionId, callSession, localMediaStream, false, false,
|
||||||
type
|
type
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
||||||
peerConnectionFactory!!,
|
peerConnectionFactory!!,
|
||||||
iceServers, sdpConstraints, sessionId, callSession, null, false, false, type
|
iceServers, sdpConstraints!!, sessionId, callSession, null, false, false, type
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1943,7 +1942,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
urlToken = roomToken
|
urlToken = roomToken
|
||||||
}
|
}
|
||||||
|
|
||||||
ncApi!!.sendSignalingMessages(
|
ncApi.sendSignalingMessages(
|
||||||
credentials, ApiUtils.getUrlForSignaling(baseUrl, urlToken),
|
credentials, ApiUtils.getUrlForSignaling(baseUrl, urlToken),
|
||||||
strings.toString()
|
strings.toString()
|
||||||
)
|
)
|
||||||
@ -2134,7 +2133,7 @@ class CallController(args: Bundle) : BaseController() {
|
|||||||
} else {
|
} else {
|
||||||
gotNick(
|
gotNick(
|
||||||
session,
|
session,
|
||||||
getPeerConnectionWrapperForSessionIdAndType(session, type, false).nick, false,
|
getPeerConnectionWrapperForSessionIdAndType(session, type, false).nick!!, false,
|
||||||
type
|
type
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkIfAnyParticipantsRemainInRoom() {
|
private fun checkIfAnyParticipantsRemainInRoom() {
|
||||||
ncApi!!.getPeersForCall(
|
ncApi.getPeersForCall(
|
||||||
credentials, ApiUtils.getUrlForParticipants(
|
credentials, ApiUtils.getUrlForParticipants(
|
||||||
userBeingCalled!!.baseUrl,
|
userBeingCalled!!.baseUrl,
|
||||||
currentConversation!!.token
|
currentConversation!!.token
|
||||||
@ -232,7 +232,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleFromNotification() {
|
private fun handleFromNotification() {
|
||||||
ncApi!!.getRooms(credentials, ApiUtils.getUrlForGetRooms(userBeingCalled!!.baseUrl))
|
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(userBeingCalled!!.baseUrl))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.retry(3)
|
.retry(3)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
@ -401,8 +401,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
|||||||
transformations(CircleCropTransformation())
|
transformations(CircleCropTransformation())
|
||||||
listener(onSuccess = { data, dataSource ->
|
listener(onSuccess = { data, dataSource ->
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
if ((AvatarStatusCodeHolder.getInstance().statusCode == 200 || AvatarStatusCodeHolder.getInstance().statusCode == 0)
|
if ((AvatarStatusCodeHolder.getInstance().statusCode == 200 || AvatarStatusCodeHolder.getInstance().statusCode == 0)) {
|
||||||
&& userBeingCalled.hasSpreedFeatureCapability("no-ping")) {
|
|
||||||
|
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
val newBitmap = BlurTransformation(activity!!, 5f).transform(
|
val newBitmap = BlurTransformation(activity!!, 5f).transform(
|
||||||
|
@ -46,7 +46,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|||||||
import androidx.work.Data
|
import androidx.work.Data
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import autodagger.AutoInjector
|
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.OnClick
|
import butterknife.OnClick
|
||||||
import butterknife.Optional
|
import butterknife.Optional
|
||||||
@ -99,7 +99,6 @@ import java.util.ArrayList
|
|||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
import java.util.HashSet
|
import java.util.HashSet
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class ContactsController : BaseController,
|
class ContactsController : BaseController,
|
||||||
SearchView.OnQueryTextListener,
|
SearchView.OnQueryTextListener,
|
||||||
@ -222,9 +221,6 @@ class ContactsController : BaseController,
|
|||||||
|
|
||||||
override fun onViewBound(view: View) {
|
override fun onViewBound(view: View) {
|
||||||
super.onViewBound(view)
|
super.onViewBound(view)
|
||||||
NextcloudTalkApplication.sharedApplication!!
|
|
||||||
.componentApplication
|
|
||||||
.inject(this)
|
|
||||||
|
|
||||||
currentUser = usersRepository.getActiveUser()
|
currentUser = usersRepository.getActiveUser()
|
||||||
|
|
||||||
@ -278,7 +274,7 @@ class ContactsController : BaseController,
|
|||||||
currentUser!!.baseUrl, roomType,
|
currentUser!!.baseUrl, roomType,
|
||||||
userId, null
|
userId, null
|
||||||
)
|
)
|
||||||
ncApi!!.createRoom(
|
ncApi.createRoom(
|
||||||
credentials,
|
credentials,
|
||||||
retrofitBucket.url, retrofitBucket.queryMap
|
retrofitBucket.url, retrofitBucket.queryMap
|
||||||
)
|
)
|
||||||
@ -304,7 +300,7 @@ class ContactsController : BaseController,
|
|||||||
)
|
)
|
||||||
|
|
||||||
if (currentUser!!.hasSpreedFeatureCapability("chat-v2")) {
|
if (currentUser!!.hasSpreedFeatureCapability("chat-v2")) {
|
||||||
ncApi!!.getRoom(
|
ncApi.getRoom(
|
||||||
credentials,
|
credentials,
|
||||||
ApiUtils.getRoom(
|
ApiUtils.getRoom(
|
||||||
currentUser!!.baseUrl,
|
currentUser!!.baseUrl,
|
||||||
@ -509,7 +505,7 @@ class ContactsController : BaseController,
|
|||||||
}
|
}
|
||||||
|
|
||||||
val finalServerIs14OrUp = serverIs14OrUp
|
val finalServerIs14OrUp = serverIs14OrUp
|
||||||
ncApi!!.getContactsWithSearchParam(
|
ncApi.getContactsWithSearchParam(
|
||||||
credentials,
|
credentials,
|
||||||
retrofitBucket.url, shareTypesList, modifiedQueryMap
|
retrofitBucket.url, shareTypesList, modifiedQueryMap
|
||||||
)
|
)
|
||||||
@ -854,7 +850,7 @@ class ContactsController : BaseController,
|
|||||||
userItem.model.userId, null
|
userItem.model.userId, null
|
||||||
)
|
)
|
||||||
|
|
||||||
ncApi!!.createRoom(
|
ncApi.createRoom(
|
||||||
credentials,
|
credentials,
|
||||||
retrofitBucket.url, retrofitBucket.queryMap
|
retrofitBucket.url, retrofitBucket.queryMap
|
||||||
)
|
)
|
||||||
|
@ -38,7 +38,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import androidx.work.Data
|
import androidx.work.Data
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import autodagger.AutoInjector
|
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.OnClick
|
import butterknife.OnClick
|
||||||
import coil.api.load
|
import coil.api.load
|
||||||
@ -99,11 +99,10 @@ import io.reactivex.disposables.Disposable
|
|||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
import org.greenrobot.eventbus.ThreadMode
|
||||||
|
import org.koin.android.ext.android.inject
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
class ConversationInfoController(args: Bundle) : BaseController(),
|
class ConversationInfoController(args: Bundle) : BaseController(),
|
||||||
FlexibleAdapter.OnItemClickListener, ConversationInfoInterface {
|
FlexibleAdapter.OnItemClickListener, ConversationInfoInterface {
|
||||||
|
|
||||||
@ -168,10 +167,7 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
|||||||
@BindView(R.id.shareAction)
|
@BindView(R.id.shareAction)
|
||||||
lateinit var shareAction: MaterialStandardPreference
|
lateinit var shareAction: MaterialStandardPreference
|
||||||
|
|
||||||
@set:Inject
|
val ncApi: NcApi by inject()
|
||||||
lateinit var ncApi: NcApi
|
|
||||||
@set:Inject
|
|
||||||
lateinit var userUtils: UserUtils
|
|
||||||
|
|
||||||
private val conversationToken: String?
|
private val conversationToken: String?
|
||||||
private val conversationUser: UserNgEntity?
|
private val conversationUser: UserNgEntity?
|
||||||
@ -201,7 +197,6 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
setHasOptionsMenu(true)
|
setHasOptionsMenu(true)
|
||||||
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
|
|
||||||
conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY)
|
conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY)
|
||||||
conversationToken = args.getString(BundleKeys.KEY_ROOM_TOKEN)
|
conversationToken = args.getString(BundleKeys.KEY_ROOM_TOKEN)
|
||||||
credentials = ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token)
|
credentials = ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token)
|
||||||
|
@ -1,300 +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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.controllers;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.database.Cursor;
|
|
||||||
import android.media.MediaPlayer;
|
|
||||||
import android.media.RingtoneManager;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
|
|
||||||
import com.bluelinelabs.logansquare.LoganSquare;
|
|
||||||
import com.nextcloud.talk.R;
|
|
||||||
import com.nextcloud.talk.adapters.items.NotificationSoundItem;
|
|
||||||
import com.nextcloud.talk.controllers.base.BaseController;
|
|
||||||
import com.nextcloud.talk.models.RingtoneSettings;
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import butterknife.BindView;
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
|
||||||
import eu.davidea.flexibleadapter.SelectableAdapter;
|
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
|
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
|
|
||||||
|
|
||||||
public class RingtoneSelectionController extends BaseController
|
|
||||||
implements FlexibleAdapter.OnItemClickListener {
|
|
||||||
|
|
||||||
private static final String TAG = "RingtoneSelectionController";
|
|
||||||
|
|
||||||
@BindView(R.id.recyclerView)
|
|
||||||
RecyclerView recyclerView;
|
|
||||||
|
|
||||||
@BindView(R.id.swipe_refresh_layout)
|
|
||||||
SwipeRefreshLayout swipeRefreshLayout;
|
|
||||||
|
|
||||||
private FlexibleAdapter adapter;
|
|
||||||
private RecyclerView.AdapterDataObserver adapterDataObserver;
|
|
||||||
private List<AbstractFlexibleItem> abstractFlexibleItemList = new ArrayList<>();
|
|
||||||
|
|
||||||
private boolean callNotificationSounds;
|
|
||||||
private MediaPlayer mediaPlayer;
|
|
||||||
private Handler cancelMediaPlayerHandler;
|
|
||||||
|
|
||||||
public RingtoneSelectionController(Bundle args) {
|
|
||||||
super();
|
|
||||||
setHasOptionsMenu(true);
|
|
||||||
this.callNotificationSounds =
|
|
||||||
args.getBoolean(BundleKeys.INSTANCE.getKEY_ARE_CALL_SOUNDS(), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
|
||||||
return inflater.inflate(R.layout.controller_generic_rv, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onViewBound(@NonNull View view) {
|
|
||||||
super.onViewBound(view);
|
|
||||||
|
|
||||||
if (adapter == null) {
|
|
||||||
adapter = new FlexibleAdapter<>(abstractFlexibleItemList, getActivity(), false);
|
|
||||||
|
|
||||||
adapter.setNotifyChangeOfUnfilteredItems(true)
|
|
||||||
.setMode(SelectableAdapter.Mode.SINGLE);
|
|
||||||
|
|
||||||
adapter.addListener(this);
|
|
||||||
|
|
||||||
cancelMediaPlayerHandler = new Handler();
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.addListener(this);
|
|
||||||
prepareViews();
|
|
||||||
fetchNotificationSounds();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case android.R.id.home:
|
|
||||||
return getRouter().popCurrentController();
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareViews() {
|
|
||||||
RecyclerView.LayoutManager layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
|
|
||||||
recyclerView.setLayoutManager(layoutManager);
|
|
||||||
recyclerView.setHasFixedSize(true);
|
|
||||||
recyclerView.setAdapter(adapter);
|
|
||||||
|
|
||||||
adapterDataObserver = new RecyclerView.AdapterDataObserver() {
|
|
||||||
@Override
|
|
||||||
public void onChanged() {
|
|
||||||
super.onChanged();
|
|
||||||
findSelectedSound();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
adapter.registerAdapterDataObserver(adapterDataObserver);
|
|
||||||
swipeRefreshLayout.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("LongLogTag")
|
|
||||||
private void findSelectedSound() {
|
|
||||||
boolean foundDefault = false;
|
|
||||||
|
|
||||||
String preferencesString = null;
|
|
||||||
if ((callNotificationSounds && TextUtils.isEmpty(
|
|
||||||
(preferencesString = appPreferences.getCallRingtoneUri())))
|
|
||||||
|| (!callNotificationSounds && TextUtils.isEmpty((preferencesString = appPreferences
|
|
||||||
.getMessageRingtoneUri())))) {
|
|
||||||
adapter.toggleSelection(1);
|
|
||||||
foundDefault = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(preferencesString) && !foundDefault) {
|
|
||||||
try {
|
|
||||||
RingtoneSettings ringtoneSettings =
|
|
||||||
LoganSquare.parse(preferencesString, RingtoneSettings.class);
|
|
||||||
if (ringtoneSettings.getRingtoneUri() == null) {
|
|
||||||
adapter.toggleSelection(0);
|
|
||||||
} else if (ringtoneSettings.getRingtoneUri().toString().equals(getRingtoneString())) {
|
|
||||||
adapter.toggleSelection(1);
|
|
||||||
} else {
|
|
||||||
NotificationSoundItem notificationSoundItem;
|
|
||||||
for (int i = 2; i < adapter.getItemCount(); i++) {
|
|
||||||
notificationSoundItem = (NotificationSoundItem) adapter.getItem(i);
|
|
||||||
if (notificationSoundItem.getNotificationSoundUri()
|
|
||||||
.equals(ringtoneSettings.getRingtoneUri().toString())) {
|
|
||||||
adapter.toggleSelection(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Failed to parse ringtone settings");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.unregisterAdapterDataObserver(adapterDataObserver);
|
|
||||||
adapterDataObserver = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getRingtoneString() {
|
|
||||||
if (callNotificationSounds) {
|
|
||||||
return ("android.resource://" + context.getPackageName() +
|
|
||||||
"/raw/librem_by_feandesign_call");
|
|
||||||
} else {
|
|
||||||
return ("android.resource://" + context.getPackageName() + "/raw" +
|
|
||||||
"/librem_by_feandesign_message");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fetchNotificationSounds() {
|
|
||||||
abstractFlexibleItemList.add(
|
|
||||||
new NotificationSoundItem(getResources().getString(R.string.nc_settings_no_ringtone),
|
|
||||||
null));
|
|
||||||
abstractFlexibleItemList.add(new NotificationSoundItem(getResources()
|
|
||||||
.getString(R.string.nc_settings_default_ringtone), getRingtoneString()));
|
|
||||||
|
|
||||||
if (getActivity() != null) {
|
|
||||||
RingtoneManager manager = new RingtoneManager(getActivity());
|
|
||||||
|
|
||||||
if (callNotificationSounds) {
|
|
||||||
manager.setType(RingtoneManager.TYPE_RINGTONE);
|
|
||||||
} else {
|
|
||||||
manager.setType(RingtoneManager.TYPE_NOTIFICATION);
|
|
||||||
}
|
|
||||||
|
|
||||||
Cursor cursor = manager.getCursor();
|
|
||||||
|
|
||||||
NotificationSoundItem notificationSoundItem;
|
|
||||||
|
|
||||||
while (cursor.moveToNext()) {
|
|
||||||
String notificationTitle = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX);
|
|
||||||
String notificationUri = cursor.getString(RingtoneManager.URI_COLUMN_INDEX);
|
|
||||||
String completeNotificationUri = notificationUri + "/" + cursor.getString(RingtoneManager
|
|
||||||
.ID_COLUMN_INDEX);
|
|
||||||
|
|
||||||
notificationSoundItem =
|
|
||||||
new NotificationSoundItem(notificationTitle, completeNotificationUri);
|
|
||||||
|
|
||||||
abstractFlexibleItemList.add(notificationSoundItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.updateDataSet(abstractFlexibleItemList, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTitle() {
|
|
||||||
return getResources().getString(R.string.nc_settings_notification_sounds);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("LongLogTag")
|
|
||||||
@Override
|
|
||||||
public boolean onItemClick(View view, int position) {
|
|
||||||
NotificationSoundItem notificationSoundItem = (NotificationSoundItem) adapter.getItem(position);
|
|
||||||
|
|
||||||
Uri ringtoneUri = null;
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(notificationSoundItem.getNotificationSoundUri())) {
|
|
||||||
ringtoneUri = Uri.parse(notificationSoundItem.getNotificationSoundUri());
|
|
||||||
|
|
||||||
endMediaPlayer();
|
|
||||||
mediaPlayer = MediaPlayer.create(getActivity(), ringtoneUri);
|
|
||||||
|
|
||||||
cancelMediaPlayerHandler = new Handler();
|
|
||||||
cancelMediaPlayerHandler.postDelayed(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
endMediaPlayer();
|
|
||||||
}
|
|
||||||
}, mediaPlayer.getDuration() + 25);
|
|
||||||
mediaPlayer.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adapter.getSelectedPositions().size() == 0
|
|
||||||
|| adapter.getSelectedPositions().get(0) != position) {
|
|
||||||
RingtoneSettings ringtoneSettings = new RingtoneSettings();
|
|
||||||
ringtoneSettings.setRingtoneName(notificationSoundItem.getNotificationSoundName());
|
|
||||||
ringtoneSettings.setRingtoneUri(ringtoneUri);
|
|
||||||
|
|
||||||
if (callNotificationSounds) {
|
|
||||||
try {
|
|
||||||
appPreferences.setCallRingtoneUri(LoganSquare.serialize(ringtoneSettings));
|
|
||||||
adapter.toggleSelection(position);
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Failed to store selected ringtone for calls");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
appPreferences.setMessageRingtoneUri(LoganSquare.serialize(ringtoneSettings));
|
|
||||||
adapter.toggleSelection(position);
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Failed to store selected ringtone for calls");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void endMediaPlayer() {
|
|
||||||
if (cancelMediaPlayerHandler != null) {
|
|
||||||
cancelMediaPlayerHandler.removeCallbacksAndMessages(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mediaPlayer != null) {
|
|
||||||
if (mediaPlayer.isPlaying()) {
|
|
||||||
mediaPlayer.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
mediaPlayer.release();
|
|
||||||
mediaPlayer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
endMediaPlayer();
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,281 @@
|
|||||||
|
/*
|
||||||
|
* 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.controllers
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.media.MediaPlayer
|
||||||
|
import android.media.RingtoneManager
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
|
||||||
|
import com.bluelinelabs.logansquare.LoganSquare
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.adapters.items.NotificationSoundItem
|
||||||
|
import com.nextcloud.talk.controllers.base.BaseController
|
||||||
|
import com.nextcloud.talk.models.RingtoneSettings
|
||||||
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
import butterknife.BindView
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.davidea.flexibleadapter.SelectableAdapter
|
||||||
|
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
|
|
||||||
|
class RingtoneSelectionController(args: Bundle) : BaseController(), FlexibleAdapter.OnItemClickListener {
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.recyclerView)
|
||||||
|
internal var recyclerView: RecyclerView? = null
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.swipe_refresh_layout)
|
||||||
|
internal var swipeRefreshLayout: SwipeRefreshLayout? = null
|
||||||
|
|
||||||
|
private var adapter: FlexibleAdapter<AbstractFlexibleItem<*>>? = null
|
||||||
|
private var adapterDataObserver: RecyclerView.AdapterDataObserver? = null
|
||||||
|
private val abstractFlexibleItemList = ArrayList<AbstractFlexibleItem<*>>()
|
||||||
|
|
||||||
|
private val callNotificationSounds: Boolean
|
||||||
|
private var mediaPlayer: MediaPlayer? = null
|
||||||
|
private var cancelMediaPlayerHandler: Handler? = null
|
||||||
|
|
||||||
|
private val ringtoneString: String
|
||||||
|
get() = if (callNotificationSounds) {
|
||||||
|
"android.resource://" + context.packageName +
|
||||||
|
"/raw/librem_by_feandesign_call"
|
||||||
|
} else {
|
||||||
|
"android.resource://" + context.packageName + "/raw" +
|
||||||
|
"/librem_by_feandesign_message"
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
this.callNotificationSounds = args.getBoolean(BundleKeys.KEY_ARE_CALL_SOUNDS, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||||
|
return inflater.inflate(R.layout.controller_generic_rv, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewBound(view: View) {
|
||||||
|
super.onViewBound(view)
|
||||||
|
|
||||||
|
if (adapter == null) {
|
||||||
|
adapter = FlexibleAdapter(abstractFlexibleItemList, activity, false)
|
||||||
|
|
||||||
|
adapter!!.setNotifyChangeOfUnfilteredItems(true).mode = SelectableAdapter.Mode.SINGLE
|
||||||
|
|
||||||
|
adapter!!.addListener(this)
|
||||||
|
|
||||||
|
cancelMediaPlayerHandler = Handler()
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter!!.addListener(this)
|
||||||
|
prepareViews()
|
||||||
|
fetchNotificationSounds()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
android.R.id.home -> return router.popCurrentController()
|
||||||
|
else -> return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepareViews() {
|
||||||
|
val layoutManager = SmoothScrollLinearLayoutManager(activity!!)
|
||||||
|
recyclerView!!.layoutManager = layoutManager
|
||||||
|
recyclerView!!.setHasFixedSize(true)
|
||||||
|
recyclerView!!.adapter = adapter
|
||||||
|
|
||||||
|
adapterDataObserver = object : RecyclerView.AdapterDataObserver() {
|
||||||
|
override fun onChanged() {
|
||||||
|
super.onChanged()
|
||||||
|
findSelectedSound()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter!!.registerAdapterDataObserver(adapterDataObserver!!)
|
||||||
|
swipeRefreshLayout!!.isEnabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("LongLogTag")
|
||||||
|
private fun findSelectedSound() {
|
||||||
|
var foundDefault = false
|
||||||
|
|
||||||
|
var preferencesString: String?
|
||||||
|
if (callNotificationSounds) {
|
||||||
|
preferencesString = appPreferences.callRingtoneUri
|
||||||
|
} else {
|
||||||
|
preferencesString = appPreferences.messageRingtoneUri
|
||||||
|
}
|
||||||
|
|
||||||
|
if (preferencesString.isNullOrEmpty()) {
|
||||||
|
adapter!!.toggleSelection(1)
|
||||||
|
foundDefault = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!preferencesString.isNullOrEmpty() && !foundDefault) {
|
||||||
|
try {
|
||||||
|
val ringtoneSettings = LoganSquare.parse(preferencesString, RingtoneSettings::class.java)
|
||||||
|
if (ringtoneSettings.ringtoneUri == null) {
|
||||||
|
adapter!!.toggleSelection(0)
|
||||||
|
} else if (ringtoneSettings.ringtoneUri.toString().equals(ringtoneString)) {
|
||||||
|
adapter!!.toggleSelection(1)
|
||||||
|
} else {
|
||||||
|
var notificationSoundItem: NotificationSoundItem
|
||||||
|
for (i in 2 until adapter!!.itemCount) {
|
||||||
|
notificationSoundItem = adapter!!.getItem(i) as NotificationSoundItem
|
||||||
|
if (notificationSoundItem.notificationSoundUri == ringtoneSettings.ringtoneUri.toString()) {
|
||||||
|
adapter!!.toggleSelection(i)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.e(TAG, "Failed to parse ringtone settings")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter!!.unregisterAdapterDataObserver(adapterDataObserver!!)
|
||||||
|
adapterDataObserver = null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchNotificationSounds() {
|
||||||
|
abstractFlexibleItemList.add(
|
||||||
|
NotificationSoundItem(resources!!.getString(R.string.nc_settings_no_ringtone), null))
|
||||||
|
abstractFlexibleItemList.add(NotificationSoundItem(resources!!
|
||||||
|
.getString(R.string.nc_settings_default_ringtone), ringtoneString))
|
||||||
|
|
||||||
|
if (activity != null) {
|
||||||
|
val manager = RingtoneManager(activity)
|
||||||
|
|
||||||
|
if (callNotificationSounds) {
|
||||||
|
manager.setType(RingtoneManager.TYPE_RINGTONE)
|
||||||
|
} else {
|
||||||
|
manager.setType(RingtoneManager.TYPE_NOTIFICATION)
|
||||||
|
}
|
||||||
|
|
||||||
|
val cursor = manager.cursor
|
||||||
|
|
||||||
|
var notificationSoundItem: NotificationSoundItem
|
||||||
|
|
||||||
|
while (cursor.moveToNext()) {
|
||||||
|
val notificationTitle = cursor.getString(RingtoneManager.TITLE_COLUMN_INDEX)
|
||||||
|
val notificationUri = cursor.getString(RingtoneManager.URI_COLUMN_INDEX)
|
||||||
|
val completeNotificationUri = "$notificationUri/" + cursor.getString(RingtoneManager
|
||||||
|
.ID_COLUMN_INDEX)
|
||||||
|
|
||||||
|
notificationSoundItem = NotificationSoundItem(notificationTitle, completeNotificationUri)
|
||||||
|
|
||||||
|
abstractFlexibleItemList.add(notificationSoundItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter!!.updateDataSet(abstractFlexibleItemList, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTitle(): String? {
|
||||||
|
return resources!!.getString(R.string.nc_settings_notification_sounds)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("LongLogTag")
|
||||||
|
override fun onItemClick(view: View, position: Int): Boolean {
|
||||||
|
val notificationSoundItem = adapter!!.getItem(position) as NotificationSoundItem?
|
||||||
|
|
||||||
|
var ringtoneUri: Uri? = null
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(notificationSoundItem!!.notificationSoundUri)) {
|
||||||
|
ringtoneUri = Uri.parse(notificationSoundItem.notificationSoundUri)
|
||||||
|
|
||||||
|
endMediaPlayer()
|
||||||
|
mediaPlayer = MediaPlayer.create(activity, ringtoneUri)
|
||||||
|
|
||||||
|
cancelMediaPlayerHandler = Handler()
|
||||||
|
cancelMediaPlayerHandler!!.postDelayed({ endMediaPlayer() }, (mediaPlayer!!.duration + 25).toLong())
|
||||||
|
mediaPlayer!!.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adapter!!.selectedPositions.size == 0 || adapter!!.selectedPositions[0] != position) {
|
||||||
|
val ringtoneSettings = RingtoneSettings()
|
||||||
|
ringtoneSettings.ringtoneName = notificationSoundItem.notificationSoundName
|
||||||
|
ringtoneSettings.ringtoneUri = ringtoneUri
|
||||||
|
|
||||||
|
if (callNotificationSounds) {
|
||||||
|
try {
|
||||||
|
appPreferences.callRingtoneUri = LoganSquare.serialize(ringtoneSettings)
|
||||||
|
adapter!!.toggleSelection(position)
|
||||||
|
adapter!!.notifyDataSetChanged()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.e(TAG, "Failed to store selected ringtone for calls")
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
appPreferences.messageRingtoneUri = LoganSquare.serialize(ringtoneSettings)
|
||||||
|
adapter!!.toggleSelection(position)
|
||||||
|
adapter!!.notifyDataSetChanged()
|
||||||
|
} catch (e: IOException) {
|
||||||
|
Log.e(TAG, "Failed to store selected ringtone for calls")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun endMediaPlayer() {
|
||||||
|
if (cancelMediaPlayerHandler != null) {
|
||||||
|
cancelMediaPlayerHandler!!.removeCallbacksAndMessages(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mediaPlayer != null) {
|
||||||
|
if (mediaPlayer!!.isPlaying) {
|
||||||
|
mediaPlayer!!.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaPlayer!!.release()
|
||||||
|
mediaPlayer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun onDestroy() {
|
||||||
|
endMediaPlayer()
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
private val TAG = "RingtoneSelectionController"
|
||||||
|
}
|
||||||
|
}
|
@ -35,7 +35,7 @@ import android.view.ViewGroup
|
|||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import autodagger.AutoInjector
|
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.OnClick
|
import butterknife.OnClick
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
@ -55,13 +55,15 @@ import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
|||||||
import com.uber.autodispose.AutoDispose
|
import com.uber.autodispose.AutoDispose
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
import studio.carbonylgroup.textfieldboxes.ExtendedEditText
|
import studio.carbonylgroup.textfieldboxes.ExtendedEditText
|
||||||
import studio.carbonylgroup.textfieldboxes.TextFieldBoxes
|
import studio.carbonylgroup.textfieldboxes.TextFieldBoxes
|
||||||
import java.security.cert.CertificateException
|
import java.security.cert.CertificateException
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
class ServerSelectionController : BaseController() {
|
class ServerSelectionController : BaseController() {
|
||||||
@JvmField
|
@JvmField
|
||||||
@BindView(R.id.extended_edit_text)
|
@BindView(R.id.extended_edit_text)
|
||||||
@ -119,8 +121,11 @@ class ServerSelectionController : BaseController() {
|
|||||||
&& TextUtils.isEmpty(resources!!.getString(R.string.nc_import_account_type))) {
|
&& TextUtils.isEmpty(resources!!.getString(R.string.nc_import_account_type))) {
|
||||||
providersTextView!!.visibility = View.INVISIBLE
|
providersTextView!!.visibility = View.INVISIBLE
|
||||||
} else {
|
} else {
|
||||||
|
GlobalScope.launch {
|
||||||
val users = usersRepository.getUsers()
|
val users = usersRepository.getUsers()
|
||||||
val usersSize = users.count()
|
val usersSize = users.count()
|
||||||
|
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
if ((TextUtils.isEmpty(resources!!.getString(R.string.nc_import_account_type)) ||
|
if ((TextUtils.isEmpty(resources!!.getString(R.string.nc_import_account_type)) ||
|
||||||
findAccounts(users).isEmpty()) &&
|
findAccounts(users).isEmpty()) &&
|
||||||
usersSize == 0) {
|
usersSize == 0) {
|
||||||
@ -180,6 +185,8 @@ class ServerSelectionController : BaseController() {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun toggleProceedButton(show: Boolean) {
|
private fun toggleProceedButton(show: Boolean) {
|
||||||
textFieldBoxes!!.endIconImageButton.isEnabled = show
|
textFieldBoxes!!.endIconImageButton.isEnabled = show
|
||||||
@ -210,7 +217,7 @@ class ServerSelectionController : BaseController() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkServer(queryUrl: String, checkForcedHttps: Boolean) {
|
private fun checkServer(queryUrl: String, checkForcedHttps: Boolean) {
|
||||||
ncApi!!.getServerStatus(queryUrl)
|
ncApi.getServerStatus(queryUrl)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.`as`(AutoDispose.autoDisposable(scopeProvider))
|
.`as`(AutoDispose.autoDisposable(scopeProvider))
|
||||||
|
@ -43,7 +43,7 @@ import androidx.core.view.ViewCompat
|
|||||||
import androidx.emoji.widget.EmojiTextView
|
import androidx.emoji.widget.EmojiTextView
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import autodagger.AutoInjector
|
|
||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.OnClick
|
import butterknife.OnClick
|
||||||
import coil.api.load
|
import coil.api.load
|
||||||
@ -97,7 +97,6 @@ import java.util.ArrayList
|
|||||||
import java.util.Arrays
|
import java.util.Arrays
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.Objects
|
import java.util.Objects
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class SettingsController : BaseController() {
|
class SettingsController : BaseController() {
|
||||||
@JvmField
|
@JvmField
|
||||||
@ -176,7 +175,6 @@ class SettingsController : BaseController() {
|
|||||||
@JvmField
|
@JvmField
|
||||||
@BindView(R.id.message_text)
|
@BindView(R.id.message_text)
|
||||||
var messageText: TextView? = null
|
var messageText: TextView? = null
|
||||||
@JvmField
|
|
||||||
val ncApi: NcApi by inject()
|
val ncApi: NcApi by inject()
|
||||||
val usersRepository: UsersRepository by inject()
|
val usersRepository: UsersRepository by inject()
|
||||||
private var saveStateHandler: LovelySaveStateHandler? = null
|
private var saveStateHandler: LovelySaveStateHandler? = null
|
||||||
@ -599,7 +597,7 @@ class SettingsController : BaseController() {
|
|||||||
|
|
||||||
loadAvatarImage()
|
loadAvatarImage()
|
||||||
|
|
||||||
ncApi!!.getUserProfile(
|
ncApi.getUserProfile(
|
||||||
credentials,
|
credentials,
|
||||||
ApiUtils.getUrlForUserProfile(currentUser!!.baseUrl)
|
ApiUtils.getUrlForUserProfile(currentUser!!.baseUrl)
|
||||||
)
|
)
|
||||||
|
@ -1,254 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Mario Danic
|
|
||||||
* Copyright (C) 2017 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/>.
|
|
||||||
*
|
|
||||||
* Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
|
|
||||||
* https://github.com/nextcloud/ownCloud-Account-Importer
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.controllers;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
|
|
||||||
|
|
||||||
import autodagger.AutoInjector;
|
|
||||||
import butterknife.BindView;
|
|
||||||
|
|
||||||
import com.bluelinelabs.conductor.RouterTransaction;
|
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
|
||||||
import com.nextcloud.talk.R;
|
|
||||||
import com.nextcloud.talk.adapters.items.AdvancedUserItem;
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
|
||||||
import com.nextcloud.talk.controllers.base.BaseController;
|
|
||||||
import com.nextcloud.talk.models.ImportAccount;
|
|
||||||
import com.nextcloud.talk.models.database.UserEntity;
|
|
||||||
import com.nextcloud.talk.models.json.participants.Participant;
|
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity;
|
|
||||||
import com.nextcloud.talk.utils.AccountUtils;
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
|
||||||
import com.uber.autodispose.AutoDispose;
|
|
||||||
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter;
|
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager;
|
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
|
|
||||||
import io.reactivex.Observer;
|
|
||||||
import io.reactivex.disposables.Disposable;
|
|
||||||
|
|
||||||
import java.net.CookieManager;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
public class SwitchAccountController extends BaseController {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
UserUtils userUtils;
|
|
||||||
|
|
||||||
@BindView(R.id.recyclerView)
|
|
||||||
RecyclerView recyclerView;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
CookieManager cookieManager;
|
|
||||||
|
|
||||||
@BindView(R.id.swipe_refresh_layout)
|
|
||||||
SwipeRefreshLayout swipeRefreshLayout;
|
|
||||||
private FlexibleAdapter<AbstractFlexibleItem> adapter;
|
|
||||||
private List<AbstractFlexibleItem> userItems = new ArrayList<>();
|
|
||||||
|
|
||||||
private boolean isAccountImport = false;
|
|
||||||
|
|
||||||
private FlexibleAdapter.OnItemClickListener onImportItemClickListener =
|
|
||||||
new FlexibleAdapter.OnItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onItemClick(View view, int position) {
|
|
||||||
if (userItems.size() > position) {
|
|
||||||
Account account = ((AdvancedUserItem) userItems.get(position)).getAccount();
|
|
||||||
reauthorizeFromImport(account);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private FlexibleAdapter.OnItemClickListener onSwitchItemClickListener =
|
|
||||||
new FlexibleAdapter.OnItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onItemClick(View view, int position) {
|
|
||||||
if (userItems.size() > position) {
|
|
||||||
UserEntity userEntity = ((AdvancedUserItem) userItems.get(position)).getEntity();
|
|
||||||
userUtils.createOrUpdateUser(null,
|
|
||||||
null, null, null,
|
|
||||||
null, true, null, userEntity.getId(), null, null, null)
|
|
||||||
.as(AutoDispose.autoDisposable(getScopeProvider()))
|
|
||||||
.subscribe(new Observer<UserEntity>() {
|
|
||||||
@Override
|
|
||||||
public void onSubscribe(Disposable d) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNext(UserEntity userEntity) {
|
|
||||||
cookieManager.getCookieStore().removeAll();
|
|
||||||
|
|
||||||
userUtils.disableAllUsersWithoutId(userEntity.getId());
|
|
||||||
if (getActivity() != null) {
|
|
||||||
getActivity().runOnUiThread(() -> getRouter().popCurrentController());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public SwitchAccountController() {
|
|
||||||
setHasOptionsMenu(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SwitchAccountController(Bundle args) {
|
|
||||||
super();
|
|
||||||
setHasOptionsMenu(true);
|
|
||||||
|
|
||||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT())) {
|
|
||||||
isAccountImport = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case android.R.id.home:
|
|
||||||
getRouter().popCurrentController();
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
|
||||||
return inflater.inflate(R.layout.controller_generic_rv, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onViewBound(@NonNull View view) {
|
|
||||||
super.onViewBound(view);
|
|
||||||
swipeRefreshLayout.setEnabled(false);
|
|
||||||
|
|
||||||
if (getActionBar() != null) {
|
|
||||||
getActionBar().show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adapter == null) {
|
|
||||||
adapter = new FlexibleAdapter<>(userItems, getActivity(), false);
|
|
||||||
|
|
||||||
UserNgEntity userEntity;
|
|
||||||
Participant participant;
|
|
||||||
|
|
||||||
if (!isAccountImport) {
|
|
||||||
for (Object userEntityObject : userUtils.getUsers()) {
|
|
||||||
userEntity = (UserEntity) userEntityObject;
|
|
||||||
if (!userEntity.getCurrent()) {
|
|
||||||
participant = new Participant();
|
|
||||||
participant.setName(userEntity.getDisplayName());
|
|
||||||
|
|
||||||
String userId;
|
|
||||||
|
|
||||||
if (userEntity.getUserId() != null) {
|
|
||||||
userId = userEntity.getUserId();
|
|
||||||
} else {
|
|
||||||
userId = userEntity.getUsername();
|
|
||||||
}
|
|
||||||
participant.setUserId(userId);
|
|
||||||
userItems.add(new AdvancedUserItem(participant, userEntity, null));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.addListener(onSwitchItemClickListener);
|
|
||||||
adapter.updateDataSet(userItems, false);
|
|
||||||
} else {
|
|
||||||
Account account;
|
|
||||||
ImportAccount importAccount;
|
|
||||||
for (Object accountObject : AccountUtils.INSTANCE.findAccounts(userUtils.getUsers())) {
|
|
||||||
account = (Account) accountObject;
|
|
||||||
importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account);
|
|
||||||
|
|
||||||
participant = new Participant();
|
|
||||||
participant.name = importAccount.username;
|
|
||||||
participant.userId = importAccount.username;
|
|
||||||
userEntity = new UserEntity();
|
|
||||||
userEntity.setBaseUrl(importAccount.getBaseUrl());
|
|
||||||
userItems.add(new AdvancedUserItem(participant, userEntity, account));
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.addListener(onImportItemClickListener);
|
|
||||||
adapter.updateDataSet(userItems, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareViews();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void prepareViews() {
|
|
||||||
LinearLayoutManager layoutManager = new SmoothScrollLinearLayoutManager(getActivity());
|
|
||||||
recyclerView.setLayoutManager(layoutManager);
|
|
||||||
recyclerView.setHasFixedSize(true);
|
|
||||||
recyclerView.setAdapter(adapter);
|
|
||||||
|
|
||||||
swipeRefreshLayout.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reauthorizeFromImport(Account account) {
|
|
||||||
ImportAccount importAccount = AccountUtils.INSTANCE.getInformationFromAccount(account);
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_BASE_URL(), importAccount.baseUrl);
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_USERNAME(), importAccount.username);
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_TOKEN(), importAccount.token);
|
|
||||||
bundle.putBoolean(BundleKeys.INSTANCE.getKEY_IS_ACCOUNT_IMPORT(), true);
|
|
||||||
getRouter().pushController(RouterTransaction.with(new AccountVerificationController(bundle))
|
|
||||||
.pushChangeHandler(new HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(new HorizontalChangeHandler()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getTitle() {
|
|
||||||
return getResources().getString(R.string.nc_select_an_account);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,227 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Mario Danic
|
||||||
|
* Copyright (C) 2017 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/>.
|
||||||
|
*
|
||||||
|
* Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
|
||||||
|
* https://github.com/nextcloud/ownCloud-Account-Importer
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.nextcloud.talk.controllers
|
||||||
|
|
||||||
|
import android.accounts.Account
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
|
||||||
|
import butterknife.BindView
|
||||||
|
|
||||||
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.adapters.items.AdvancedUserItem
|
||||||
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
|
import com.nextcloud.talk.controllers.base.BaseController
|
||||||
|
import com.nextcloud.talk.models.ImportAccount
|
||||||
|
import com.nextcloud.talk.models.json.participants.Participant
|
||||||
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
|
import com.nextcloud.talk.utils.AccountUtils
|
||||||
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
|
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||||
|
import com.uber.autodispose.AutoDispose
|
||||||
|
|
||||||
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
|
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||||
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
|
import io.reactivex.Observer
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import org.koin.android.ext.android.inject
|
||||||
|
|
||||||
|
import java.net.CookieManager
|
||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
class SwitchAccountController : BaseController {
|
||||||
|
@JvmField @BindView(R.id.recyclerView)
|
||||||
|
internal var recyclerView: RecyclerView? = null
|
||||||
|
|
||||||
|
val cookieManager: CookieManager by inject()
|
||||||
|
val userUtils: UserUtils by inject()
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.swipe_refresh_layout)
|
||||||
|
internal var swipeRefreshLayout: SwipeRefreshLayout? = null
|
||||||
|
private var adapter: FlexibleAdapter<AbstractFlexibleItem<*>>? = null
|
||||||
|
private val userItems = ArrayList<AbstractFlexibleItem<*>>()
|
||||||
|
|
||||||
|
private var isAccountImport = false
|
||||||
|
|
||||||
|
private val onImportItemClickListener = FlexibleAdapter.OnItemClickListener { view, position ->
|
||||||
|
if (userItems.size > position) {
|
||||||
|
val account = (userItems[position] as AdvancedUserItem).account
|
||||||
|
reauthorizeFromImport(account)
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
private val onSwitchItemClickListener = FlexibleAdapter.OnItemClickListener { view, position ->
|
||||||
|
if (userItems.size > position) {
|
||||||
|
val userEntity = (userItems[position] as AdvancedUserItem).entity
|
||||||
|
/*userUtils!!.createOrUpdateUser(null, null, null, null, null, true, null, userEntity!!.getId(), null, null, null)
|
||||||
|
.`as`(AutoDispose.autoDisposable<Any>(scopeProvider))
|
||||||
|
.subscribe(object : Observer<UserEntity> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(userEntity: UserEntity) {
|
||||||
|
cookieManager!!.cookieStore.removeAll()
|
||||||
|
|
||||||
|
userUtils!!.disableAllUsersWithoutId(userEntity.getId())
|
||||||
|
if (activity != null) {
|
||||||
|
activity!!.runOnUiThread { router.popCurrentController() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
})*/
|
||||||
|
}
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(args: Bundle) : super() {
|
||||||
|
setHasOptionsMenu(true)
|
||||||
|
|
||||||
|
if (args.containsKey(BundleKeys.KEY_IS_ACCOUNT_IMPORT)) {
|
||||||
|
isAccountImport = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
android.R.id.home -> {
|
||||||
|
router.popCurrentController()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
else -> return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||||
|
return inflater.inflate(R.layout.controller_generic_rv, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewBound(view: View) {
|
||||||
|
super.onViewBound(view)
|
||||||
|
swipeRefreshLayout!!.isEnabled = false
|
||||||
|
|
||||||
|
if (actionBar != null) {
|
||||||
|
actionBar!!.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
if (adapter == null) {
|
||||||
|
adapter = FlexibleAdapter(userItems, activity, false)
|
||||||
|
|
||||||
|
var userEntity: UserNgEntity
|
||||||
|
var participant: Participant
|
||||||
|
|
||||||
|
if (!isAccountImport) {
|
||||||
|
for (userEntityObject in userUtils!!.users) {
|
||||||
|
userEntity = userEntityObject as UserEntity
|
||||||
|
if (!userEntity.getCurrent()) {
|
||||||
|
participant = Participant()
|
||||||
|
participant.setName(userEntity.displayName)
|
||||||
|
|
||||||
|
val userId: String
|
||||||
|
|
||||||
|
if (userEntity.userId != null) {
|
||||||
|
userId = userEntity.userId
|
||||||
|
} else {
|
||||||
|
userId = userEntity.username
|
||||||
|
}
|
||||||
|
participant.setUserId(userId)
|
||||||
|
userItems.add(AdvancedUserItem(participant, userEntity, null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter!!.addListener(onSwitchItemClickListener)
|
||||||
|
adapter!!.updateDataSet(userItems, false)
|
||||||
|
} else {
|
||||||
|
var account: Account
|
||||||
|
var importAccount: ImportAccount
|
||||||
|
for (accountObject in AccountUtils.findAccounts(userUtils!!.users)) {
|
||||||
|
account = accountObject
|
||||||
|
importAccount = AccountUtils.getInformationFromAccount(account)
|
||||||
|
|
||||||
|
participant = Participant()
|
||||||
|
participant.name = importAccount.username
|
||||||
|
participant.userId = importAccount.username
|
||||||
|
userEntity = UserEntity()
|
||||||
|
userEntity.baseUrl = importAccount.getBaseUrl()
|
||||||
|
userItems.add(AdvancedUserItem(participant, userEntity, account))
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter!!.addListener(onImportItemClickListener)
|
||||||
|
adapter!!.updateDataSet(userItems, false)
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
prepareViews()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun prepareViews() {
|
||||||
|
val layoutManager = SmoothScrollLinearLayoutManager(activity!!)
|
||||||
|
recyclerView!!.layoutManager = layoutManager
|
||||||
|
recyclerView!!.setHasFixedSize(true)
|
||||||
|
recyclerView!!.adapter = adapter
|
||||||
|
|
||||||
|
swipeRefreshLayout!!.isEnabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reauthorizeFromImport(account: Account?) {
|
||||||
|
val importAccount = AccountUtils.getInformationFromAccount(account!!)
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putString(BundleKeys.KEY_BASE_URL, importAccount.baseUrl)
|
||||||
|
bundle.putString(BundleKeys.KEY_USERNAME, importAccount.username)
|
||||||
|
bundle.putString(BundleKeys.KEY_TOKEN, importAccount.token)
|
||||||
|
bundle.putBoolean(BundleKeys.KEY_IS_ACCOUNT_IMPORT, true)
|
||||||
|
router.pushController(RouterTransaction.with(AccountVerificationController(bundle))
|
||||||
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(HorizontalChangeHandler()))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTitle(): String? {
|
||||||
|
return resources!!.getString(R.string.nc_select_an_account)
|
||||||
|
}
|
||||||
|
}
|
@ -33,7 +33,7 @@ import android.view.inputmethod.InputMethodManager
|
|||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.app.ActionBar
|
import androidx.appcompat.app.ActionBar
|
||||||
import autodagger.AutoInjector
|
|
||||||
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider
|
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.controllers.AccountVerificationController
|
import com.nextcloud.talk.controllers.AccountVerificationController
|
||||||
@ -47,7 +47,6 @@ import org.greenrobot.eventbus.EventBus
|
|||||||
import org.koin.android.ext.android.inject
|
import org.koin.android.ext.android.inject
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
abstract class BaseController : ButterKnifeController(), ComponentCallbacks {
|
abstract class BaseController : ButterKnifeController(), ComponentCallbacks {
|
||||||
|
|
||||||
val scopeProvider: LifecycleScopeProvider<*> = ControllerScopeProvider.from(this)
|
val scopeProvider: LifecycleScopeProvider<*> = ControllerScopeProvider.from(this)
|
||||||
|
@ -1,333 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Mario Danic
|
|
||||||
* Copyright (C) 2017 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.controllers.bottomsheet;
|
|
||||||
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.text.Editable;
|
|
||||||
import android.text.InputType;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.text.TextWatcher;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.inputmethod.EditorInfo;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import butterknife.BindView;
|
|
||||||
import butterknife.OnClick;
|
|
||||||
import com.bluelinelabs.conductor.RouterTransaction;
|
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
|
||||||
import com.google.android.material.textfield.TextInputLayout;
|
|
||||||
import com.nextcloud.talk.R;
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
|
||||||
import com.nextcloud.talk.controllers.base.BaseController;
|
|
||||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation;
|
|
||||||
import com.nextcloud.talk.utils.EmojiTextInputEditText;
|
|
||||||
import com.nextcloud.talk.utils.ShareUtils;
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
|
||||||
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder;
|
|
||||||
import com.vanniktech.emoji.EmojiImageView;
|
|
||||||
import com.vanniktech.emoji.EmojiPopup;
|
|
||||||
import com.vanniktech.emoji.emoji.Emoji;
|
|
||||||
import com.vanniktech.emoji.listeners.OnEmojiClickListener;
|
|
||||||
import com.vanniktech.emoji.listeners.OnEmojiPopupDismissListener;
|
|
||||||
import com.vanniktech.emoji.listeners.OnEmojiPopupShownListener;
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
|
||||||
import org.parceler.Parcels;
|
|
||||||
|
|
||||||
public class EntryMenuController extends BaseController {
|
|
||||||
|
|
||||||
@BindView(R.id.ok_button)
|
|
||||||
Button proceedButton;
|
|
||||||
|
|
||||||
@BindView(R.id.text_edit)
|
|
||||||
EmojiTextInputEditText editText;
|
|
||||||
|
|
||||||
@BindView(R.id.text_input_layout)
|
|
||||||
TextInputLayout textInputLayout;
|
|
||||||
|
|
||||||
@BindView(R.id.smileyButton)
|
|
||||||
ImageView smileyButton;
|
|
||||||
|
|
||||||
private int operationCode;
|
|
||||||
private Conversation conversation;
|
|
||||||
private Intent shareIntent;
|
|
||||||
private String packageName;
|
|
||||||
private String name;
|
|
||||||
private String callUrl;
|
|
||||||
|
|
||||||
private EmojiPopup emojiPopup;
|
|
||||||
|
|
||||||
private Bundle originalBundle;
|
|
||||||
|
|
||||||
public EntryMenuController(Bundle args) {
|
|
||||||
super();
|
|
||||||
originalBundle = args;
|
|
||||||
|
|
||||||
this.operationCode = args.getInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE());
|
|
||||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_ROOM())) {
|
|
||||||
this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_SHARE_INTENT())) {
|
|
||||||
this.shareIntent =
|
|
||||||
Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_SHARE_INTENT()));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.name = args.getString(BundleKeys.INSTANCE.getKEY_APP_ITEM_NAME(), "");
|
|
||||||
this.packageName = args.getString(BundleKeys.INSTANCE.getKEY_APP_ITEM_PACKAGE_NAME(), "");
|
|
||||||
this.callUrl = args.getString(BundleKeys.INSTANCE.getKEY_CALL_URL(), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
|
||||||
return inflater.inflate(R.layout.controller_entry_menu, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.smileyButton)
|
|
||||||
void onSmileyClick() {
|
|
||||||
emojiPopup.toggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onAttach(@NonNull View view) {
|
|
||||||
super.onAttach(view);
|
|
||||||
if (ApplicationWideMessageHolder.getInstance().getMessageType() != null &&
|
|
||||||
ApplicationWideMessageHolder.getInstance()
|
|
||||||
.getMessageType()
|
|
||||||
.equals(ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG)) {
|
|
||||||
textInputLayout.setError(getResources().getString(R.string.nc_wrong_password));
|
|
||||||
ApplicationWideMessageHolder.getInstance().setMessageType(null);
|
|
||||||
if (proceedButton.isEnabled()) {
|
|
||||||
proceedButton.setEnabled(false);
|
|
||||||
proceedButton.setAlpha(0.7f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OnClick(R.id.ok_button)
|
|
||||||
public void onProceedButtonClick() {
|
|
||||||
Bundle bundle;
|
|
||||||
if (operationCode == 99) {
|
|
||||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
|
||||||
bundle = new Bundle();
|
|
||||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), callUrl);
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(),
|
|
||||||
editText.getText().toString());
|
|
||||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
|
|
||||||
if (originalBundle.containsKey(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES())) {
|
|
||||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES(),
|
|
||||||
originalBundle.getParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES()));
|
|
||||||
}
|
|
||||||
|
|
||||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
|
||||||
.pushChangeHandler(new HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(new HorizontalChangeHandler()));
|
|
||||||
} else if (operationCode != 7 && operationCode != 10 && operationCode != 11) {
|
|
||||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
|
||||||
bundle = new Bundle();
|
|
||||||
if (operationCode == 4 || operationCode == 6) {
|
|
||||||
conversation.setPassword(editText.getText().toString());
|
|
||||||
} else {
|
|
||||||
conversation.setName(editText.getText().toString());
|
|
||||||
}
|
|
||||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
|
|
||||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
|
|
||||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
|
||||||
.pushChangeHandler(new HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(new HorizontalChangeHandler()));
|
|
||||||
} else if (operationCode == 7) {
|
|
||||||
if (getActivity() != null) {
|
|
||||||
shareIntent.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(getActivity(),
|
|
||||||
editText.getText().toString(), conversation));
|
|
||||||
Intent intent = new Intent(shareIntent);
|
|
||||||
intent.setComponent(new ComponentName(packageName, name));
|
|
||||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
||||||
getActivity().startActivity(intent);
|
|
||||||
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
|
||||||
}
|
|
||||||
} else if (operationCode != 11) {
|
|
||||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
|
||||||
bundle = new Bundle();
|
|
||||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), operationCode);
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), editText.getText().toString());
|
|
||||||
getRouter().pushController(RouterTransaction.with(new OperationsMenuController(bundle))
|
|
||||||
.pushChangeHandler(new HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(new HorizontalChangeHandler()));
|
|
||||||
} else if (operationCode == 11) {
|
|
||||||
eventBus.post(new BottomSheetLockEvent(false, 0, false, false));
|
|
||||||
originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(),
|
|
||||||
editText.getText().toString());
|
|
||||||
getRouter().pushController(
|
|
||||||
RouterTransaction.with(new OperationsMenuController(originalBundle))
|
|
||||||
.pushChangeHandler(new HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(new HorizontalChangeHandler()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onViewBound(@NonNull View view) {
|
|
||||||
super.onViewBound(view);
|
|
||||||
NextcloudTalkApplication.Companion.getSharedApplication()
|
|
||||||
.getComponentApplication()
|
|
||||||
.inject(this);
|
|
||||||
|
|
||||||
if (conversation != null && operationCode == 2) {
|
|
||||||
editText.setText(conversation.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
editText.setOnEditorActionListener((v, actionId, event) -> {
|
|
||||||
if (actionId == EditorInfo.IME_ACTION_DONE
|
|
||||||
&& proceedButton != null
|
|
||||||
&& proceedButton.isEnabled()) {
|
|
||||||
proceedButton.callOnClick();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
editText.addTextChangedListener(new TextWatcher() {
|
|
||||||
@Override
|
|
||||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterTextChanged(Editable s) {
|
|
||||||
if (!TextUtils.isEmpty(s)) {
|
|
||||||
if (operationCode == 2) {
|
|
||||||
if (conversation.getName() == null || !conversation.getName().equals(s.toString())) {
|
|
||||||
if (!proceedButton.isEnabled()) {
|
|
||||||
proceedButton.setEnabled(true);
|
|
||||||
proceedButton.setAlpha(1.0f);
|
|
||||||
}
|
|
||||||
textInputLayout.setErrorEnabled(false);
|
|
||||||
} else {
|
|
||||||
if (proceedButton.isEnabled()) {
|
|
||||||
proceedButton.setEnabled(false);
|
|
||||||
proceedButton.setAlpha(0.38f);
|
|
||||||
}
|
|
||||||
textInputLayout.setError(getResources().getString(R.string.nc_call_name_is_same));
|
|
||||||
}
|
|
||||||
} else if (operationCode != 10) {
|
|
||||||
if (!proceedButton.isEnabled()) {
|
|
||||||
proceedButton.setEnabled(true);
|
|
||||||
proceedButton.setAlpha(1.0f);
|
|
||||||
}
|
|
||||||
textInputLayout.setErrorEnabled(false);
|
|
||||||
} else if ((editText.getText().toString().startsWith("http://") ||
|
|
||||||
editText.getText().toString().startsWith("https://")) &&
|
|
||||||
editText.getText().toString().contains("/call/")) {
|
|
||||||
// operation code 10
|
|
||||||
if (!proceedButton.isEnabled()) {
|
|
||||||
proceedButton.setEnabled(true);
|
|
||||||
proceedButton.setAlpha(1.0f);
|
|
||||||
}
|
|
||||||
textInputLayout.setErrorEnabled(false);
|
|
||||||
} else {
|
|
||||||
if (proceedButton.isEnabled()) {
|
|
||||||
proceedButton.setEnabled(false);
|
|
||||||
proceedButton.setAlpha(0.38f);
|
|
||||||
}
|
|
||||||
textInputLayout.setError(getResources().getString(R.string.nc_wrong_link));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (proceedButton.isEnabled()) {
|
|
||||||
proceedButton.setEnabled(false);
|
|
||||||
proceedButton.setAlpha(0.38f);
|
|
||||||
}
|
|
||||||
textInputLayout.setErrorEnabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
String labelText = "";
|
|
||||||
switch (operationCode) {
|
|
||||||
case 11:
|
|
||||||
case 2:
|
|
||||||
labelText = getResources().getString(R.string.nc_call_name);
|
|
||||||
editText.setInputType(InputType.TYPE_CLASS_TEXT);
|
|
||||||
smileyButton.setVisibility(View.VISIBLE);
|
|
||||||
emojiPopup = EmojiPopup.Builder.fromRootView(view)
|
|
||||||
.setOnEmojiPopupShownListener(new OnEmojiPopupShownListener() {
|
|
||||||
@Override
|
|
||||||
public void onEmojiPopupShown() {
|
|
||||||
if (getResources() != null) {
|
|
||||||
smileyButton.setColorFilter(getResources().getColor(R.color.colorPrimary),
|
|
||||||
PorterDuff.Mode.SRC_IN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setOnEmojiPopupDismissListener(new OnEmojiPopupDismissListener() {
|
|
||||||
@Override
|
|
||||||
public void onEmojiPopupDismiss() {
|
|
||||||
if (smileyButton != null) {
|
|
||||||
smileyButton.setColorFilter(getResources().getColor(R.color.emoji_icons),
|
|
||||||
PorterDuff.Mode.SRC_IN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.setOnEmojiClickListener(new OnEmojiClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onEmojiClick(@NonNull EmojiImageView emoji, @NonNull Emoji imageView) {
|
|
||||||
editText.getEditableText().append(" ");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.build(editText);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
labelText = getResources().getString(R.string.nc_new_password);
|
|
||||||
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
case 7:
|
|
||||||
case 99:
|
|
||||||
// 99 is joining a conversation via password
|
|
||||||
labelText = getResources().getString(R.string.nc_password);
|
|
||||||
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
labelText = getResources().getString(R.string.nc_conversation_link);
|
|
||||||
editText.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
textInputLayout.setPasswordVisibilityToggleEnabled(
|
|
||||||
operationCode == 99 || operationCode == 4 || operationCode == 6 || operationCode == 7);
|
|
||||||
textInputLayout.setHint(labelText);
|
|
||||||
textInputLayout.requestFocus();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,297 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Mario Danic
|
||||||
|
* Copyright (C) 2017 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.controllers.bottomsheet
|
||||||
|
|
||||||
|
import android.content.ComponentName
|
||||||
|
import android.content.Intent
|
||||||
|
import android.graphics.PorterDuff
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.InputType
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.ImageView
|
||||||
|
import butterknife.BindView
|
||||||
|
import butterknife.OnClick
|
||||||
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||||
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
|
import com.nextcloud.talk.controllers.base.BaseController
|
||||||
|
import com.nextcloud.talk.events.BottomSheetLockEvent
|
||||||
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
|
import com.nextcloud.talk.utils.EmojiTextInputEditText
|
||||||
|
import com.nextcloud.talk.utils.ShareUtils
|
||||||
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
|
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||||
|
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
||||||
|
import com.vanniktech.emoji.EmojiImageView
|
||||||
|
import com.vanniktech.emoji.EmojiPopup
|
||||||
|
import com.vanniktech.emoji.emoji.Emoji
|
||||||
|
import com.vanniktech.emoji.listeners.OnEmojiClickListener
|
||||||
|
import com.vanniktech.emoji.listeners.OnEmojiPopupDismissListener
|
||||||
|
import com.vanniktech.emoji.listeners.OnEmojiPopupShownListener
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.parceler.Parcels
|
||||||
|
|
||||||
|
class EntryMenuController(private val originalBundle: Bundle) : BaseController() {
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.ok_button)
|
||||||
|
internal var proceedButton: Button? = null
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.text_edit)
|
||||||
|
internal var editText: EmojiTextInputEditText? = null
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.text_input_layout)
|
||||||
|
internal var textInputLayout: TextInputLayout? = null
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.smileyButton)
|
||||||
|
internal var smileyButton: ImageView? = null
|
||||||
|
|
||||||
|
private val operationCode: Int
|
||||||
|
private var conversation: Conversation? = null
|
||||||
|
private var shareIntent: Intent? = null
|
||||||
|
private val packageName: String
|
||||||
|
private val name: String
|
||||||
|
private val callUrl: String
|
||||||
|
|
||||||
|
private var emojiPopup: EmojiPopup? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
|
||||||
|
this.operationCode = originalBundle.getInt(BundleKeys.KEY_OPERATION_CODE)
|
||||||
|
if (originalBundle.containsKey(BundleKeys.KEY_ROOM)) {
|
||||||
|
this.conversation = Parcels.unwrap(originalBundle.getParcelable(BundleKeys.KEY_ROOM))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (originalBundle.containsKey(BundleKeys.KEY_SHARE_INTENT)) {
|
||||||
|
this.shareIntent = Parcels.unwrap(originalBundle.getParcelable(BundleKeys.KEY_SHARE_INTENT))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.name = originalBundle.getString(BundleKeys.KEY_APP_ITEM_NAME, "")
|
||||||
|
this.packageName = originalBundle.getString(BundleKeys.KEY_APP_ITEM_PACKAGE_NAME, "")
|
||||||
|
this.callUrl = originalBundle.getString(BundleKeys.KEY_CALL_URL, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||||
|
return inflater.inflate(R.layout.controller_entry_menu, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.smileyButton)
|
||||||
|
internal fun onSmileyClick() {
|
||||||
|
emojiPopup!!.toggle()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onAttach(view: View) {
|
||||||
|
super.onAttach(view)
|
||||||
|
if (ApplicationWideMessageHolder.getInstance().messageType != null && ApplicationWideMessageHolder.getInstance()
|
||||||
|
.messageType == ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG) {
|
||||||
|
textInputLayout!!.error = resources!!.getString(R.string.nc_wrong_password)
|
||||||
|
ApplicationWideMessageHolder.getInstance().messageType = null
|
||||||
|
if (proceedButton!!.isEnabled) {
|
||||||
|
proceedButton!!.isEnabled = false
|
||||||
|
proceedButton!!.alpha = 0.7f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnClick(R.id.ok_button)
|
||||||
|
fun onProceedButtonClick() {
|
||||||
|
val bundle: Bundle
|
||||||
|
if (operationCode == 99) {
|
||||||
|
eventBus.post(BottomSheetLockEvent(false, 0, false, false))
|
||||||
|
bundle = Bundle()
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation))
|
||||||
|
bundle.putString(BundleKeys.KEY_CALL_URL, callUrl)
|
||||||
|
bundle.putString(BundleKeys.KEY_CONVERSATION_PASSWORD,
|
||||||
|
editText!!.text!!.toString())
|
||||||
|
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode)
|
||||||
|
if (originalBundle.containsKey(BundleKeys.KEY_SERVER_CAPABILITIES)) {
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_SERVER_CAPABILITIES,
|
||||||
|
originalBundle.getParcelable(BundleKeys.KEY_SERVER_CAPABILITIES))
|
||||||
|
}
|
||||||
|
|
||||||
|
router.pushController(RouterTransaction.with(OperationsMenuController(bundle))
|
||||||
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(HorizontalChangeHandler()))
|
||||||
|
} else if (operationCode != 7 && operationCode != 10 && operationCode != 11) {
|
||||||
|
eventBus.post(BottomSheetLockEvent(false, 0, false, false))
|
||||||
|
bundle = Bundle()
|
||||||
|
if (operationCode == 4 || operationCode == 6) {
|
||||||
|
conversation!!.password = editText!!.text!!.toString()
|
||||||
|
} else {
|
||||||
|
conversation!!.name = editText!!.text!!.toString()
|
||||||
|
}
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation))
|
||||||
|
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode)
|
||||||
|
router.pushController(RouterTransaction.with(OperationsMenuController(bundle))
|
||||||
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(HorizontalChangeHandler()))
|
||||||
|
} else if (operationCode == 7) {
|
||||||
|
if (activity != null) {
|
||||||
|
shareIntent!!.putExtra(Intent.EXTRA_TEXT, ShareUtils.getStringForIntent(activity,
|
||||||
|
editText!!.text!!.toString(), conversation!!))
|
||||||
|
val intent = Intent(shareIntent)
|
||||||
|
intent.component = ComponentName(packageName, name)
|
||||||
|
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
activity!!.startActivity(intent)
|
||||||
|
eventBus.post(BottomSheetLockEvent(true, 0, false, true))
|
||||||
|
}
|
||||||
|
} else if (operationCode != 11) {
|
||||||
|
eventBus.post(BottomSheetLockEvent(false, 0, false, false))
|
||||||
|
bundle = Bundle()
|
||||||
|
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, operationCode)
|
||||||
|
bundle.putString(BundleKeys.KEY_CALL_URL, editText!!.text!!.toString())
|
||||||
|
router.pushController(RouterTransaction.with(OperationsMenuController(bundle))
|
||||||
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(HorizontalChangeHandler()))
|
||||||
|
} else if (operationCode == 11) {
|
||||||
|
eventBus.post(BottomSheetLockEvent(false, 0, false, false))
|
||||||
|
originalBundle.putString(BundleKeys.KEY_CONVERSATION_NAME,
|
||||||
|
editText!!.text!!.toString())
|
||||||
|
router.pushController(
|
||||||
|
RouterTransaction.with(OperationsMenuController(originalBundle))
|
||||||
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(HorizontalChangeHandler()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewBound(view: View) {
|
||||||
|
super.onViewBound(view)
|
||||||
|
if (conversation != null && operationCode == 2) {
|
||||||
|
editText!!.setText(conversation!!.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
editText!!.setOnEditorActionListener { v, actionId, event ->
|
||||||
|
if (actionId == EditorInfo.IME_ACTION_DONE
|
||||||
|
&& proceedButton != null
|
||||||
|
&& proceedButton!!.isEnabled) {
|
||||||
|
proceedButton!!.callOnClick()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
editText!!.addTextChangedListener(object : TextWatcher {
|
||||||
|
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterTextChanged(s: Editable) {
|
||||||
|
if (!TextUtils.isEmpty(s)) {
|
||||||
|
if (operationCode == 2) {
|
||||||
|
if (conversation!!.name == null || conversation!!.name != s.toString()) {
|
||||||
|
if (!proceedButton!!.isEnabled) {
|
||||||
|
proceedButton!!.isEnabled = true
|
||||||
|
proceedButton!!.alpha = 1.0f
|
||||||
|
}
|
||||||
|
textInputLayout!!.isErrorEnabled = false
|
||||||
|
} else {
|
||||||
|
if (proceedButton!!.isEnabled) {
|
||||||
|
proceedButton!!.isEnabled = false
|
||||||
|
proceedButton!!.alpha = 0.38f
|
||||||
|
}
|
||||||
|
textInputLayout!!.error = resources!!.getString(R.string.nc_call_name_is_same)
|
||||||
|
}
|
||||||
|
} else if (operationCode != 10) {
|
||||||
|
if (!proceedButton!!.isEnabled) {
|
||||||
|
proceedButton!!.isEnabled = true
|
||||||
|
proceedButton!!.alpha = 1.0f
|
||||||
|
}
|
||||||
|
textInputLayout!!.isErrorEnabled = false
|
||||||
|
} else if ((editText!!.text!!.toString().startsWith("http://") || editText!!.text!!.toString().startsWith("https://")) && editText!!.text!!.toString().contains("/call/")) {
|
||||||
|
// operation code 10
|
||||||
|
if (!proceedButton!!.isEnabled) {
|
||||||
|
proceedButton!!.isEnabled = true
|
||||||
|
proceedButton!!.alpha = 1.0f
|
||||||
|
}
|
||||||
|
textInputLayout!!.isErrorEnabled = false
|
||||||
|
} else {
|
||||||
|
if (proceedButton!!.isEnabled) {
|
||||||
|
proceedButton!!.isEnabled = false
|
||||||
|
proceedButton!!.alpha = 0.38f
|
||||||
|
}
|
||||||
|
textInputLayout!!.error = resources!!.getString(R.string.nc_wrong_link)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (proceedButton!!.isEnabled) {
|
||||||
|
proceedButton!!.isEnabled = false
|
||||||
|
proceedButton!!.alpha = 0.38f
|
||||||
|
}
|
||||||
|
textInputLayout!!.isErrorEnabled = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var labelText = ""
|
||||||
|
when (operationCode) {
|
||||||
|
11, 2 -> {
|
||||||
|
labelText = resources!!.getString(R.string.nc_call_name)
|
||||||
|
editText!!.inputType = InputType.TYPE_CLASS_TEXT
|
||||||
|
smileyButton!!.visibility = View.VISIBLE
|
||||||
|
emojiPopup = EmojiPopup.Builder.fromRootView(view)
|
||||||
|
.setOnEmojiPopupShownListener {
|
||||||
|
if (resources != null) {
|
||||||
|
smileyButton!!.setColorFilter(resources!!.getColor(R.color.colorPrimary),
|
||||||
|
PorterDuff.Mode.SRC_IN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.setOnEmojiPopupDismissListener {
|
||||||
|
if (smileyButton != null) {
|
||||||
|
smileyButton!!.setColorFilter(resources!!.getColor(R.color.emoji_icons),
|
||||||
|
PorterDuff.Mode.SRC_IN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.setOnEmojiClickListener { emoji, imageView -> editText!!.editableText.append(" ") }
|
||||||
|
.build(editText!!)
|
||||||
|
}
|
||||||
|
4 -> {
|
||||||
|
labelText = resources!!.getString(R.string.nc_new_password)
|
||||||
|
editText!!.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
|
||||||
|
}
|
||||||
|
6, 7, 99 -> {
|
||||||
|
// 99 is joining a conversation via password
|
||||||
|
labelText = resources!!.getString(R.string.nc_password)
|
||||||
|
editText!!.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD
|
||||||
|
}
|
||||||
|
10 -> {
|
||||||
|
labelText = resources!!.getString(R.string.nc_conversation_link)
|
||||||
|
editText!!.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
textInputLayout!!.isPasswordVisibilityToggleEnabled = operationCode == 99 || operationCode == 4 || operationCode == 6 || operationCode == 7
|
||||||
|
textInputLayout!!.hint = labelText
|
||||||
|
textInputLayout!!.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
@ -1,753 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Mario Danic
|
|
||||||
* Copyright (C) 2017 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.controllers.bottomsheet;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.inputmethod.InputMethodManager;
|
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import autodagger.AutoInjector;
|
|
||||||
import butterknife.BindView;
|
|
||||||
import com.bluelinelabs.conductor.RouterTransaction;
|
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
|
||||||
import com.bluelinelabs.logansquare.LoganSquare;
|
|
||||||
import com.nextcloud.talk.R;
|
|
||||||
import com.nextcloud.talk.activities.MagicCallActivity;
|
|
||||||
import com.nextcloud.talk.api.NcApi;
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
|
||||||
import com.nextcloud.talk.controllers.base.BaseController;
|
|
||||||
import com.nextcloud.talk.events.BottomSheetLockEvent;
|
|
||||||
import com.nextcloud.talk.models.RetrofitBucket;
|
|
||||||
import com.nextcloud.talk.models.database.UserEntity;
|
|
||||||
import com.nextcloud.talk.models.json.capabilities.Capabilities;
|
|
||||||
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall;
|
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation;
|
|
||||||
import com.nextcloud.talk.models.json.conversations.RoomOverall;
|
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall;
|
|
||||||
import com.nextcloud.talk.models.json.participants.AddParticipantOverall;
|
|
||||||
import com.nextcloud.talk.utils.ApiUtils;
|
|
||||||
import com.nextcloud.talk.utils.ConductorRemapping;
|
|
||||||
import com.nextcloud.talk.utils.DisplayUtils;
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys;
|
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils;
|
|
||||||
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder;
|
|
||||||
import io.reactivex.Observer;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.disposables.Disposable;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import org.greenrobot.eventbus.EventBus;
|
|
||||||
import org.parceler.Parcels;
|
|
||||||
import retrofit2.HttpException;
|
|
||||||
|
|
||||||
public class OperationsMenuController extends BaseController {
|
|
||||||
|
|
||||||
@BindView(R.id.progress_bar)
|
|
||||||
ProgressBar progressBar;
|
|
||||||
|
|
||||||
@BindView(R.id.result_image_view)
|
|
||||||
ImageView resultImageView;
|
|
||||||
|
|
||||||
@BindView(R.id.result_text_view)
|
|
||||||
TextView resultsTextView;
|
|
||||||
|
|
||||||
@BindView(R.id.ok_button)
|
|
||||||
Button okButton;
|
|
||||||
|
|
||||||
@BindView(R.id.web_button)
|
|
||||||
Button webButton;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
NcApi ncApi;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
UserUtils userUtils;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
EventBus eventBus;
|
|
||||||
|
|
||||||
private int operationCode;
|
|
||||||
private Conversation conversation;
|
|
||||||
|
|
||||||
private UserEntity currentUser;
|
|
||||||
private String callPassword;
|
|
||||||
private String callUrl;
|
|
||||||
|
|
||||||
private String baseUrl;
|
|
||||||
private String conversationToken;
|
|
||||||
|
|
||||||
private Disposable disposable;
|
|
||||||
|
|
||||||
private Conversation.ConversationType conversationType;
|
|
||||||
private ArrayList<String> invitedUsers = new ArrayList<>();
|
|
||||||
private ArrayList<String> invitedGroups = new ArrayList<>();
|
|
||||||
|
|
||||||
private Capabilities serverCapabilities;
|
|
||||||
private String credentials;
|
|
||||||
private String conversationName;
|
|
||||||
|
|
||||||
public OperationsMenuController(Bundle args) {
|
|
||||||
super();
|
|
||||||
this.operationCode = args.getInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE());
|
|
||||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_ROOM())) {
|
|
||||||
this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_ROOM()));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.callPassword = args.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), "");
|
|
||||||
this.callUrl = args.getString(BundleKeys.INSTANCE.getKEY_CALL_URL(), "");
|
|
||||||
|
|
||||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_INVITED_PARTICIPANTS())) {
|
|
||||||
this.invitedUsers =
|
|
||||||
args.getStringArrayList(BundleKeys.INSTANCE.getKEY_INVITED_PARTICIPANTS());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_INVITED_GROUP())) {
|
|
||||||
this.invitedGroups = args.getStringArrayList(BundleKeys.INSTANCE.getKEY_INVITED_GROUP());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_CONVERSATION_TYPE())) {
|
|
||||||
this.conversationType =
|
|
||||||
Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_CONVERSATION_TYPE()));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args.containsKey(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES())) {
|
|
||||||
this.serverCapabilities =
|
|
||||||
Parcels.unwrap(args.getParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES()));
|
|
||||||
}
|
|
||||||
|
|
||||||
this.conversationName = args.getString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), "");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected View inflateView(@NonNull LayoutInflater inflater, @NonNull ViewGroup container) {
|
|
||||||
return inflater.inflate(R.layout.controller_operations_menu, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onViewBound(@NonNull View view) {
|
|
||||||
super.onViewBound(view);
|
|
||||||
processOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processOperation() {
|
|
||||||
currentUser = userUtils.getCurrentUser();
|
|
||||||
OperationsObserver operationsObserver = new OperationsObserver();
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(callUrl) && callUrl.contains("/call")) {
|
|
||||||
conversationToken = callUrl.substring(callUrl.lastIndexOf("/") + 1);
|
|
||||||
if (callUrl.contains("/index.php")) {
|
|
||||||
baseUrl = callUrl.substring(0, callUrl.indexOf("/index.php"));
|
|
||||||
} else {
|
|
||||||
baseUrl = callUrl.substring(0, callUrl.indexOf("/call"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentUser != null) {
|
|
||||||
credentials = ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken());
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(baseUrl) && !baseUrl.equals(currentUser.getBaseUrl())) {
|
|
||||||
credentials = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (operationCode) {
|
|
||||||
case 2:
|
|
||||||
ncApi.renameRoom(credentials,
|
|
||||||
ApiUtils.getRoom(currentUser.getBaseUrl(), conversation.getToken()),
|
|
||||||
conversation.getName())
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(operationsObserver);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
ncApi.makeRoomPublic(credentials,
|
|
||||||
ApiUtils.getUrlForRoomVisibility(currentUser.getBaseUrl(), conversation
|
|
||||||
.getToken()))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(operationsObserver);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
case 5:
|
|
||||||
case 6:
|
|
||||||
String pass = "";
|
|
||||||
if (conversation.getPassword() != null) {
|
|
||||||
pass = conversation.getPassword();
|
|
||||||
}
|
|
||||||
ncApi.setPassword(credentials, ApiUtils.getUrlForPassword(currentUser.getBaseUrl(),
|
|
||||||
conversation.getToken()), pass)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(operationsObserver);
|
|
||||||
break;
|
|
||||||
case 7:
|
|
||||||
// Operation 7 is sharing, so we handle this differently
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
ncApi.makeRoomPrivate(credentials,
|
|
||||||
ApiUtils.getUrlForRoomVisibility(currentUser.getBaseUrl(), conversation
|
|
||||||
.getToken()))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(operationsObserver);
|
|
||||||
break;
|
|
||||||
case 10:
|
|
||||||
ncApi.getRoom(credentials, ApiUtils.getRoom(baseUrl, conversationToken))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(new Observer<RoomOverall>() {
|
|
||||||
@Override
|
|
||||||
public void onSubscribe(Disposable d) {
|
|
||||||
disposable = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNext(RoomOverall roomOverall) {
|
|
||||||
conversation = roomOverall.getOcs().getData();
|
|
||||||
fetchCapabilities(credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable e) {
|
|
||||||
showResultImage(false, false);
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 11:
|
|
||||||
RetrofitBucket retrofitBucket;
|
|
||||||
boolean isGroupCallWorkaround = false;
|
|
||||||
String invite = null;
|
|
||||||
|
|
||||||
if (invitedGroups.size() > 0) {
|
|
||||||
invite = invitedGroups.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conversationType.equals(Conversation.ConversationType.PUBLIC_CONVERSATION) ||
|
|
||||||
!currentUser.hasSpreedFeatureCapability("empty-group-room")) {
|
|
||||||
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser.getBaseUrl(),
|
|
||||||
"3", invite, conversationName);
|
|
||||||
} else {
|
|
||||||
String roomType = "2";
|
|
||||||
if (!currentUser.hasSpreedFeatureCapability("empty-group-room")) {
|
|
||||||
isGroupCallWorkaround = true;
|
|
||||||
roomType = "3";
|
|
||||||
}
|
|
||||||
|
|
||||||
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser.getBaseUrl(),
|
|
||||||
roomType, invite, conversationName);
|
|
||||||
}
|
|
||||||
|
|
||||||
final boolean isGroupCallWorkaroundFinal = isGroupCallWorkaround;
|
|
||||||
ncApi.createRoom(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(new Observer<RoomOverall>() {
|
|
||||||
@Override
|
|
||||||
public void onSubscribe(Disposable d) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNext(RoomOverall roomOverall) {
|
|
||||||
conversation = roomOverall.getOcs().getData();
|
|
||||||
|
|
||||||
ncApi.getRoom(credentials,
|
|
||||||
ApiUtils.getRoom(currentUser.getBaseUrl(), conversation.getToken()))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(new Observer<RoomOverall>() {
|
|
||||||
@Override
|
|
||||||
public void onSubscribe(Disposable d) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNext(RoomOverall roomOverall) {
|
|
||||||
conversation = roomOverall.getOcs().getData();
|
|
||||||
if (conversationType.equals(
|
|
||||||
Conversation.ConversationType.PUBLIC_CONVERSATION)
|
|
||||||
&& isGroupCallWorkaroundFinal) {
|
|
||||||
performGroupCallWorkaround(credentials);
|
|
||||||
} else {
|
|
||||||
inviteUsersToAConversation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable e) {
|
|
||||||
showResultImage(false, false);
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable e) {
|
|
||||||
showResultImage(false, false);
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 97:
|
|
||||||
case 98:
|
|
||||||
if (operationCode == 97) {
|
|
||||||
ncApi.removeConversationFromFavorites(credentials,
|
|
||||||
ApiUtils.getUrlForConversationFavorites(currentUser.getBaseUrl(),
|
|
||||||
conversation.getToken()))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(operationsObserver);
|
|
||||||
} else {
|
|
||||||
ncApi.addConversationToFavorites(credentials,
|
|
||||||
ApiUtils.getUrlForConversationFavorites(currentUser.getBaseUrl(),
|
|
||||||
conversation.getToken()))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(operationsObserver);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 99:
|
|
||||||
ncApi.joinRoom(credentials,
|
|
||||||
ApiUtils.getUrlForSettingMyselfAsActiveParticipant(baseUrl, conversationToken),
|
|
||||||
callPassword)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(operationsObserver);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void performGroupCallWorkaround(String credentials) {
|
|
||||||
ncApi.makeRoomPrivate(credentials,
|
|
||||||
ApiUtils.getUrlForRoomVisibility(currentUser.getBaseUrl(), conversation.getToken()))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(new Observer<GenericOverall>() {
|
|
||||||
@Override
|
|
||||||
public void onSubscribe(Disposable d) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNext(GenericOverall genericOverall) {
|
|
||||||
inviteUsersToAConversation();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable e) {
|
|
||||||
showResultImage(false, false);
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showResultImage(boolean everythingOK, boolean isGuestSupportError) {
|
|
||||||
progressBar.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
if (everythingOK) {
|
|
||||||
resultImageView.setImageDrawable(DisplayUtils.INSTANCE.getTintedDrawable(getResources(), R.drawable
|
|
||||||
.ic_check_circle_black_24dp, R.color.nc_darkGreen));
|
|
||||||
} else {
|
|
||||||
resultImageView.setImageDrawable(DisplayUtils.INSTANCE.getTintedDrawable(getResources(), R.drawable
|
|
||||||
.ic_cancel_black_24dp, R.color.nc_darkRed));
|
|
||||||
}
|
|
||||||
|
|
||||||
resultImageView.setVisibility(View.VISIBLE);
|
|
||||||
|
|
||||||
if (everythingOK) {
|
|
||||||
resultsTextView.setText(R.string.nc_all_ok_operation);
|
|
||||||
} else {
|
|
||||||
resultsTextView.setTextColor(getResources().getColor(R.color.nc_darkRed));
|
|
||||||
if (!isGuestSupportError) {
|
|
||||||
resultsTextView.setText(R.string.nc_failed_to_perform_operation);
|
|
||||||
} else {
|
|
||||||
resultsTextView.setText(R.string.nc_failed_signaling_settings);
|
|
||||||
webButton.setOnClickListener(v -> {
|
|
||||||
eventBus.post(new BottomSheetLockEvent(true, 0, false, true));
|
|
||||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(callUrl));
|
|
||||||
startActivity(browserIntent);
|
|
||||||
new BottomSheetLockEvent(true, 0, false, true);
|
|
||||||
});
|
|
||||||
webButton.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resultsTextView.setVisibility(View.VISIBLE);
|
|
||||||
if (everythingOK) {
|
|
||||||
eventBus.post(new BottomSheetLockEvent(true, 2500, true, true));
|
|
||||||
} else {
|
|
||||||
resultImageView.setImageDrawable(DisplayUtils.INSTANCE.getTintedDrawable(getResources(), R.drawable
|
|
||||||
.ic_cancel_black_24dp, R.color.nc_darkRed));
|
|
||||||
okButton.setOnClickListener(
|
|
||||||
v -> eventBus.post(new BottomSheetLockEvent(true, 0, operationCode != 99
|
|
||||||
&& operationCode != 10, true)));
|
|
||||||
okButton.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void dispose() {
|
|
||||||
if (disposable != null && !disposable.isDisposed()) {
|
|
||||||
disposable.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
disposable = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fetchCapabilities(String credentials) {
|
|
||||||
ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(new Observer<CapabilitiesOverall>() {
|
|
||||||
@Override
|
|
||||||
public void onSubscribe(Disposable d) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNext(CapabilitiesOverall capabilitiesOverall) {
|
|
||||||
if (capabilitiesOverall.getOcs().getData()
|
|
||||||
.getCapabilities().getSpreedCapability() != null &&
|
|
||||||
capabilitiesOverall.getOcs().getData()
|
|
||||||
.getCapabilities().getSpreedCapability()
|
|
||||||
.getFeatures() != null && capabilitiesOverall.getOcs().getData()
|
|
||||||
.getCapabilities().getSpreedCapability()
|
|
||||||
.getFeatures().contains("chat-v2")) {
|
|
||||||
if (conversation.getHasPassword() && conversation.isGuest()) {
|
|
||||||
eventBus.post(new BottomSheetLockEvent(true, 0,
|
|
||||||
true, false));
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ROOM(), Parcels.wrap(conversation));
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CALL_URL(), callUrl);
|
|
||||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_SERVER_CAPABILITIES(),
|
|
||||||
Parcels.wrap(capabilitiesOverall.getOcs().getData().getCapabilities()));
|
|
||||||
bundle.putInt(BundleKeys.INSTANCE.getKEY_OPERATION_CODE(), 99);
|
|
||||||
getRouter().pushController(RouterTransaction.with(new EntryMenuController(bundle))
|
|
||||||
.pushChangeHandler(new HorizontalChangeHandler())
|
|
||||||
.popChangeHandler(new HorizontalChangeHandler()));
|
|
||||||
} else {
|
|
||||||
initiateConversation(false, capabilitiesOverall.getOcs().getData()
|
|
||||||
.getCapabilities());
|
|
||||||
}
|
|
||||||
} else if (capabilitiesOverall.getOcs().getData()
|
|
||||||
.getCapabilities().getSpreedCapability() != null &&
|
|
||||||
capabilitiesOverall.getOcs().getData()
|
|
||||||
.getCapabilities().getSpreedCapability()
|
|
||||||
.getFeatures() != null && capabilitiesOverall.getOcs().getData()
|
|
||||||
.getCapabilities().getSpreedCapability()
|
|
||||||
.getFeatures().contains("guest-signaling")) {
|
|
||||||
initiateCall();
|
|
||||||
} else {
|
|
||||||
showResultImage(false, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable e) {
|
|
||||||
showResultImage(false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void inviteUsersToAConversation() {
|
|
||||||
RetrofitBucket retrofitBucket;
|
|
||||||
final ArrayList<String> localInvitedUsers = invitedUsers;
|
|
||||||
final ArrayList<String> localInvitedGroups = invitedGroups;
|
|
||||||
if (localInvitedGroups.size() > 0) {
|
|
||||||
localInvitedGroups.remove(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localInvitedUsers.size() > 0 || (localInvitedGroups.size() > 0
|
|
||||||
&& currentUser.hasSpreedFeatureCapability("invite-groups-and-mails"))) {
|
|
||||||
if ((localInvitedGroups.size() > 0 && currentUser.hasSpreedFeatureCapability(
|
|
||||||
"invite-groups-and-mails"))) {
|
|
||||||
for (int i = 0; i < localInvitedGroups.size(); i++) {
|
|
||||||
final String groupId = localInvitedGroups.get(i);
|
|
||||||
retrofitBucket =
|
|
||||||
ApiUtils.getRetrofitBucketForAddGroupParticipant(currentUser.getBaseUrl(),
|
|
||||||
conversation.getToken(),
|
|
||||||
groupId);
|
|
||||||
|
|
||||||
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(new Observer<AddParticipantOverall>() {
|
|
||||||
@Override
|
|
||||||
public void onSubscribe(Disposable d) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNext(AddParticipantOverall addParticipantOverall) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable e) {
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
synchronized (localInvitedGroups) {
|
|
||||||
localInvitedGroups.remove(groupId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localInvitedGroups.size() == 0 && localInvitedUsers.size() == 0) {
|
|
||||||
initiateConversation(true, null);
|
|
||||||
}
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < localInvitedUsers.size(); i++) {
|
|
||||||
final String userId = invitedUsers.get(i);
|
|
||||||
retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipant(currentUser.getBaseUrl(),
|
|
||||||
conversation.getToken(),
|
|
||||||
userId);
|
|
||||||
|
|
||||||
ncApi.addParticipant(credentials, retrofitBucket.getUrl(), retrofitBucket.getQueryMap())
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.retry(1)
|
|
||||||
.subscribe(new Observer<AddParticipantOverall>() {
|
|
||||||
@Override
|
|
||||||
public void onSubscribe(Disposable d) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNext(AddParticipantOverall addParticipantOverall) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable e) {
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
synchronized (localInvitedUsers) {
|
|
||||||
localInvitedUsers.remove(userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (localInvitedGroups.size() == 0 && localInvitedUsers.size() == 0) {
|
|
||||||
initiateConversation(true, null);
|
|
||||||
}
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (!currentUser.hasSpreedFeatureCapability("chat-v2")) {
|
|
||||||
showResultImage(true, false);
|
|
||||||
} else {
|
|
||||||
initiateConversation(true, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initiateConversation(boolean dismissView, @Nullable Capabilities capabilities) {
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
boolean isGuestUser = false;
|
|
||||||
boolean hasChatCapability;
|
|
||||||
|
|
||||||
if (baseUrl != null && !baseUrl.equals(currentUser.getBaseUrl())) {
|
|
||||||
isGuestUser = true;
|
|
||||||
hasChatCapability = capabilities != null
|
|
||||||
&& capabilities.getSpreedCapability() != null
|
|
||||||
&& capabilities.getSpreedCapability().getFeatures() != null
|
|
||||||
&& capabilities.getSpreedCapability().getFeatures().contains("chat-v2");
|
|
||||||
} else {
|
|
||||||
hasChatCapability = currentUser.hasSpreedFeatureCapability("chat-v2");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasChatCapability) {
|
|
||||||
eventBus.post(new BottomSheetLockEvent(true, 0,
|
|
||||||
true, true, dismissView));
|
|
||||||
|
|
||||||
Intent conversationIntent = new Intent(getActivity(), MagicCallActivity.class);
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_ID(), conversation.getConversationId());
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(),
|
|
||||||
conversation.getDisplayName());
|
|
||||||
UserEntity conversationUser;
|
|
||||||
if (isGuestUser) {
|
|
||||||
conversationUser = new UserEntity();
|
|
||||||
conversationUser.setBaseUrl(baseUrl);
|
|
||||||
conversationUser.setUserId("?");
|
|
||||||
try {
|
|
||||||
conversationUser.setCapabilities(LoganSquare.serialize(capabilities));
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e("OperationsMenu", "Failed to serialize capabilities");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
conversationUser = currentUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), conversationUser);
|
|
||||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(),
|
|
||||||
Parcels.wrap(conversation));
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_PASSWORD(), callPassword);
|
|
||||||
|
|
||||||
conversationIntent.putExtras(bundle);
|
|
||||||
|
|
||||||
if (getParentController() != null) {
|
|
||||||
ConductorRemapping.INSTANCE.remapChatController(getParentController().getRouter(),
|
|
||||||
conversationUser.getId(),
|
|
||||||
conversation.getToken(), bundle, true);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
initiateCall();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initiateCall() {
|
|
||||||
eventBus.post(new BottomSheetLockEvent(true, 0, true, true));
|
|
||||||
Bundle bundle = new Bundle();
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_ROOM_TOKEN(), conversation.getToken());
|
|
||||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_USER_ENTITY(), currentUser);
|
|
||||||
if (baseUrl != null && !baseUrl.equals(currentUser.getBaseUrl())) {
|
|
||||||
bundle.putString(BundleKeys.INSTANCE.getKEY_MODIFIED_BASE_URL(), baseUrl);
|
|
||||||
}
|
|
||||||
bundle.putParcelable(BundleKeys.INSTANCE.getKEY_ACTIVE_CONVERSATION(),
|
|
||||||
Parcels.wrap(conversation));
|
|
||||||
|
|
||||||
if (getActivity() != null) {
|
|
||||||
|
|
||||||
Intent callIntent = new Intent(getActivity(), MagicCallActivity.class);
|
|
||||||
callIntent.putExtras(bundle);
|
|
||||||
|
|
||||||
InputMethodManager imm =
|
|
||||||
(InputMethodManager) getActivity().getSystemService(Activity.INPUT_METHOD_SERVICE);
|
|
||||||
if (imm != null) {
|
|
||||||
imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
new Handler().postDelayed(() -> getParentController().getRouter().popCurrentController(),
|
|
||||||
100);
|
|
||||||
startActivity(callIntent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class OperationsObserver implements Observer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSubscribe(Disposable d) {
|
|
||||||
disposable = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNext(Object o) {
|
|
||||||
if (operationCode != 99) {
|
|
||||||
showResultImage(true, false);
|
|
||||||
} else {
|
|
||||||
RoomOverall roomOverall = (RoomOverall) o;
|
|
||||||
conversation = roomOverall.getOcs().getData();
|
|
||||||
initiateConversation(true, serverCapabilities);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable e) {
|
|
||||||
if (operationCode != 99 || !(e instanceof HttpException)) {
|
|
||||||
showResultImage(false, false);
|
|
||||||
} else {
|
|
||||||
if (((HttpException) e).response().code() == 403) {
|
|
||||||
eventBus.post(new BottomSheetLockEvent(true, 0, false,
|
|
||||||
false));
|
|
||||||
ApplicationWideMessageHolder.getInstance()
|
|
||||||
.setMessageType(ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG);
|
|
||||||
getRouter().popCurrentController();
|
|
||||||
} else {
|
|
||||||
showResultImage(false, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onComplete() {
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,662 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Mario Danic
|
||||||
|
* Copyright (C) 2017 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.controllers.bottomsheet
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Intent
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.text.TextUtils
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.view.inputmethod.InputMethodManager
|
||||||
|
import android.widget.Button
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.ProgressBar
|
||||||
|
import android.widget.TextView
|
||||||
|
import butterknife.BindView
|
||||||
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||||
|
import com.bluelinelabs.logansquare.LoganSquare
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.activities.MagicCallActivity
|
||||||
|
import com.nextcloud.talk.api.NcApi
|
||||||
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
|
import com.nextcloud.talk.controllers.base.BaseController
|
||||||
|
import com.nextcloud.talk.events.BottomSheetLockEvent
|
||||||
|
import com.nextcloud.talk.models.RetrofitBucket
|
||||||
|
import com.nextcloud.talk.models.json.capabilities.Capabilities
|
||||||
|
import com.nextcloud.talk.models.json.capabilities.CapabilitiesOverall
|
||||||
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
|
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||||
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
|
import com.nextcloud.talk.models.json.participants.AddParticipantOverall
|
||||||
|
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
||||||
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
|
import com.nextcloud.talk.newarch.local.models.getCredentials
|
||||||
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
|
import com.nextcloud.talk.utils.ConductorRemapping
|
||||||
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
|
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||||
|
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
||||||
|
import io.reactivex.Observer
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.disposables.Disposable
|
||||||
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import java.io.IOException
|
||||||
|
import java.util.ArrayList
|
||||||
|
import org.greenrobot.eventbus.EventBus
|
||||||
|
import org.koin.android.ext.android.inject
|
||||||
|
import org.parceler.Parcels
|
||||||
|
import retrofit2.HttpException
|
||||||
|
|
||||||
|
class OperationsMenuController(args: Bundle) : BaseController() {
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.progress_bar)
|
||||||
|
internal var progressBar: ProgressBar? = null
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.result_image_view)
|
||||||
|
internal var resultImageView: ImageView? = null
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.result_text_view)
|
||||||
|
internal var resultsTextView: TextView? = null
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.ok_button)
|
||||||
|
internal var okButton: Button? = null
|
||||||
|
|
||||||
|
@JvmField @BindView(R.id.web_button)
|
||||||
|
internal var webButton: Button? = null
|
||||||
|
|
||||||
|
val ncApi: NcApi by inject()
|
||||||
|
val usersRepository: UsersRepository by inject()
|
||||||
|
|
||||||
|
private val operationCode: Int
|
||||||
|
private var conversation: Conversation? = null
|
||||||
|
|
||||||
|
private var currentUser: UserNgEntity? = null
|
||||||
|
private val callPassword: String
|
||||||
|
private val callUrl: String
|
||||||
|
|
||||||
|
private var baseUrl: String? = null
|
||||||
|
private var conversationToken: String? = null
|
||||||
|
|
||||||
|
private var disposable: Disposable? = null
|
||||||
|
|
||||||
|
private var conversationType: Conversation.ConversationType? = null
|
||||||
|
private var invitedUsers: ArrayList<String>? = ArrayList()
|
||||||
|
private var invitedGroups: ArrayList<String>? = ArrayList()
|
||||||
|
|
||||||
|
private var serverCapabilities: Capabilities? = null
|
||||||
|
private var credentials: String? = null
|
||||||
|
private val conversationName: String
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
this.operationCode = args.getInt(BundleKeys.KEY_OPERATION_CODE)
|
||||||
|
if (args.containsKey(BundleKeys.KEY_ROOM)) {
|
||||||
|
this.conversation = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_ROOM))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.callPassword = args.getString(BundleKeys.KEY_CONVERSATION_PASSWORD, "")
|
||||||
|
this.callUrl = args.getString(BundleKeys.KEY_CALL_URL, "")
|
||||||
|
|
||||||
|
if (args.containsKey(BundleKeys.KEY_INVITED_PARTICIPANTS)) {
|
||||||
|
this.invitedUsers = args.getStringArrayList(BundleKeys.KEY_INVITED_PARTICIPANTS)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.containsKey(BundleKeys.KEY_INVITED_GROUP)) {
|
||||||
|
this.invitedGroups = args.getStringArrayList(BundleKeys.KEY_INVITED_GROUP)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.containsKey(BundleKeys.KEY_CONVERSATION_TYPE)) {
|
||||||
|
this.conversationType = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_CONVERSATION_TYPE))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.containsKey(BundleKeys.KEY_SERVER_CAPABILITIES)) {
|
||||||
|
this.serverCapabilities = Parcels.unwrap(args.getParcelable(BundleKeys.KEY_SERVER_CAPABILITIES))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.conversationName = args.getString(BundleKeys.KEY_CONVERSATION_NAME, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||||
|
return inflater.inflate(R.layout.controller_operations_menu, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewBound(view: View) {
|
||||||
|
super.onViewBound(view)
|
||||||
|
processOperation()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processOperation() {
|
||||||
|
currentUser = usersRepository.getActiveUser()
|
||||||
|
val operationsObserver = OperationsObserver()
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(callUrl) && callUrl.contains("/call")) {
|
||||||
|
conversationToken = callUrl.substring(callUrl.lastIndexOf("/") + 1)
|
||||||
|
if (callUrl.contains("/index.php")) {
|
||||||
|
baseUrl = callUrl.substring(0, callUrl.indexOf("/index.php"))
|
||||||
|
} else {
|
||||||
|
baseUrl = callUrl.substring(0, callUrl.indexOf("/call"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentUser != null) {
|
||||||
|
credentials = currentUser!!.getCredentials()
|
||||||
|
|
||||||
|
if (!TextUtils.isEmpty(baseUrl) && baseUrl != currentUser!!.baseUrl) {
|
||||||
|
credentials = null
|
||||||
|
}
|
||||||
|
|
||||||
|
when (operationCode) {
|
||||||
|
2 -> ncApi.renameRoom(credentials,
|
||||||
|
ApiUtils.getRoom(currentUser!!.baseUrl, conversation!!.token),
|
||||||
|
conversation!!.name)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(operationsObserver)
|
||||||
|
3 -> ncApi.makeRoomPublic(credentials,
|
||||||
|
ApiUtils.getUrlForRoomVisibility(currentUser!!.baseUrl, conversation!!
|
||||||
|
.token))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(operationsObserver)
|
||||||
|
4, 5, 6 -> {
|
||||||
|
var pass: String? = ""
|
||||||
|
if (conversation!!.password != null) {
|
||||||
|
pass = conversation!!.password
|
||||||
|
}
|
||||||
|
ncApi.setPassword(credentials, ApiUtils.getUrlForPassword(currentUser!!.baseUrl,
|
||||||
|
conversation!!.token), pass)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(operationsObserver)
|
||||||
|
}
|
||||||
|
7 -> {
|
||||||
|
}
|
||||||
|
8 -> ncApi.makeRoomPrivate(credentials,
|
||||||
|
ApiUtils.getUrlForRoomVisibility(currentUser!!.baseUrl, conversation!!
|
||||||
|
.token))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(operationsObserver)
|
||||||
|
10 -> ncApi.getRoom(credentials, ApiUtils.getRoom(baseUrl, conversationToken))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(object : Observer<RoomOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
disposable = d
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(roomOverall: RoomOverall) {
|
||||||
|
conversation = roomOverall.ocs.data
|
||||||
|
fetchCapabilities(credentials)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
showResultImage(false, false)
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
11 -> {
|
||||||
|
val retrofitBucket: RetrofitBucket
|
||||||
|
var isGroupCallWorkaround = false
|
||||||
|
var invite: String? = null
|
||||||
|
|
||||||
|
if (invitedGroups!!.size > 0) {
|
||||||
|
invite = invitedGroups!![0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conversationType == Conversation.ConversationType.PUBLIC_CONVERSATION || !currentUser!!.hasSpreedFeatureCapability("empty-group-room")) {
|
||||||
|
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser!!.baseUrl,
|
||||||
|
"3", invite, conversationName)
|
||||||
|
} else {
|
||||||
|
var roomType = "2"
|
||||||
|
if (!currentUser!!.hasSpreedFeatureCapability("empty-group-room")) {
|
||||||
|
isGroupCallWorkaround = true
|
||||||
|
roomType = "3"
|
||||||
|
}
|
||||||
|
|
||||||
|
retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser!!.baseUrl,
|
||||||
|
roomType, invite, conversationName)
|
||||||
|
}
|
||||||
|
|
||||||
|
val isGroupCallWorkaroundFinal = isGroupCallWorkaround
|
||||||
|
ncApi.createRoom(credentials, retrofitBucket.url, retrofitBucket.queryMap)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(object : Observer<RoomOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(roomOverall: RoomOverall) {
|
||||||
|
conversation = roomOverall.ocs.data
|
||||||
|
|
||||||
|
ncApi.getRoom(credentials,
|
||||||
|
ApiUtils.getRoom(currentUser!!.baseUrl, conversation!!.token))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(object : Observer<RoomOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(roomOverall: RoomOverall) {
|
||||||
|
conversation = roomOverall.ocs.data
|
||||||
|
if (conversationType == Conversation.ConversationType.PUBLIC_CONVERSATION && isGroupCallWorkaroundFinal) {
|
||||||
|
performGroupCallWorkaround(credentials)
|
||||||
|
} else {
|
||||||
|
inviteUsersToAConversation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
showResultImage(false, false)
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
showResultImage(false, false)
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
97, 98 -> if (operationCode == 97) {
|
||||||
|
ncApi.removeConversationFromFavorites(credentials,
|
||||||
|
ApiUtils.getUrlForConversationFavorites(currentUser!!.baseUrl,
|
||||||
|
conversation!!.token))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(operationsObserver)
|
||||||
|
} else {
|
||||||
|
ncApi.addConversationToFavorites(credentials,
|
||||||
|
ApiUtils.getUrlForConversationFavorites(currentUser!!.baseUrl,
|
||||||
|
conversation!!.token))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(operationsObserver)
|
||||||
|
}
|
||||||
|
99 -> ncApi.joinRoom(credentials,
|
||||||
|
ApiUtils.getUrlForSettingMyselfAsActiveParticipant(baseUrl, conversationToken),
|
||||||
|
callPassword)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(operationsObserver)
|
||||||
|
else -> {
|
||||||
|
}
|
||||||
|
}// Operation 7 is sharing, so we handle this differently
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun performGroupCallWorkaround(credentials: String?) {
|
||||||
|
ncApi.makeRoomPrivate(credentials,
|
||||||
|
ApiUtils.getUrlForRoomVisibility(currentUser!!.baseUrl, conversation!!.token))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(object : Observer<GenericOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(genericOverall: GenericOverall) {
|
||||||
|
inviteUsersToAConversation()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
showResultImage(false, false)
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showResultImage(everythingOK: Boolean, isGuestSupportError: Boolean) {
|
||||||
|
progressBar!!.visibility = View.GONE
|
||||||
|
|
||||||
|
if (everythingOK) {
|
||||||
|
resultImageView!!.setImageDrawable(DisplayUtils.getTintedDrawable(resources!!, R.drawable
|
||||||
|
.ic_check_circle_black_24dp, R.color.nc_darkGreen))
|
||||||
|
} else {
|
||||||
|
resultImageView!!.setImageDrawable(DisplayUtils.getTintedDrawable(resources!!, R.drawable
|
||||||
|
.ic_cancel_black_24dp, R.color.nc_darkRed))
|
||||||
|
}
|
||||||
|
|
||||||
|
resultImageView!!.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
if (everythingOK) {
|
||||||
|
resultsTextView!!.setText(R.string.nc_all_ok_operation)
|
||||||
|
} else {
|
||||||
|
resultsTextView!!.setTextColor(resources!!.getColor(R.color.nc_darkRed))
|
||||||
|
if (!isGuestSupportError) {
|
||||||
|
resultsTextView!!.setText(R.string.nc_failed_to_perform_operation)
|
||||||
|
} else {
|
||||||
|
resultsTextView!!.setText(R.string.nc_failed_signaling_settings)
|
||||||
|
webButton!!.setOnClickListener { v ->
|
||||||
|
eventBus.post(BottomSheetLockEvent(true, 0, false, true))
|
||||||
|
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(callUrl))
|
||||||
|
startActivity(browserIntent)
|
||||||
|
BottomSheetLockEvent(true, 0, false, true)
|
||||||
|
}
|
||||||
|
webButton!!.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resultsTextView!!.visibility = View.VISIBLE
|
||||||
|
if (everythingOK) {
|
||||||
|
eventBus.post(BottomSheetLockEvent(true, 2500, true, true))
|
||||||
|
} else {
|
||||||
|
resultImageView!!.setImageDrawable(DisplayUtils.getTintedDrawable(resources!!, R.drawable
|
||||||
|
.ic_cancel_black_24dp, R.color.nc_darkRed))
|
||||||
|
okButton!!.setOnClickListener { v -> eventBus.post(BottomSheetLockEvent(true, 0, operationCode != 99 && operationCode != 10, true)) }
|
||||||
|
okButton!!.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun dispose() {
|
||||||
|
if (disposable != null && !disposable!!.isDisposed) {
|
||||||
|
disposable!!.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
disposable = null
|
||||||
|
}
|
||||||
|
|
||||||
|
public override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchCapabilities(credentials: String?) {
|
||||||
|
ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(object : Observer<CapabilitiesOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(capabilitiesOverall: CapabilitiesOverall) {
|
||||||
|
val hasChatV2Capability = capabilitiesOverall.ocs?.data?.capabilities?.spreedCapability?.features?.contains("chat-v2") == true
|
||||||
|
val hasGuestSignaling = capabilitiesOverall.ocs?.data?.capabilities?.spreedCapability?.features?.contains("guest-signaling") == true
|
||||||
|
|
||||||
|
if (hasChatV2Capability) {
|
||||||
|
if (conversation!!.hasPassword && conversation!!.isGuest) {
|
||||||
|
eventBus.post(BottomSheetLockEvent(true, 0,
|
||||||
|
true, false))
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation))
|
||||||
|
bundle.putString(BundleKeys.KEY_CALL_URL, callUrl)
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_SERVER_CAPABILITIES,
|
||||||
|
Parcels.wrap(capabilitiesOverall.ocs.data.capabilities))
|
||||||
|
bundle.putInt(BundleKeys.KEY_OPERATION_CODE, 99)
|
||||||
|
router.pushController(RouterTransaction.with(EntryMenuController(bundle))
|
||||||
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
|
.popChangeHandler(HorizontalChangeHandler()))
|
||||||
|
} else {
|
||||||
|
initiateConversation(false, capabilitiesOverall.ocs.data.capabilities)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (hasGuestSignaling) {
|
||||||
|
initiateCall()
|
||||||
|
} else {
|
||||||
|
showResultImage(false, true)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
showResultImage(false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun inviteUsersToAConversation() {
|
||||||
|
var retrofitBucket: RetrofitBucket
|
||||||
|
val localInvitedUsers = invitedUsers
|
||||||
|
val localInvitedGroups = invitedGroups
|
||||||
|
if (localInvitedGroups!!.size > 0) {
|
||||||
|
localInvitedGroups.removeAt(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localInvitedUsers!!.size > 0 || localInvitedGroups.size > 0 && currentUser!!.hasSpreedFeatureCapability("invite-groups-and-mails")) {
|
||||||
|
if (localInvitedGroups.size > 0 && currentUser!!.hasSpreedFeatureCapability(
|
||||||
|
"invite-groups-and-mails")) {
|
||||||
|
for (i in localInvitedGroups.indices) {
|
||||||
|
val groupId = localInvitedGroups[i]
|
||||||
|
retrofitBucket = ApiUtils.getRetrofitBucketForAddGroupParticipant(currentUser!!.baseUrl,
|
||||||
|
conversation!!.token,
|
||||||
|
groupId)
|
||||||
|
|
||||||
|
ncApi.addParticipant(credentials, retrofitBucket.url, retrofitBucket.queryMap)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(object : Observer<AddParticipantOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(addParticipantOverall: AddParticipantOverall) {}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
synchronized(localInvitedGroups) {
|
||||||
|
localInvitedGroups.remove(groupId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localInvitedGroups.size == 0 && localInvitedUsers.size == 0) {
|
||||||
|
initiateConversation(true, null)
|
||||||
|
}
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i in localInvitedUsers.indices) {
|
||||||
|
val userId = invitedUsers!![i]
|
||||||
|
retrofitBucket = ApiUtils.getRetrofitBucketForAddParticipant(currentUser!!.baseUrl,
|
||||||
|
conversation!!.token,
|
||||||
|
userId)
|
||||||
|
|
||||||
|
ncApi.addParticipant(credentials, retrofitBucket.url, retrofitBucket.queryMap)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.retry(1)
|
||||||
|
.subscribe(object : Observer<AddParticipantOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(addParticipantOverall: AddParticipantOverall) {}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
synchronized(localInvitedUsers) {
|
||||||
|
localInvitedUsers.remove(userId)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localInvitedGroups.size == 0 && localInvitedUsers.size == 0) {
|
||||||
|
initiateConversation(true, null)
|
||||||
|
}
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!currentUser!!.hasSpreedFeatureCapability("chat-v2")) {
|
||||||
|
showResultImage(true, false)
|
||||||
|
} else {
|
||||||
|
initiateConversation(true, null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initiateConversation(dismissView: Boolean, capabilities: Capabilities?) {
|
||||||
|
val bundle = Bundle()
|
||||||
|
var isGuestUser = false
|
||||||
|
val hasChatCapability: Boolean
|
||||||
|
|
||||||
|
if (baseUrl != null && baseUrl != currentUser!!.baseUrl) {
|
||||||
|
isGuestUser = true
|
||||||
|
hasChatCapability = capabilities?.spreedCapability?.features?.contains("chat-v2") == true
|
||||||
|
} else {
|
||||||
|
hasChatCapability = currentUser!!.hasSpreedFeatureCapability("chat-v2")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasChatCapability) {
|
||||||
|
eventBus.post(BottomSheetLockEvent(true, 0,
|
||||||
|
true, true, dismissView))
|
||||||
|
|
||||||
|
val conversationIntent = Intent(activity, MagicCallActivity::class.java)
|
||||||
|
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversation!!.token)
|
||||||
|
bundle.putString(BundleKeys.KEY_ROOM_ID, conversation!!.conversationId)
|
||||||
|
bundle.putString(BundleKeys.KEY_CONVERSATION_NAME,
|
||||||
|
conversation!!.displayName)
|
||||||
|
val conversationUser: UserNgEntity
|
||||||
|
if (isGuestUser) {
|
||||||
|
conversationUser = UserNgEntity(-1, "?", "?", baseUrl!!)
|
||||||
|
conversationUser.capabilities = capabilities!!
|
||||||
|
} else {
|
||||||
|
conversationUser = currentUser!!
|
||||||
|
}
|
||||||
|
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, conversationUser)
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION,
|
||||||
|
Parcels.wrap(conversation))
|
||||||
|
bundle.putString(BundleKeys.KEY_CONVERSATION_PASSWORD, callPassword)
|
||||||
|
|
||||||
|
conversationIntent.putExtras(bundle)
|
||||||
|
|
||||||
|
if (parentController != null) {
|
||||||
|
ConductorRemapping.remapChatController(parentController!!.router,
|
||||||
|
conversationUser.id!!,
|
||||||
|
conversation!!.token!!, bundle, true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
initiateCall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initiateCall() {
|
||||||
|
eventBus.post(BottomSheetLockEvent(true, 0, true, true))
|
||||||
|
val bundle = Bundle()
|
||||||
|
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, conversation!!.token)
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, currentUser)
|
||||||
|
if (baseUrl != null && baseUrl != currentUser!!.baseUrl) {
|
||||||
|
bundle.putString(BundleKeys.KEY_MODIFIED_BASE_URL, baseUrl)
|
||||||
|
}
|
||||||
|
bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION,
|
||||||
|
Parcels.wrap(conversation))
|
||||||
|
|
||||||
|
if (activity != null) {
|
||||||
|
|
||||||
|
val callIntent = Intent(activity, MagicCallActivity::class.java)
|
||||||
|
callIntent.putExtras(bundle)
|
||||||
|
|
||||||
|
val imm = activity!!.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
|
imm?.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0)
|
||||||
|
|
||||||
|
Handler().postDelayed({ parentController!!.router.popCurrentController() },
|
||||||
|
100)
|
||||||
|
startActivity(callIntent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inner class OperationsObserver : Observer<Any> {
|
||||||
|
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
disposable = d
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(o: Any) {
|
||||||
|
if (operationCode != 99) {
|
||||||
|
showResultImage(true, false)
|
||||||
|
} else {
|
||||||
|
val roomOverall = o as RoomOverall
|
||||||
|
conversation = roomOverall.ocs.data
|
||||||
|
initiateConversation(true, serverCapabilities)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
if (operationCode != 99 || e !is HttpException) {
|
||||||
|
showResultImage(false, false)
|
||||||
|
} else {
|
||||||
|
if (e.response()!!.code() == 403) {
|
||||||
|
eventBus.post(BottomSheetLockEvent(true, 0, false,
|
||||||
|
false))
|
||||||
|
ApplicationWideMessageHolder.getInstance()
|
||||||
|
.setMessageType(ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG)
|
||||||
|
router.popCurrentController()
|
||||||
|
} else {
|
||||||
|
showResultImage(false, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,6 @@ package com.nextcloud.talk.jobs
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.work.CoroutineWorker
|
import androidx.work.CoroutineWorker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import autodagger.AutoInjector
|
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.events.EventStatus
|
import com.nextcloud.talk.events.EventStatus
|
||||||
@ -43,7 +42,6 @@ import retrofit2.Retrofit
|
|||||||
import java.net.CookieManager
|
import java.net.CookieManager
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
class CapabilitiesWorker(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams), KoinComponent {
|
class CapabilitiesWorker(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams), KoinComponent {
|
||||||
val retrofit: Retrofit by inject()
|
val retrofit: Retrofit by inject()
|
||||||
val eventBus: EventBus by inject()
|
val eventBus: EventBus by inject()
|
||||||
|
@ -22,7 +22,6 @@ package com.nextcloud.talk.jobs
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.work.CoroutineWorker
|
import androidx.work.CoroutineWorker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import autodagger.AutoInjector
|
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
@ -45,7 +44,6 @@ import org.koin.core.inject
|
|||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import java.net.CookieManager
|
import java.net.CookieManager
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
class DeleteConversationWorker(context: Context,
|
class DeleteConversationWorker(context: Context,
|
||||||
workerParams: WorkerParameters) : CoroutineWorker(context, workerParams), KoinComponent {
|
workerParams: WorkerParameters) : CoroutineWorker(context, workerParams), KoinComponent {
|
||||||
val retrofit: Retrofit by inject()
|
val retrofit: Retrofit by inject()
|
||||||
@ -84,10 +82,4 @@ class DeleteConversationWorker(context: Context,
|
|||||||
}
|
}
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
sharedApplication
|
|
||||||
?.componentApplication
|
|
||||||
?.inject(this)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -22,7 +22,6 @@ package com.nextcloud.talk.jobs
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.work.Worker
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import autodagger.AutoInjector
|
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.events.EventStatus
|
import com.nextcloud.talk.events.EventStatus
|
||||||
@ -44,7 +43,6 @@ import org.koin.core.inject
|
|||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import java.net.CookieManager
|
import java.net.CookieManager
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
class LeaveConversationWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams), KoinComponent {
|
class LeaveConversationWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams), KoinComponent {
|
||||||
val retrofit: Retrofit by inject()
|
val retrofit: Retrofit by inject()
|
||||||
val okHttpClient: OkHttpClient by inject()
|
val okHttpClient: OkHttpClient by inject()
|
||||||
|
@ -47,22 +47,16 @@ import androidx.core.app.Person
|
|||||||
import androidx.core.graphics.drawable.IconCompat
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
import androidx.core.graphics.drawable.toBitmap
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import androidx.emoji.text.EmojiCompat
|
import androidx.emoji.text.EmojiCompat
|
||||||
import androidx.work.ListenableWorker.Result
|
|
||||||
import androidx.work.Worker
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import coil.Coil
|
import coil.Coil
|
||||||
import coil.target.Target
|
import coil.target.Target
|
||||||
import coil.transform.CircleCropTransformation
|
import coil.transform.CircleCropTransformation
|
||||||
import com.bluelinelabs.logansquare.LoganSquare
|
import com.bluelinelabs.logansquare.LoganSquare
|
||||||
import com.nextcloud.talk.R.color
|
import com.nextcloud.talk.R.*
|
||||||
import com.nextcloud.talk.R.dimen
|
|
||||||
import com.nextcloud.talk.R.drawable
|
|
||||||
import com.nextcloud.talk.R.string
|
|
||||||
import com.nextcloud.talk.activities.MagicCallActivity
|
import com.nextcloud.talk.activities.MagicCallActivity
|
||||||
import com.nextcloud.talk.activities.MainActivity
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
|
||||||
import com.nextcloud.talk.models.RingtoneSettings
|
import com.nextcloud.talk.models.RingtoneSettings
|
||||||
import com.nextcloud.talk.models.SignatureVerification
|
import com.nextcloud.talk.models.SignatureVerification
|
||||||
import com.nextcloud.talk.models.database.ArbitraryStorageEntity
|
import com.nextcloud.talk.models.database.ArbitraryStorageEntity
|
||||||
@ -77,7 +71,6 @@ import com.nextcloud.talk.models.json.push.NotificationUser
|
|||||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
import com.nextcloud.talk.newarch.local.models.getCredentials
|
import com.nextcloud.talk.newarch.local.models.getCredentials
|
||||||
import com.nextcloud.talk.newarch.local.models.hasSpreedFeatureCapability
|
|
||||||
import com.nextcloud.talk.newarch.utils.Images
|
import com.nextcloud.talk.newarch.utils.Images
|
||||||
import com.nextcloud.talk.newarch.utils.getCredentials
|
import com.nextcloud.talk.newarch.utils.getCredentials
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
@ -116,7 +109,7 @@ import java.net.CookieManager
|
|||||||
import java.security.InvalidKeyException
|
import java.security.InvalidKeyException
|
||||||
import java.security.NoSuchAlgorithmException
|
import java.security.NoSuchAlgorithmException
|
||||||
import java.security.PrivateKey
|
import java.security.PrivateKey
|
||||||
import java.util.HashMap
|
import java.util.*
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
import java.util.zip.CRC32
|
import java.util.zip.CRC32
|
||||||
import javax.crypto.Cipher
|
import javax.crypto.Cipher
|
||||||
|
@ -52,7 +52,7 @@ class ShareOperationWorker(
|
|||||||
private val baseUrl: String
|
private val baseUrl: String
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
for (i in filesArray.indices) {
|
for (i in filesArray.indices) {
|
||||||
ncApi!!.createRemoteShare(
|
ncApi.createRemoteShare(
|
||||||
credentials,
|
credentials,
|
||||||
ApiUtils.getSharingUrl(baseUrl),
|
ApiUtils.getSharingUrl(baseUrl),
|
||||||
filesArray[i],
|
filesArray[i],
|
||||||
|
@ -24,7 +24,6 @@ import androidx.work.CoroutineWorker
|
|||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import autodagger.AutoInjector
|
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
@ -44,7 +43,6 @@ import org.greenrobot.eventbus.EventBus
|
|||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
import org.koin.core.inject
|
import org.koin.core.inject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class SignalingSettingsWorker(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams), KoinComponent {
|
class SignalingSettingsWorker(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams), KoinComponent {
|
||||||
val ncApi: NcApi by inject()
|
val ncApi: NcApi by inject()
|
||||||
@ -65,7 +63,7 @@ class SignalingSettingsWorker(context: Context, workerParams: WorkerParameters)
|
|||||||
for (i in userEntityList.indices) {
|
for (i in userEntityList.indices) {
|
||||||
userEntity = userEntityList[i]
|
userEntity = userEntityList[i]
|
||||||
val finalUserEntity: UserNgEntity? = userEntity
|
val finalUserEntity: UserNgEntity? = userEntity
|
||||||
ncApi!!.getSignalingSettings(
|
ncApi.getSignalingSettings(
|
||||||
userEntity!!.getCredentials(),
|
userEntity!!.getCredentials(),
|
||||||
ApiUtils.getUrlForSignalingSettings(userEntity.baseUrl))
|
ApiUtils.getUrlForSignalingSettings(userEntity.baseUrl))
|
||||||
.blockingSubscribe(object : Observer<SignalingSettingsOverall> {
|
.blockingSubscribe(object : Observer<SignalingSettingsOverall> {
|
||||||
|
@ -27,11 +27,9 @@ import android.util.Log
|
|||||||
import androidx.work.ListenableWorker
|
import androidx.work.ListenableWorker
|
||||||
import androidx.work.Worker
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import autodagger.AutoInjector
|
|
||||||
import com.bluelinelabs.logansquare.LoganSquare
|
import com.bluelinelabs.logansquare.LoganSquare
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.models.ExternalSignalingServer
|
import com.nextcloud.talk.models.ExternalSignalingServer
|
||||||
import com.nextcloud.talk.models.database.UserEntity
|
|
||||||
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||||
@ -39,9 +37,7 @@ import com.nextcloud.talk.webrtc.WebSocketConnectionHelper
|
|||||||
import org.koin.core.KoinComponent
|
import org.koin.core.KoinComponent
|
||||||
import org.koin.core.inject
|
import org.koin.core.inject
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
class WebsocketConnectionsWorker(
|
class WebsocketConnectionsWorker(
|
||||||
context: Context,
|
context: Context,
|
||||||
workerParams: WorkerParameters
|
workerParams: WorkerParameters
|
||||||
@ -50,10 +46,6 @@ class WebsocketConnectionsWorker(
|
|||||||
val usersRepository: UsersRepository by inject()
|
val usersRepository: UsersRepository by inject()
|
||||||
|
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
NextcloudTalkApplication.sharedApplication!!
|
|
||||||
.componentApplication
|
|
||||||
.inject(this)
|
|
||||||
|
|
||||||
val userEntityList = usersRepository.getUsers()
|
val userEntityList = usersRepository.getUsers()
|
||||||
var userEntity: UserNgEntity
|
var userEntity: UserNgEntity
|
||||||
for (i in userEntityList.indices) {
|
for (i in userEntityList.indices) {
|
||||||
|
@ -60,76 +60,5 @@ public interface User extends Parcelable, Persistable, Serializable {
|
|||||||
boolean getCurrent();
|
boolean getCurrent();
|
||||||
|
|
||||||
boolean getScheduledForDeletion();
|
boolean getScheduledForDeletion();
|
||||||
|
|
||||||
default boolean hasNotificationsCapability(String capabilityName) {
|
|
||||||
if (getCapabilities() != null) {
|
|
||||||
try {
|
|
||||||
Capabilities capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
|
|
||||||
if (capabilities.getNotificationsCapability() != null
|
|
||||||
&& capabilities.getNotificationsCapability().getFeatures() != null) {
|
|
||||||
return capabilities.getSpreedCapability().getFeatures().contains(capabilityName);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Failed to get capabilities for the user");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean hasExternalCapability(String capabilityName) {
|
|
||||||
if (getCapabilities() != null) {
|
|
||||||
try {
|
|
||||||
Capabilities capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
|
|
||||||
if (capabilities.getExternalCapability() != null && capabilities.getExternalCapability()
|
|
||||||
.containsKey("v1")) {
|
|
||||||
return capabilities.getExternalCapability().get("v1").contains("capabilityName");
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Failed to get capabilities for the user");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean hasSpreedFeatureCapability(String capabilityName) {
|
|
||||||
if (getCapabilities() != null) {
|
|
||||||
try {
|
|
||||||
Capabilities capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
|
|
||||||
if (capabilities != null && 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
default int getMessageMaxLength() {
|
|
||||||
if (getCapabilities() != null) {
|
|
||||||
Capabilities capabilities = null;
|
|
||||||
try {
|
|
||||||
capabilities = LoganSquare.parse(getCapabilities(), Capabilities.class);
|
|
||||||
if (capabilities != null
|
|
||||||
&& capabilities.getSpreedCapability() != null
|
|
||||||
&& capabilities.getSpreedCapability().getConfig() != null
|
|
||||||
&& capabilities.getSpreedCapability().getConfig().containsKey("chat")) {
|
|
||||||
HashMap<String, String> chatConfigHashMap =
|
|
||||||
capabilities.getSpreedCapability().getConfig().get("chat");
|
|
||||||
if (chatConfigHashMap != null && chatConfigHashMap.containsKey("max-length")) {
|
|
||||||
int chatSize = Integer.parseInt(chatConfigHashMap.get("max-length"));
|
|
||||||
if (chatSize > 0) {
|
|
||||||
return chatSize;
|
|
||||||
} else {
|
|
||||||
return 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -31,5 +31,5 @@ import org.parceler.Parcel;
|
|||||||
@JsonObject
|
@JsonObject
|
||||||
public class NotificationsCapability {
|
public class NotificationsCapability {
|
||||||
@JsonField(name = "ocs-endpoints")
|
@JsonField(name = "ocs-endpoints")
|
||||||
List<String> features;
|
public List<String> features;
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ package com.nextcloud.talk.newarch.data.repository.online
|
|||||||
|
|
||||||
import com.nextcloud.talk.models.database.UserEntity
|
import com.nextcloud.talk.models.database.UserEntity
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
|
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||||
import com.nextcloud.talk.newarch.data.source.remote.ApiService
|
import com.nextcloud.talk.newarch.data.source.remote.ApiService
|
||||||
import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository
|
import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository
|
||||||
@ -52,6 +53,10 @@ class NextcloudTalkRepositoryImpl(private val apiService: ApiService) : Nextclou
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun getConversationForUser(userEntity: UserNgEntity, conversationToken: String): RoomOverall {
|
||||||
|
return apiService.getConversation(userEntity.getCredentials(), conversationToken)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun setFavoriteValueForConversation(
|
override suspend fun setFavoriteValueForConversation(
|
||||||
user: UserNgEntity,
|
user: UserNgEntity,
|
||||||
conversation: Conversation,
|
conversation: Conversation,
|
||||||
|
@ -62,5 +62,5 @@ interface ApiService {
|
|||||||
): GenericOverall
|
): GenericOverall
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
suspend fun getRoom(@Header("Authorization") authorization: String, @Url url: String): RoomOverall
|
suspend fun getConversation(@Header("Authorization") authorization: String, @Url url: String): RoomOverall
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ val StorageModule = module {
|
|||||||
single { createMessagesRepository(get()) }
|
single { createMessagesRepository(get()) }
|
||||||
single { createUsersRepository(get()) }
|
single { createUsersRepository(get()) }
|
||||||
single { createArbitraryStorageUtils(get()) }
|
single { createArbitraryStorageUtils(get()) }
|
||||||
|
single { createUserUtils(get()) }
|
||||||
single { TalkDatabase.getInstance(androidApplication()) }
|
single { TalkDatabase.getInstance(androidApplication()) }
|
||||||
single { get<TalkDatabase>().conversationsDao() }
|
single { get<TalkDatabase>().conversationsDao() }
|
||||||
single { get<TalkDatabase>().messagesDao() }
|
single { get<TalkDatabase>().messagesDao() }
|
||||||
@ -93,3 +93,7 @@ fun createDataStore(sqlCipherDatabaseSource: SqlCipherDatabaseSource): ReactiveE
|
|||||||
fun createArbitraryStorageUtils(dataStore: ReactiveEntityStore<Persistable>): ArbitraryStorageUtils {
|
fun createArbitraryStorageUtils(dataStore: ReactiveEntityStore<Persistable>): ArbitraryStorageUtils {
|
||||||
return ArbitraryStorageUtils(dataStore)
|
return ArbitraryStorageUtils(dataStore)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createUserUtils(dataStore: ReactiveEntityStore<Persistable>): UserUtils {
|
||||||
|
return UserUtils(dataStore)
|
||||||
|
}
|
@ -44,8 +44,8 @@ interface NextcloudTalkRepository {
|
|||||||
conversation: Conversation
|
conversation: Conversation
|
||||||
): GenericOverall
|
): GenericOverall
|
||||||
|
|
||||||
suspend fun getRoomForUser(
|
suspend fun getConversationForUser(
|
||||||
userEntity: UserNgEntity,
|
userEntity: UserNgEntity,
|
||||||
roomToken: String
|
conversationToken: String
|
||||||
): RoomOverall
|
): RoomOverall
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,12 @@ import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkReposito
|
|||||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCase
|
import com.nextcloud.talk.newarch.domain.usecases.base.UseCase
|
||||||
import org.koin.core.parameter.DefinitionParameters
|
import org.koin.core.parameter.DefinitionParameters
|
||||||
|
|
||||||
class GetRoomUseCase constructor(
|
class GetConversationUseCase constructor(
|
||||||
private val nextcloudTalkRepository: NextcloudTalkRepository,
|
private val nextcloudTalkRepository: NextcloudTalkRepository,
|
||||||
apiErrorHandler: ApiErrorHandler?
|
apiErrorHandler: ApiErrorHandler?
|
||||||
) : UseCase<RoomOverall, Any?>(apiErrorHandler) {
|
) : UseCase<RoomOverall, Any?>(apiErrorHandler) {
|
||||||
override suspend fun run(params: Any?): RoomOverall {
|
override suspend fun run(params: Any?): RoomOverall {
|
||||||
val definitionParameters = params as DefinitionParameters
|
val definitionParameters = params as DefinitionParameters
|
||||||
return nextcloudTalkRepository.getRoomForUser(definitionParameters[0], definitionParameters[1])
|
return nextcloudTalkRepository.getConversationForUser(definitionParameters[0], definitionParameters[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -32,7 +32,7 @@ import com.nextcloud.talk.newarch.local.models.MessageEntity
|
|||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
abstract class MessagesDao {
|
abstract class MessagesDao {
|
||||||
@Query("SELECT * FROM messages WHERE conversation = :conversationId")
|
@Query("SELECT * FROM messages WHERE conversation_id = :conversationId")
|
||||||
abstract fun getMessagesWithUserForConversation(conversationId: String):
|
abstract fun getMessagesWithUserForConversation(conversationId: String):
|
||||||
LiveData<List<MessageEntity>>
|
LiveData<List<MessageEntity>>
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType
|
|||||||
|
|
||||||
@Entity(
|
@Entity(
|
||||||
tableName = "messages",
|
tableName = "messages",
|
||||||
indices = [Index(value = ["conversation"])],
|
indices = [Index(value = ["conversation_id"])],
|
||||||
foreignKeys = [ForeignKey(
|
foreignKeys = [ForeignKey(
|
||||||
entity = ConversationEntity::class,
|
entity = ConversationEntity::class,
|
||||||
parentColumns = arrayOf("id"),
|
parentColumns = arrayOf("id"),
|
||||||
|
@ -76,7 +76,7 @@ class MentionAutocompletePresenter : RecyclerViewPresenter<Mention?>, FlexibleAd
|
|||||||
""
|
""
|
||||||
}
|
}
|
||||||
adapter!!.setFilter(queryString)
|
adapter!!.setFilter(queryString)
|
||||||
ncApi!!.getMentionAutocompleteSuggestions(
|
ncApi.getMentionAutocompleteSuggestions(
|
||||||
currentUser!!.getCredentials(), ApiUtils.getUrlForMentionSuggestions(currentUser!!.baseUrl, roomToken),
|
currentUser!!.getCredentials(), ApiUtils.getUrlForMentionSuggestions(currentUser!!.baseUrl, roomToken),
|
||||||
queryString, 5)
|
queryString, 5)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
|
@ -215,7 +215,7 @@ class PushUtils(val usersRepository: UsersRepository): KoinComponent {
|
|||||||
userEntity.username, userEntity.token
|
userEntity.username, userEntity.token
|
||||||
)
|
)
|
||||||
val finalCredentials = credentials
|
val finalCredentials = credentials
|
||||||
ncApi!!.registerDeviceForNotificationsWithNextcloud(
|
ncApi.registerDeviceForNotificationsWithNextcloud(
|
||||||
credentials,
|
credentials,
|
||||||
ApiUtils.getUrlNextcloudPush(userEntity.baseUrl),
|
ApiUtils.getUrlNextcloudPush(userEntity.baseUrl),
|
||||||
queryMap
|
queryMap
|
||||||
@ -232,7 +232,7 @@ class PushUtils(val usersRepository: UsersRepository): KoinComponent {
|
|||||||
.data.signature
|
.data.signature
|
||||||
proxyMap["userPublicKey"] = pushRegistrationOverall.ocs
|
proxyMap["userPublicKey"] = pushRegistrationOverall.ocs
|
||||||
.data.publicKey
|
.data.publicKey
|
||||||
ncApi!!.registerDeviceForNotificationsWithProxy(
|
ncApi.registerDeviceForNotificationsWithProxy(
|
||||||
ApiUtils.getUrlPushProxy(), proxyMap
|
ApiUtils.getUrlPushProxy(), proxyMap
|
||||||
)
|
)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
|
@ -22,6 +22,7 @@ package com.nextcloud.talk.utils.database.arbitrarystorage;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.nextcloud.talk.models.database.ArbitraryStorage;
|
import com.nextcloud.talk.models.database.ArbitraryStorage;
|
||||||
import com.nextcloud.talk.models.database.ArbitraryStorageEntity;
|
import com.nextcloud.talk.models.database.ArbitraryStorageEntity;
|
||||||
|
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import io.requery.Persistable;
|
import io.requery.Persistable;
|
||||||
|
@ -24,9 +24,8 @@ import android.text.TextUtils;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import com.nextcloud.talk.models.database.User;
|
import com.nextcloud.talk.models.database.User;
|
||||||
import com.nextcloud.talk.models.database.UserEntity;
|
import com.nextcloud.talk.models.database.UserEntity;
|
||||||
import io.reactivex.Completable;
|
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
import io.requery.Persistable;
|
import io.requery.Persistable;
|
||||||
import io.requery.query.Result;
|
import io.requery.query.Result;
|
||||||
@ -52,29 +51,6 @@ public class UserUtils {
|
|||||||
return findUsersQueryResult.toList();
|
return findUsersQueryResult.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List getUsersScheduledForDeletion() {
|
|
||||||
Result findUsersQueryResult =
|
|
||||||
dataStore.select(User.class).where(UserEntity.SCHEDULED_FOR_DELETION.eq(true))
|
|
||||||
.get();
|
|
||||||
|
|
||||||
return findUsersQueryResult.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserEntity getAnyUserAndSetAsActive() {
|
|
||||||
Result findUserQueryResult = dataStore.select(User.class)
|
|
||||||
.where(UserEntity.SCHEDULED_FOR_DELETION.notEqual(true))
|
|
||||||
.limit(1).get();
|
|
||||||
|
|
||||||
UserEntity userEntity;
|
|
||||||
if ((userEntity = (UserEntity) findUserQueryResult.firstOrNull()) != null) {
|
|
||||||
userEntity.setCurrent(true);
|
|
||||||
dataStore.update(userEntity).blockingGet();
|
|
||||||
return userEntity;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserEntity getCurrentUser() {
|
public UserEntity getCurrentUser() {
|
||||||
Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.CURRENT.eq(true)
|
Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.CURRENT.eq(true)
|
||||||
.and(UserEntity.SCHEDULED_FOR_DELETION.notEqual(true)))
|
.and(UserEntity.SCHEDULED_FOR_DELETION.notEqual(true)))
|
||||||
@ -83,33 +59,6 @@ public class UserUtils {
|
|||||||
return (UserEntity) findUserQueryResult.firstOrNull();
|
return (UserEntity) findUserQueryResult.firstOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Completable deleteUser(long internalId) {
|
|
||||||
Result findUserQueryResult =
|
|
||||||
dataStore.select(User.class).where(UserEntity.ID.eq(internalId)).limit(1).get();
|
|
||||||
|
|
||||||
UserEntity user = (UserEntity) findUserQueryResult.firstOrNull();
|
|
||||||
|
|
||||||
return dataStore.delete(user)
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Completable deleteUserWithId(long id) {
|
|
||||||
Result findUserQueryResult =
|
|
||||||
dataStore.select(User.class).where(UserEntity.ID.eq(id)).limit(1).get();
|
|
||||||
|
|
||||||
UserEntity user = (UserEntity) findUserQueryResult.firstOrNull();
|
|
||||||
|
|
||||||
return dataStore.delete(user)
|
|
||||||
.subscribeOn(Schedulers.io());
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserEntity getUserById(String id) {
|
|
||||||
Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.USER_ID.eq(id))
|
|
||||||
.limit(1).get();
|
|
||||||
|
|
||||||
return (UserEntity) findUserQueryResult.firstOrNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserEntity getUserWithId(long id) {
|
public UserEntity getUserWithId(long id) {
|
||||||
Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.ID.eq(id))
|
Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.ID.eq(id))
|
||||||
@ -118,61 +67,6 @@ public class UserUtils {
|
|||||||
return (UserEntity) findUserQueryResult.firstOrNull();
|
return (UserEntity) findUserQueryResult.firstOrNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disableAllUsersWithoutId(long userId) {
|
|
||||||
Result findUserQueryResult =
|
|
||||||
dataStore.select(User.class).where(UserEntity.ID.notEqual(userId)).get();
|
|
||||||
|
|
||||||
for (Object object : findUserQueryResult) {
|
|
||||||
UserEntity userEntity = (UserEntity) object;
|
|
||||||
userEntity.setCurrent(false);
|
|
||||||
dataStore.update(userEntity).blockingGet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean checkIfUserIsScheduledForDeletion(String username, String server) {
|
|
||||||
Result findUserQueryResult =
|
|
||||||
dataStore.select(User.class).where(UserEntity.USERNAME.eq(username))
|
|
||||||
.and(UserEntity.BASE_URL.eq(server))
|
|
||||||
.limit(1).get();
|
|
||||||
|
|
||||||
UserEntity userEntity;
|
|
||||||
if ((userEntity = (UserEntity) findUserQueryResult.firstOrNull()) != null) {
|
|
||||||
return userEntity.getScheduledForDeletion();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)))
|
|
||||||
.limit(1).get();
|
|
||||||
|
|
||||||
return findUserQueryResult.firstOrNull() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean scheduleUserForDeletionWithId(long id) {
|
|
||||||
Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.ID.eq(id))
|
|
||||||
.limit(1).get();
|
|
||||||
|
|
||||||
UserEntity userEntity;
|
|
||||||
if ((userEntity = (UserEntity) findUserQueryResult.firstOrNull()) != null) {
|
|
||||||
userEntity.setScheduledForDeletion(true);
|
|
||||||
userEntity.setCurrent(false);
|
|
||||||
dataStore.update(userEntity).blockingGet();
|
|
||||||
}
|
|
||||||
|
|
||||||
return getAnyUserAndSetAsActive() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Observable<UserEntity> createOrUpdateUser(@Nullable String username,
|
public Observable<UserEntity> createOrUpdateUser(@Nullable String username,
|
||||||
@Nullable String token,
|
@Nullable String token,
|
||||||
@Nullable String serverUrl,
|
@Nullable String serverUrl,
|
||||||
|
@ -97,7 +97,7 @@ class DatabaseStorageModule(
|
|||||||
"always" -> 1
|
"always" -> 1
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
ncApi!!.setNotificationLevel(
|
ncApi.setNotificationLevel(
|
||||||
ApiUtils.getCredentials(
|
ApiUtils.getCredentials(
|
||||||
conversationUser.username,
|
conversationUser.username,
|
||||||
conversationUser.token
|
conversationUser.token
|
||||||
@ -124,7 +124,7 @@ class DatabaseStorageModule(
|
|||||||
}
|
}
|
||||||
} else if (key == "conversation_password") {
|
} else if (key == "conversation_password") {
|
||||||
if (hasPassword != null) {
|
if (hasPassword != null) {
|
||||||
ncApi!!.setPassword(
|
ncApi.setPassword(
|
||||||
ApiUtils.getCredentials(
|
ApiUtils.getCredentials(
|
||||||
conversationUser.username,
|
conversationUser.username,
|
||||||
conversationUser.token
|
conversationUser.token
|
||||||
@ -153,7 +153,7 @@ class DatabaseStorageModule(
|
|||||||
conversationNameValue
|
conversationNameValue
|
||||||
) && conversationNameValue != value
|
) && conversationNameValue != value
|
||||||
) {
|
) {
|
||||||
ncApi!!.renameRoom(
|
ncApi.renameRoom(
|
||||||
ApiUtils.getCredentials(
|
ApiUtils.getCredentials(
|
||||||
conversationUser.username,
|
conversationUser.username,
|
||||||
conversationUser.token
|
conversationUser.token
|
||||||
|
@ -54,7 +54,7 @@ class MagicPeerConnectionWrapper(peerConnectionFactory: PeerConnectionFactory,
|
|||||||
var peerConnection: PeerConnection?
|
var peerConnection: PeerConnection?
|
||||||
private set
|
private set
|
||||||
var sessionId: String
|
var sessionId: String
|
||||||
private var nick: String? = null
|
public var nick: String? = null
|
||||||
private val sdpConstraints: MediaConstraints
|
private val sdpConstraints: MediaConstraints
|
||||||
private var magicDataChannel: DataChannel? = null
|
private var magicDataChannel: DataChannel? = null
|
||||||
val magicSdpObserver: MagicSdpObserver
|
val magicSdpObserver: MagicSdpObserver
|
||||||
@ -129,18 +129,6 @@ class MagicPeerConnectionWrapper(peerConnectionFactory: PeerConnectionFactory,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNick(): String? {
|
|
||||||
return if (!TextUtils.isEmpty(nick)) {
|
|
||||||
nick
|
|
||||||
} else {
|
|
||||||
context.resources.getString(R.string.nc_nick_guest)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setNick(nick: String?) {
|
|
||||||
this.nick = nick
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun sendInitialMediaStatus() {
|
private fun sendInitialMediaStatus() {
|
||||||
if (localMediaStream != null) {
|
if (localMediaStream != null) {
|
||||||
if (localMediaStream.videoTracks.size == 1 && localMediaStream.videoTracks[0]
|
if (localMediaStream.videoTracks.size == 1 && localMediaStream.videoTracks[0]
|
||||||
@ -201,9 +189,9 @@ class MagicPeerConnectionWrapper(peerConnectionFactory: PeerConnectionFactory,
|
|||||||
if (dataChannelMessage.payload is String) {
|
if (dataChannelMessage.payload is String) {
|
||||||
internalNick = dataChannelMessage.payload as String
|
internalNick = dataChannelMessage.payload as String
|
||||||
if (internalNick != nick) {
|
if (internalNick != nick) {
|
||||||
setNick(nick)
|
nick = internalNick
|
||||||
EventBus.getDefault()
|
EventBus.getDefault()
|
||||||
.post(PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType.NICK_CHANGE, sessionId, getNick(), null, videoStreamType))
|
.post(PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType.NICK_CHANGE, sessionId, nick, null, videoStreamType))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (dataChannelMessage.payload != null) {
|
if (dataChannelMessage.payload != null) {
|
||||||
|
@ -22,7 +22,6 @@ package com.nextcloud.talk.webrtc
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import autodagger.AutoInjector
|
|
||||||
import com.bluelinelabs.logansquare.LoganSquare
|
import com.bluelinelabs.logansquare.LoganSquare
|
||||||
import com.nextcloud.talk.R.string
|
import com.nextcloud.talk.R.string
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
@ -58,9 +57,7 @@ import org.koin.core.inject
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
|
||||||
class MagicWebSocketInstance internal constructor(
|
class MagicWebSocketInstance internal constructor(
|
||||||
conversationUser: UserNgEntity,
|
conversationUser: UserNgEntity,
|
||||||
connectionUrl: String,
|
connectionUrl: String,
|
||||||
@ -513,9 +510,6 @@ class MagicWebSocketInstance internal constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
sharedApplication
|
|
||||||
?.componentApplication
|
|
||||||
?.inject(this)
|
|
||||||
this.connectionUrl = connectionUrl
|
this.connectionUrl = connectionUrl
|
||||||
this.conversationUser = conversationUser
|
this.conversationUser = conversationUser
|
||||||
this.webSocketTicket = webSocketTicket
|
this.webSocketTicket = webSocketTicket
|
||||||
|
Loading…
Reference in New Issue
Block a user