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,
|
||||
"database": {
|
||||
"version": 1,
|
||||
"identityHash": "95ddaea30271abd3160e1cdc8ab404d5",
|
||||
"identityHash": "26585a95894baebb7d811a80f3811b85",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "conversations",
|
||||
@ -261,7 +261,16 @@
|
||||
],
|
||||
"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": [
|
||||
{
|
||||
"table": "conversations",
|
||||
@ -360,7 +369,7 @@
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"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.Window
|
||||
import android.view.WindowManager
|
||||
import autodagger.AutoInjector
|
||||
import butterknife.BindView
|
||||
import butterknife.ButterKnife
|
||||
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.utils.bundle.BundleKeys
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class MagicCallActivity : BaseActivity() {
|
||||
|
||||
@BindView(R.id.controller_container)
|
||||
@ -50,7 +48,6 @@ class MagicCallActivity : BaseActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
window.addFlags(
|
||||
|
@ -30,7 +30,6 @@ import coil.api.load
|
||||
import coil.transform.CircleCropTransformation
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.models.database.UserEntity
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.models.json.conversations.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.DavResponse;
|
||||
import com.nextcloud.talk.dagger.modules.RestModule;
|
||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity;
|
||||
import com.nextcloud.talk.newarch.utils.NetworkUtils;
|
||||
import com.nextcloud.talk.utils.ApiUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -49,7 +49,7 @@ public class ReadFilesystemOperation {
|
||||
OkHttpClient.Builder okHttpClientBuilder = okHttpClient.newBuilder();
|
||||
okHttpClientBuilder.followRedirects(false);
|
||||
okHttpClientBuilder.followSslRedirects(false);
|
||||
okHttpClientBuilder.authenticator(new RestModule.MagicAuthenticator(
|
||||
okHttpClientBuilder.authenticator(new NetworkUtils.MagicAuthenticator(
|
||||
ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()),
|
||||
"Authorization"));
|
||||
this.okHttpClient = okHttpClientBuilder.build();
|
||||
|
@ -151,7 +151,7 @@ class AccountVerificationController(args: Bundle?) : BaseController(), KoinCompo
|
||||
queryUrl = "http://" + baseUrl + ApiUtils.getUrlPostfixForStatus()
|
||||
}
|
||||
|
||||
ncApi!!.getServerStatus(queryUrl)
|
||||
ncApi.getServerStatus(queryUrl)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.`as`<ObservableSubscribeProxy<Status>>(AutoDispose.autoDisposable(scopeProvider))
|
||||
@ -194,7 +194,7 @@ class AccountVerificationController(args: Bundle?) : BaseController(), KoinCompo
|
||||
}
|
||||
|
||||
private fun findServerTalkApp(credentials: String?) {
|
||||
ncApi!!.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
|
||||
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.`as`<ObservableSubscribeProxy<RoomsOverall>>(AutoDispose.autoDisposable(scopeProvider))
|
||||
.subscribe(object : Observer<RoomsOverall> {
|
||||
@ -250,7 +250,7 @@ class AccountVerificationController(args: Bundle?) : BaseController(), KoinCompo
|
||||
}
|
||||
|
||||
private fun fetchProfile(credentials: String?) {
|
||||
ncApi!!.getUserProfile(credentials,
|
||||
ncApi.getUserProfile(credentials,
|
||||
ApiUtils.getUrlForUserProfile(baseUrl))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.`as`<ObservableSubscribeProxy<UserProfileOverall>>(AutoDispose.autoDisposable(scopeProvider))
|
||||
|
@ -46,7 +46,7 @@ import android.widget.ProgressBar
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import autodagger.AutoInjector
|
||||
|
||||
import butterknife.BindView
|
||||
import butterknife.OnClick
|
||||
import butterknife.OnLongClick
|
||||
@ -110,7 +110,6 @@ import java.util.HashMap
|
||||
import java.util.HashSet
|
||||
import java.util.Objects
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import me.zhanghai.android.effortlesspermissions.AfterPermissionDenied
|
||||
import me.zhanghai.android.effortlesspermissions.EffortlessPermissions
|
||||
import me.zhanghai.android.effortlesspermissions.OpenAppDetailsDialogFragment
|
||||
@ -393,7 +392,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
}
|
||||
|
||||
private fun handleFromNotification() {
|
||||
ncApi!!.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
|
||||
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(baseUrl))
|
||||
.retry(3)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -943,7 +942,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
}
|
||||
|
||||
private fun fetchSignalingSettings() {
|
||||
ncApi!!.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(baseUrl))
|
||||
ncApi.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(baseUrl))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.retry(3)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -1046,7 +1045,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
}
|
||||
|
||||
private fun checkCapabilities() {
|
||||
ncApi!!.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
|
||||
ncApi.getCapabilities(credentials, ApiUtils.getUrlForCapabilities(baseUrl))
|
||||
.retry(3)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -1092,7 +1091,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
}
|
||||
|
||||
private fun joinRoomAndCall() {
|
||||
ncApi!!.joinRoom(
|
||||
ncApi.joinRoom(
|
||||
credentials, ApiUtils.getUrlForSettingMyselfAsActiveParticipant(
|
||||
baseUrl,
|
||||
roomToken
|
||||
@ -1131,7 +1130,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
}
|
||||
|
||||
private fun performCall() {
|
||||
ncApi!!.joinCall(
|
||||
ncApi.joinCall(
|
||||
credentials,
|
||||
ApiUtils.getUrlForCall(baseUrl, roomToken)
|
||||
)
|
||||
@ -1148,7 +1147,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
setCallState(CallStatus.ESTABLISHED)
|
||||
|
||||
if (needsPing) {
|
||||
ncApi!!.pingCall(credentials, ApiUtils.getUrlForCallPing(baseUrl, roomToken))
|
||||
ncApi.pingCall(credentials, ApiUtils.getUrlForCallPing(baseUrl, roomToken))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.repeatWhen { observable -> observable.delay(5000, TimeUnit.MILLISECONDS) }
|
||||
@ -1193,7 +1192,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
}
|
||||
|
||||
if (!hasExternalSignalingServer) {
|
||||
ncApi!!.pullSignalingMessages(
|
||||
ncApi.pullSignalingMessages(
|
||||
credentials,
|
||||
ApiUtils.getUrlForSignaling(baseUrl, urlToken)
|
||||
)
|
||||
@ -1393,7 +1392,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
)
|
||||
|
||||
if (magicPeerConnectionWrapper.peerConnection != null) {
|
||||
magicPeerConnectionWrapper.peerConnection
|
||||
magicPeerConnectionWrapper.peerConnection!!
|
||||
.setRemoteDescription(
|
||||
magicPeerConnectionWrapper
|
||||
.magicSdpObserver, sessionDescriptionWithPreferredCodec
|
||||
@ -1474,7 +1473,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
}
|
||||
|
||||
private fun hangupNetworkCalls(shutDownView: Boolean) {
|
||||
ncApi!!.leaveCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
|
||||
ncApi.leaveCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Observer<GenericOverall> {
|
||||
@ -1509,7 +1508,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
}
|
||||
|
||||
private fun leaveRoom(shutDownView: Boolean) {
|
||||
ncApi!!.leaveRoom(
|
||||
ncApi.leaveRoom(
|
||||
credentials,
|
||||
ApiUtils.getUrlForSettingMyselfAsActiveParticipant(baseUrl, roomToken)
|
||||
)
|
||||
@ -1603,7 +1602,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
}
|
||||
|
||||
private fun getPeersForCall() {
|
||||
ncApi!!.getPeersForCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
|
||||
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(baseUrl, roomToken))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.subscribe(object : Observer<ParticipantsOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
@ -1660,25 +1659,25 @@ class CallController(args: Bundle) : BaseController() {
|
||||
if (hasMCU && publisher) {
|
||||
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
||||
peerConnectionFactory!!,
|
||||
iceServers, sdpConstraintsForMCU, sessionId, callSession, localMediaStream, true, true,
|
||||
iceServers, sdpConstraintsForMCU!!, sessionId, callSession, localMediaStream, true, true,
|
||||
type
|
||||
)
|
||||
} else if (hasMCU) {
|
||||
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
||||
peerConnectionFactory!!,
|
||||
iceServers, sdpConstraints, sessionId, callSession, null, false, true, type
|
||||
iceServers, sdpConstraints!!, sessionId, callSession, null, false, true, type
|
||||
)
|
||||
} else {
|
||||
if ("screen" != type) {
|
||||
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
||||
peerConnectionFactory!!,
|
||||
iceServers, sdpConstraints, sessionId, callSession, localMediaStream, false, false,
|
||||
iceServers, sdpConstraints!!, sessionId, callSession, localMediaStream, false, false,
|
||||
type
|
||||
)
|
||||
} else {
|
||||
magicPeerConnectionWrapper = MagicPeerConnectionWrapper(
|
||||
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
|
||||
}
|
||||
|
||||
ncApi!!.sendSignalingMessages(
|
||||
ncApi.sendSignalingMessages(
|
||||
credentials, ApiUtils.getUrlForSignaling(baseUrl, urlToken),
|
||||
strings.toString()
|
||||
)
|
||||
@ -2134,7 +2133,7 @@ class CallController(args: Bundle) : BaseController() {
|
||||
} else {
|
||||
gotNick(
|
||||
session,
|
||||
getPeerConnectionWrapperForSessionIdAndType(session, type, false).nick, false,
|
||||
getPeerConnectionWrapperForSessionIdAndType(session, type, false).nick!!, false,
|
||||
type
|
||||
)
|
||||
}
|
||||
|
@ -184,7 +184,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
||||
}
|
||||
|
||||
private fun checkIfAnyParticipantsRemainInRoom() {
|
||||
ncApi!!.getPeersForCall(
|
||||
ncApi.getPeersForCall(
|
||||
credentials, ApiUtils.getUrlForParticipants(
|
||||
userBeingCalled!!.baseUrl,
|
||||
currentConversation!!.token
|
||||
@ -232,7 +232,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
||||
}
|
||||
|
||||
private fun handleFromNotification() {
|
||||
ncApi!!.getRooms(credentials, ApiUtils.getUrlForGetRooms(userBeingCalled!!.baseUrl))
|
||||
ncApi.getRooms(credentials, ApiUtils.getUrlForGetRooms(userBeingCalled!!.baseUrl))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.retry(3)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -401,8 +401,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr
|
||||
transformations(CircleCropTransformation())
|
||||
listener(onSuccess = { data, dataSource ->
|
||||
GlobalScope.launch {
|
||||
if ((AvatarStatusCodeHolder.getInstance().statusCode == 200 || AvatarStatusCodeHolder.getInstance().statusCode == 0)
|
||||
&& userBeingCalled.hasSpreedFeatureCapability("no-ping")) {
|
||||
if ((AvatarStatusCodeHolder.getInstance().statusCode == 200 || AvatarStatusCodeHolder.getInstance().statusCode == 0)) {
|
||||
|
||||
if (activity != null) {
|
||||
val newBitmap = BlurTransformation(activity!!, 5f).transform(
|
||||
|
@ -46,7 +46,7 @@ import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import androidx.work.Data
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import autodagger.AutoInjector
|
||||
|
||||
import butterknife.BindView
|
||||
import butterknife.OnClick
|
||||
import butterknife.Optional
|
||||
@ -99,7 +99,6 @@ import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
import java.util.HashMap
|
||||
import java.util.HashSet
|
||||
import javax.inject.Inject
|
||||
|
||||
class ContactsController : BaseController,
|
||||
SearchView.OnQueryTextListener,
|
||||
@ -222,9 +221,6 @@ class ContactsController : BaseController,
|
||||
|
||||
override fun onViewBound(view: View) {
|
||||
super.onViewBound(view)
|
||||
NextcloudTalkApplication.sharedApplication!!
|
||||
.componentApplication
|
||||
.inject(this)
|
||||
|
||||
currentUser = usersRepository.getActiveUser()
|
||||
|
||||
@ -278,7 +274,7 @@ class ContactsController : BaseController,
|
||||
currentUser!!.baseUrl, roomType,
|
||||
userId, null
|
||||
)
|
||||
ncApi!!.createRoom(
|
||||
ncApi.createRoom(
|
||||
credentials,
|
||||
retrofitBucket.url, retrofitBucket.queryMap
|
||||
)
|
||||
@ -304,7 +300,7 @@ class ContactsController : BaseController,
|
||||
)
|
||||
|
||||
if (currentUser!!.hasSpreedFeatureCapability("chat-v2")) {
|
||||
ncApi!!.getRoom(
|
||||
ncApi.getRoom(
|
||||
credentials,
|
||||
ApiUtils.getRoom(
|
||||
currentUser!!.baseUrl,
|
||||
@ -509,7 +505,7 @@ class ContactsController : BaseController,
|
||||
}
|
||||
|
||||
val finalServerIs14OrUp = serverIs14OrUp
|
||||
ncApi!!.getContactsWithSearchParam(
|
||||
ncApi.getContactsWithSearchParam(
|
||||
credentials,
|
||||
retrofitBucket.url, shareTypesList, modifiedQueryMap
|
||||
)
|
||||
@ -854,7 +850,7 @@ class ContactsController : BaseController,
|
||||
userItem.model.userId, null
|
||||
)
|
||||
|
||||
ncApi!!.createRoom(
|
||||
ncApi.createRoom(
|
||||
credentials,
|
||||
retrofitBucket.url, retrofitBucket.queryMap
|
||||
)
|
||||
|
@ -38,7 +38,7 @@ 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 coil.api.load
|
||||
@ -99,11 +99,10 @@ import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.greenrobot.eventbus.Subscribe
|
||||
import org.greenrobot.eventbus.ThreadMode
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.util.ArrayList
|
||||
import java.util.Calendar
|
||||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
FlexibleAdapter.OnItemClickListener, ConversationInfoInterface {
|
||||
|
||||
@ -168,10 +167,7 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
@BindView(R.id.shareAction)
|
||||
lateinit var shareAction: MaterialStandardPreference
|
||||
|
||||
@set:Inject
|
||||
lateinit var ncApi: NcApi
|
||||
@set:Inject
|
||||
lateinit var userUtils: UserUtils
|
||||
val ncApi: NcApi by inject()
|
||||
|
||||
private val conversationToken: String?
|
||||
private val conversationUser: UserNgEntity?
|
||||
@ -201,7 +197,6 @@ class ConversationInfoController(args: Bundle) : BaseController(),
|
||||
|
||||
init {
|
||||
setHasOptionsMenu(true)
|
||||
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
|
||||
conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY)
|
||||
conversationToken = args.getString(BundleKeys.KEY_ROOM_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.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import autodagger.AutoInjector
|
||||
|
||||
import butterknife.BindView
|
||||
import butterknife.OnClick
|
||||
import com.bluelinelabs.conductor.RouterTransaction
|
||||
@ -55,13 +55,15 @@ import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
|
||||
import com.uber.autodispose.AutoDispose
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
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 studio.carbonylgroup.textfieldboxes.ExtendedEditText
|
||||
import studio.carbonylgroup.textfieldboxes.TextFieldBoxes
|
||||
import java.security.cert.CertificateException
|
||||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class ServerSelectionController : BaseController() {
|
||||
@JvmField
|
||||
@BindView(R.id.extended_edit_text)
|
||||
@ -119,65 +121,70 @@ class ServerSelectionController : BaseController() {
|
||||
&& TextUtils.isEmpty(resources!!.getString(R.string.nc_import_account_type))) {
|
||||
providersTextView!!.visibility = View.INVISIBLE
|
||||
} else {
|
||||
val users = usersRepository.getUsers()
|
||||
val usersSize = users.count()
|
||||
if ((TextUtils.isEmpty(resources!!.getString(R.string.nc_import_account_type)) ||
|
||||
findAccounts(users).isEmpty()) &&
|
||||
usersSize == 0) {
|
||||
providersTextView!!.setText(R.string.nc_get_from_provider)
|
||||
providersTextView!!.setOnClickListener { view12: View? ->
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(resources!!
|
||||
.getString(R.string.nc_providers_url)))
|
||||
startActivity(browserIntent)
|
||||
}
|
||||
} else if (findAccounts(users).isNotEmpty()) {
|
||||
if (!TextUtils.isEmpty(getAppNameBasedOnPackage(resources!!
|
||||
.getString(R.string.nc_import_accounts_from)))) {
|
||||
if (findAccounts(users).size > 1) {
|
||||
providersTextView!!.text = String.format(resources!!.getString(R.string.nc_server_import_accounts),
|
||||
getAppNameBasedOnPackage(resources!!
|
||||
.getString(R.string.nc_import_accounts_from)))
|
||||
GlobalScope.launch {
|
||||
val users = usersRepository.getUsers()
|
||||
val usersSize = users.count()
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
if ((TextUtils.isEmpty(resources!!.getString(R.string.nc_import_account_type)) ||
|
||||
findAccounts(users).isEmpty()) &&
|
||||
usersSize == 0) {
|
||||
providersTextView!!.setText(R.string.nc_get_from_provider)
|
||||
providersTextView!!.setOnClickListener { view12: View? ->
|
||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(resources!!
|
||||
.getString(R.string.nc_providers_url)))
|
||||
startActivity(browserIntent)
|
||||
}
|
||||
} else if (findAccounts(users).isNotEmpty()) {
|
||||
if (!TextUtils.isEmpty(getAppNameBasedOnPackage(resources!!
|
||||
.getString(R.string.nc_import_accounts_from)))) {
|
||||
if (findAccounts(users).size > 1) {
|
||||
providersTextView!!.text = String.format(resources!!.getString(R.string.nc_server_import_accounts),
|
||||
getAppNameBasedOnPackage(resources!!
|
||||
.getString(R.string.nc_import_accounts_from)))
|
||||
} else {
|
||||
providersTextView!!.text = String.format(resources!!.getString(R.string.nc_server_import_account),
|
||||
getAppNameBasedOnPackage(resources!!
|
||||
.getString(R.string.nc_import_accounts_from)))
|
||||
}
|
||||
} else {
|
||||
if (findAccounts(users).size > 1) {
|
||||
providersTextView!!.text = resources!!.getString(R.string.nc_server_import_accounts_plain)
|
||||
} else {
|
||||
providersTextView!!.text = resources!!.getString(R.string.nc_server_import_account_plain)
|
||||
}
|
||||
}
|
||||
providersTextView!!.setOnClickListener { view13: View? ->
|
||||
val bundle = Bundle()
|
||||
bundle.putBoolean(KEY_IS_ACCOUNT_IMPORT, true)
|
||||
router.pushController(RouterTransaction.with(
|
||||
SwitchAccountController(bundle))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler()))
|
||||
}
|
||||
} else {
|
||||
providersTextView!!.text = String.format(resources!!.getString(R.string.nc_server_import_account),
|
||||
getAppNameBasedOnPackage(resources!!
|
||||
.getString(R.string.nc_import_accounts_from)))
|
||||
}
|
||||
} else {
|
||||
if (findAccounts(users).size > 1) {
|
||||
providersTextView!!.text = resources!!.getString(R.string.nc_server_import_accounts_plain)
|
||||
} else {
|
||||
providersTextView!!.text = resources!!.getString(R.string.nc_server_import_account_plain)
|
||||
providersTextView!!.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
providersTextView!!.setOnClickListener { view13: View? ->
|
||||
val bundle = Bundle()
|
||||
bundle.putBoolean(KEY_IS_ACCOUNT_IMPORT, true)
|
||||
router.pushController(RouterTransaction.with(
|
||||
SwitchAccountController(bundle))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler()))
|
||||
}
|
||||
} else {
|
||||
providersTextView!!.visibility = View.INVISIBLE
|
||||
}
|
||||
}
|
||||
serverEntry!!.requestFocus()
|
||||
serverEntry!!.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||
override fun afterTextChanged(editable: Editable) {
|
||||
if (!textFieldBoxes!!.isOnError && !TextUtils.isEmpty(serverEntry!!.text)) {
|
||||
toggleProceedButton(true)
|
||||
} else {
|
||||
toggleProceedButton(false)
|
||||
serverEntry!!.requestFocus()
|
||||
serverEntry!!.addTextChangedListener(object : TextWatcher {
|
||||
override fun beforeTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||
override fun onTextChanged(charSequence: CharSequence, i: Int, i1: Int, i2: Int) {}
|
||||
override fun afterTextChanged(editable: Editable) {
|
||||
if (!textFieldBoxes!!.isOnError && !TextUtils.isEmpty(serverEntry!!.text)) {
|
||||
toggleProceedButton(true)
|
||||
} else {
|
||||
toggleProceedButton(false)
|
||||
}
|
||||
}
|
||||
})
|
||||
serverEntry!!.setOnEditorActionListener { textView: TextView?, i: Int, keyEvent: KeyEvent? ->
|
||||
if (i == EditorInfo.IME_ACTION_DONE) {
|
||||
checkServerAndProceed()
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
})
|
||||
serverEntry!!.setOnEditorActionListener { textView: TextView?, i: Int, keyEvent: KeyEvent? ->
|
||||
if (i == EditorInfo.IME_ACTION_DONE) {
|
||||
checkServerAndProceed()
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,7 +217,7 @@ class ServerSelectionController : BaseController() {
|
||||
}
|
||||
|
||||
private fun checkServer(queryUrl: String, checkForcedHttps: Boolean) {
|
||||
ncApi!!.getServerStatus(queryUrl)
|
||||
ncApi.getServerStatus(queryUrl)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.`as`(AutoDispose.autoDisposable(scopeProvider))
|
||||
|
@ -43,7 +43,7 @@ import androidx.core.view.ViewCompat
|
||||
import androidx.emoji.widget.EmojiTextView
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import autodagger.AutoInjector
|
||||
|
||||
import butterknife.BindView
|
||||
import butterknife.OnClick
|
||||
import coil.api.load
|
||||
@ -97,7 +97,6 @@ import java.util.ArrayList
|
||||
import java.util.Arrays
|
||||
import java.util.Locale
|
||||
import java.util.Objects
|
||||
import javax.inject.Inject
|
||||
|
||||
class SettingsController : BaseController() {
|
||||
@JvmField
|
||||
@ -176,7 +175,6 @@ class SettingsController : BaseController() {
|
||||
@JvmField
|
||||
@BindView(R.id.message_text)
|
||||
var messageText: TextView? = null
|
||||
@JvmField
|
||||
val ncApi: NcApi by inject()
|
||||
val usersRepository: UsersRepository by inject()
|
||||
private var saveStateHandler: LovelySaveStateHandler? = null
|
||||
@ -599,7 +597,7 @@ class SettingsController : BaseController() {
|
||||
|
||||
loadAvatarImage()
|
||||
|
||||
ncApi!!.getUserProfile(
|
||||
ncApi.getUserProfile(
|
||||
credentials,
|
||||
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 androidx.annotation.RequiresApi
|
||||
import androidx.appcompat.app.ActionBar
|
||||
import autodagger.AutoInjector
|
||||
|
||||
import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.controllers.AccountVerificationController
|
||||
@ -47,7 +47,6 @@ import org.greenrobot.eventbus.EventBus
|
||||
import org.koin.android.ext.android.inject
|
||||
import java.util.ArrayList
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
abstract class BaseController : ButterKnifeController(), ComponentCallbacks {
|
||||
|
||||
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 androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkerParameters
|
||||
import autodagger.AutoInjector
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.events.EventStatus
|
||||
@ -43,7 +42,6 @@ import retrofit2.Retrofit
|
||||
import java.net.CookieManager
|
||||
import java.util.*
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class CapabilitiesWorker(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams), KoinComponent {
|
||||
val retrofit: Retrofit by inject()
|
||||
val eventBus: EventBus by inject()
|
||||
|
@ -22,7 +22,6 @@ package com.nextcloud.talk.jobs
|
||||
import android.content.Context
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkerParameters
|
||||
import autodagger.AutoInjector
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||
@ -45,7 +44,6 @@ import org.koin.core.inject
|
||||
import retrofit2.Retrofit
|
||||
import java.net.CookieManager
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class DeleteConversationWorker(context: Context,
|
||||
workerParams: WorkerParameters) : CoroutineWorker(context, workerParams), KoinComponent {
|
||||
val retrofit: Retrofit by inject()
|
||||
@ -84,10 +82,4 @@ class DeleteConversationWorker(context: Context,
|
||||
}
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
init {
|
||||
sharedApplication
|
||||
?.componentApplication
|
||||
?.inject(this)
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@ package com.nextcloud.talk.jobs
|
||||
import android.content.Context
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import autodagger.AutoInjector
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
import com.nextcloud.talk.events.EventStatus
|
||||
@ -44,7 +43,6 @@ import org.koin.core.inject
|
||||
import retrofit2.Retrofit
|
||||
import java.net.CookieManager
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class LeaveConversationWorker(context: Context, workerParams: WorkerParameters) : Worker(context, workerParams), KoinComponent {
|
||||
val retrofit: Retrofit 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.toBitmap
|
||||
import androidx.emoji.text.EmojiCompat
|
||||
import androidx.work.ListenableWorker.Result
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import coil.Coil
|
||||
import coil.target.Target
|
||||
import coil.transform.CircleCropTransformation
|
||||
import com.bluelinelabs.logansquare.LoganSquare
|
||||
import com.nextcloud.talk.R.color
|
||||
import com.nextcloud.talk.R.dimen
|
||||
import com.nextcloud.talk.R.drawable
|
||||
import com.nextcloud.talk.R.string
|
||||
import com.nextcloud.talk.R.*
|
||||
import com.nextcloud.talk.activities.MagicCallActivity
|
||||
import com.nextcloud.talk.activities.MainActivity
|
||||
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.SignatureVerification
|
||||
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.local.models.UserNgEntity
|
||||
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.getCredentials
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
@ -116,7 +109,7 @@ import java.net.CookieManager
|
||||
import java.security.InvalidKeyException
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.security.PrivateKey
|
||||
import java.util.HashMap
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
import java.util.zip.CRC32
|
||||
import javax.crypto.Cipher
|
||||
|
@ -52,7 +52,7 @@ class ShareOperationWorker(
|
||||
private val baseUrl: String
|
||||
override fun doWork(): Result {
|
||||
for (i in filesArray.indices) {
|
||||
ncApi!!.createRemoteShare(
|
||||
ncApi.createRemoteShare(
|
||||
credentials,
|
||||
ApiUtils.getSharingUrl(baseUrl),
|
||||
filesArray[i],
|
||||
|
@ -24,7 +24,6 @@ import androidx.work.CoroutineWorker
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import autodagger.AutoInjector
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
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.inject
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class SignalingSettingsWorker(context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams), KoinComponent {
|
||||
val ncApi: NcApi by inject()
|
||||
@ -65,7 +63,7 @@ class SignalingSettingsWorker(context: Context, workerParams: WorkerParameters)
|
||||
for (i in userEntityList.indices) {
|
||||
userEntity = userEntityList[i]
|
||||
val finalUserEntity: UserNgEntity? = userEntity
|
||||
ncApi!!.getSignalingSettings(
|
||||
ncApi.getSignalingSettings(
|
||||
userEntity!!.getCredentials(),
|
||||
ApiUtils.getUrlForSignalingSettings(userEntity.baseUrl))
|
||||
.blockingSubscribe(object : Observer<SignalingSettingsOverall> {
|
||||
|
@ -27,11 +27,9 @@ import android.util.Log
|
||||
import androidx.work.ListenableWorker
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import autodagger.AutoInjector
|
||||
import com.bluelinelabs.logansquare.LoganSquare
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
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.local.models.UserNgEntity
|
||||
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.inject
|
||||
import java.io.IOException
|
||||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class WebsocketConnectionsWorker(
|
||||
context: Context,
|
||||
workerParams: WorkerParameters
|
||||
@ -50,10 +46,6 @@ class WebsocketConnectionsWorker(
|
||||
val usersRepository: UsersRepository by inject()
|
||||
|
||||
override fun doWork(): Result {
|
||||
NextcloudTalkApplication.sharedApplication!!
|
||||
.componentApplication
|
||||
.inject(this)
|
||||
|
||||
val userEntityList = usersRepository.getUsers()
|
||||
var userEntity: UserNgEntity
|
||||
for (i in userEntityList.indices) {
|
||||
|
@ -60,76 +60,5 @@ public interface User extends Parcelable, Persistable, Serializable {
|
||||
boolean getCurrent();
|
||||
|
||||
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
|
||||
public class NotificationsCapability {
|
||||
@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.json.conversations.Conversation
|
||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||
import com.nextcloud.talk.newarch.data.source.remote.ApiService
|
||||
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(
|
||||
user: UserNgEntity,
|
||||
conversation: Conversation,
|
||||
|
@ -62,5 +62,5 @@ interface ApiService {
|
||||
): GenericOverall
|
||||
|
||||
@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 { createUsersRepository(get()) }
|
||||
single { createArbitraryStorageUtils(get()) }
|
||||
|
||||
single { createUserUtils(get()) }
|
||||
single { TalkDatabase.getInstance(androidApplication()) }
|
||||
single { get<TalkDatabase>().conversationsDao() }
|
||||
single { get<TalkDatabase>().messagesDao() }
|
||||
@ -93,3 +93,7 @@ fun createDataStore(sqlCipherDatabaseSource: SqlCipherDatabaseSource): ReactiveE
|
||||
fun createArbitraryStorageUtils(dataStore: ReactiveEntityStore<Persistable>): ArbitraryStorageUtils {
|
||||
return ArbitraryStorageUtils(dataStore)
|
||||
}
|
||||
|
||||
fun createUserUtils(dataStore: ReactiveEntityStore<Persistable>): UserUtils {
|
||||
return UserUtils(dataStore)
|
||||
}
|
@ -44,8 +44,8 @@ interface NextcloudTalkRepository {
|
||||
conversation: Conversation
|
||||
): GenericOverall
|
||||
|
||||
suspend fun getRoomForUser(
|
||||
suspend fun getConversationForUser(
|
||||
userEntity: UserNgEntity,
|
||||
roomToken: String
|
||||
conversationToken: String
|
||||
): RoomOverall
|
||||
}
|
||||
|
@ -6,12 +6,12 @@ import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkReposito
|
||||
import com.nextcloud.talk.newarch.domain.usecases.base.UseCase
|
||||
import org.koin.core.parameter.DefinitionParameters
|
||||
|
||||
class GetRoomUseCase constructor(
|
||||
class GetConversationUseCase constructor(
|
||||
private val nextcloudTalkRepository: NextcloudTalkRepository,
|
||||
apiErrorHandler: ApiErrorHandler?
|
||||
) : UseCase<RoomOverall, Any?>(apiErrorHandler) {
|
||||
override suspend fun run(params: Any?): RoomOverall {
|
||||
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
|
||||
abstract class MessagesDao {
|
||||
@Query("SELECT * FROM messages WHERE conversation = :conversationId")
|
||||
@Query("SELECT * FROM messages WHERE conversation_id = :conversationId")
|
||||
abstract fun getMessagesWithUserForConversation(conversationId: String):
|
||||
LiveData<List<MessageEntity>>
|
||||
|
||||
|
@ -35,7 +35,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType
|
||||
|
||||
@Entity(
|
||||
tableName = "messages",
|
||||
indices = [Index(value = ["conversation"])],
|
||||
indices = [Index(value = ["conversation_id"])],
|
||||
foreignKeys = [ForeignKey(
|
||||
entity = ConversationEntity::class,
|
||||
parentColumns = arrayOf("id"),
|
||||
|
@ -76,7 +76,7 @@ class MentionAutocompletePresenter : RecyclerViewPresenter<Mention?>, FlexibleAd
|
||||
""
|
||||
}
|
||||
adapter!!.setFilter(queryString)
|
||||
ncApi!!.getMentionAutocompleteSuggestions(
|
||||
ncApi.getMentionAutocompleteSuggestions(
|
||||
currentUser!!.getCredentials(), ApiUtils.getUrlForMentionSuggestions(currentUser!!.baseUrl, roomToken),
|
||||
queryString, 5)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
@ -215,7 +215,7 @@ class PushUtils(val usersRepository: UsersRepository): KoinComponent {
|
||||
userEntity.username, userEntity.token
|
||||
)
|
||||
val finalCredentials = credentials
|
||||
ncApi!!.registerDeviceForNotificationsWithNextcloud(
|
||||
ncApi.registerDeviceForNotificationsWithNextcloud(
|
||||
credentials,
|
||||
ApiUtils.getUrlNextcloudPush(userEntity.baseUrl),
|
||||
queryMap
|
||||
@ -232,7 +232,7 @@ class PushUtils(val usersRepository: UsersRepository): KoinComponent {
|
||||
.data.signature
|
||||
proxyMap["userPublicKey"] = pushRegistrationOverall.ocs
|
||||
.data.publicKey
|
||||
ncApi!!.registerDeviceForNotificationsWithProxy(
|
||||
ncApi.registerDeviceForNotificationsWithProxy(
|
||||
ApiUtils.getUrlPushProxy(), proxyMap
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
@ -22,6 +22,7 @@ package com.nextcloud.talk.utils.database.arbitrarystorage;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.nextcloud.talk.models.database.ArbitraryStorage;
|
||||
import com.nextcloud.talk.models.database.ArbitraryStorageEntity;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.requery.Persistable;
|
||||
|
@ -24,9 +24,8 @@ import android.text.TextUtils;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.nextcloud.talk.models.database.User;
|
||||
import com.nextcloud.talk.models.database.UserEntity;
|
||||
import io.reactivex.Completable;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import io.requery.Persistable;
|
||||
import io.requery.query.Result;
|
||||
@ -52,29 +51,6 @@ public class UserUtils {
|
||||
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() {
|
||||
Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.CURRENT.eq(true)
|
||||
.and(UserEntity.SCHEDULED_FOR_DELETION.notEqual(true)))
|
||||
@ -83,33 +59,6 @@ public class UserUtils {
|
||||
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) {
|
||||
Result findUserQueryResult = dataStore.select(User.class).where(UserEntity.ID.eq(id))
|
||||
@ -118,72 +67,17 @@ public class UserUtils {
|
||||
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,
|
||||
@Nullable String token,
|
||||
@Nullable String serverUrl,
|
||||
@Nullable String displayName,
|
||||
@Nullable String pushConfigurationState,
|
||||
@Nullable Boolean currentUser,
|
||||
@Nullable String userId,
|
||||
@Nullable Long internalId,
|
||||
@Nullable String capabilities,
|
||||
@Nullable String certificateAlias,
|
||||
@Nullable String externalSignalingServer) {
|
||||
@Nullable String token,
|
||||
@Nullable String serverUrl,
|
||||
@Nullable String displayName,
|
||||
@Nullable String pushConfigurationState,
|
||||
@Nullable Boolean currentUser,
|
||||
@Nullable String userId,
|
||||
@Nullable Long internalId,
|
||||
@Nullable String capabilities,
|
||||
@Nullable String certificateAlias,
|
||||
@Nullable String externalSignalingServer) {
|
||||
Result findUserQueryResult;
|
||||
if (internalId == null) {
|
||||
findUserQueryResult = dataStore.select(User.class).where(UserEntity.USERNAME.eq(username).
|
||||
|
@ -97,7 +97,7 @@ class DatabaseStorageModule(
|
||||
"always" -> 1
|
||||
else -> 0
|
||||
}
|
||||
ncApi!!.setNotificationLevel(
|
||||
ncApi.setNotificationLevel(
|
||||
ApiUtils.getCredentials(
|
||||
conversationUser.username,
|
||||
conversationUser.token
|
||||
@ -124,7 +124,7 @@ class DatabaseStorageModule(
|
||||
}
|
||||
} else if (key == "conversation_password") {
|
||||
if (hasPassword != null) {
|
||||
ncApi!!.setPassword(
|
||||
ncApi.setPassword(
|
||||
ApiUtils.getCredentials(
|
||||
conversationUser.username,
|
||||
conversationUser.token
|
||||
@ -153,7 +153,7 @@ class DatabaseStorageModule(
|
||||
conversationNameValue
|
||||
) && conversationNameValue != value
|
||||
) {
|
||||
ncApi!!.renameRoom(
|
||||
ncApi.renameRoom(
|
||||
ApiUtils.getCredentials(
|
||||
conversationUser.username,
|
||||
conversationUser.token
|
||||
|
@ -54,7 +54,7 @@ class MagicPeerConnectionWrapper(peerConnectionFactory: PeerConnectionFactory,
|
||||
var peerConnection: PeerConnection?
|
||||
private set
|
||||
var sessionId: String
|
||||
private var nick: String? = null
|
||||
public var nick: String? = null
|
||||
private val sdpConstraints: MediaConstraints
|
||||
private var magicDataChannel: DataChannel? = null
|
||||
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() {
|
||||
if (localMediaStream != null) {
|
||||
if (localMediaStream.videoTracks.size == 1 && localMediaStream.videoTracks[0]
|
||||
@ -201,9 +189,9 @@ class MagicPeerConnectionWrapper(peerConnectionFactory: PeerConnectionFactory,
|
||||
if (dataChannelMessage.payload is String) {
|
||||
internalNick = dataChannelMessage.payload as String
|
||||
if (internalNick != nick) {
|
||||
setNick(nick)
|
||||
nick = internalNick
|
||||
EventBus.getDefault()
|
||||
.post(PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType.NICK_CHANGE, sessionId, getNick(), null, videoStreamType))
|
||||
.post(PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType.NICK_CHANGE, sessionId, nick, null, videoStreamType))
|
||||
}
|
||||
} else {
|
||||
if (dataChannelMessage.payload != null) {
|
||||
|
@ -22,7 +22,6 @@ package com.nextcloud.talk.webrtc
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import autodagger.AutoInjector
|
||||
import com.bluelinelabs.logansquare.LoganSquare
|
||||
import com.nextcloud.talk.R.string
|
||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||
@ -58,9 +57,7 @@ import org.koin.core.inject
|
||||
import java.io.IOException
|
||||
import java.util.ArrayList
|
||||
import java.util.HashMap
|
||||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class MagicWebSocketInstance internal constructor(
|
||||
conversationUser: UserNgEntity,
|
||||
connectionUrl: String,
|
||||
@ -513,9 +510,6 @@ class MagicWebSocketInstance internal constructor(
|
||||
}
|
||||
|
||||
init {
|
||||
sharedApplication
|
||||
?.componentApplication
|
||||
?.inject(this)
|
||||
this.connectionUrl = connectionUrl
|
||||
this.conversationUser = conversationUser
|
||||
this.webSocketTicket = webSocketTicket
|
||||
|
Loading…
Reference in New Issue
Block a user