mirror of
https://github.com/ChronosX88/Influence-P2P.git
synced 2024-11-22 07:12:19 +00:00
Remove Start chat fragment, replaced with EditTextDialog (Floating Action Button)
This commit is contained in:
parent
6181665938
commit
58ed8aef78
@ -46,11 +46,13 @@ interface CoreContracts {
|
|||||||
|
|
||||||
interface IMainLogicContract {
|
interface IMainLogicContract {
|
||||||
fun initPeer()
|
fun initPeer()
|
||||||
|
fun sendStartChatMessage(username: String)
|
||||||
fun shutdownPeer()
|
fun shutdownPeer()
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMainPresenterContract {
|
interface IMainPresenterContract {
|
||||||
fun initPeer()
|
fun initPeer()
|
||||||
|
fun startChatWithPeer(username: String)
|
||||||
fun onDestroy()
|
fun onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,11 +22,14 @@ import net.tomp2p.nat.PeerBuilderNAT;
|
|||||||
import net.tomp2p.nat.PeerNAT;
|
import net.tomp2p.nat.PeerNAT;
|
||||||
import net.tomp2p.p2p.PeerBuilder;
|
import net.tomp2p.p2p.PeerBuilder;
|
||||||
import net.tomp2p.peers.Number160;
|
import net.tomp2p.peers.Number160;
|
||||||
|
import net.tomp2p.peers.Number640;
|
||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import net.tomp2p.relay.tcp.TCPRelayClientConfig;
|
import net.tomp2p.relay.tcp.TCPRelayClientConfig;
|
||||||
import net.tomp2p.replication.IndirectReplication;
|
import net.tomp2p.replication.IndirectReplication;
|
||||||
import net.tomp2p.storage.Data;
|
import net.tomp2p.storage.Data;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
@ -34,6 +37,8 @@ import java.net.InetAddress;
|
|||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -42,10 +47,14 @@ import io.github.chronosx88.influence.contracts.CoreContracts;
|
|||||||
import io.github.chronosx88.influence.helpers.AppHelper;
|
import io.github.chronosx88.influence.helpers.AppHelper;
|
||||||
import io.github.chronosx88.influence.helpers.JVMShutdownHook;
|
import io.github.chronosx88.influence.helpers.JVMShutdownHook;
|
||||||
import io.github.chronosx88.influence.helpers.KeyPairManager;
|
import io.github.chronosx88.influence.helpers.KeyPairManager;
|
||||||
|
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
||||||
import io.github.chronosx88.influence.helpers.NetworkHandler;
|
import io.github.chronosx88.influence.helpers.NetworkHandler;
|
||||||
|
import io.github.chronosx88.influence.helpers.ObservableUtils;
|
||||||
import io.github.chronosx88.influence.helpers.P2PUtils;
|
import io.github.chronosx88.influence.helpers.P2PUtils;
|
||||||
import io.github.chronosx88.influence.helpers.StorageBerkeleyDB;
|
import io.github.chronosx88.influence.helpers.StorageBerkeleyDB;
|
||||||
import io.github.chronosx88.influence.helpers.actions.UIActions;
|
import io.github.chronosx88.influence.helpers.actions.UIActions;
|
||||||
|
import io.github.chronosx88.influence.models.ChatMetadata;
|
||||||
|
import io.github.chronosx88.influence.models.NewChatRequestMessage;
|
||||||
import io.github.chronosx88.influence.models.PublicUserProfile;
|
import io.github.chronosx88.influence.models.PublicUserProfile;
|
||||||
|
|
||||||
public class MainLogic implements CoreContracts.IMainLogicContract {
|
public class MainLogic implements CoreContracts.IMainLogicContract {
|
||||||
@ -236,8 +245,10 @@ public class MainLogic implements CoreContracts.IMainLogicContract {
|
|||||||
if(replication != null) {
|
if(replication != null) {
|
||||||
replication.shutdown();
|
replication.shutdown();
|
||||||
}
|
}
|
||||||
|
if(peerDHT != null) {
|
||||||
peerDHT.peer().announceShutdown().start().awaitUninterruptibly();
|
peerDHT.peer().announceShutdown().start().awaitUninterruptibly();
|
||||||
peerDHT.peer().shutdown().awaitUninterruptibly();
|
peerDHT.peer().shutdown().awaitUninterruptibly();
|
||||||
|
}
|
||||||
storage.close();
|
storage.close();
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}).start();
|
}).start();
|
||||||
@ -292,4 +303,74 @@ public class MainLogic implements CoreContracts.IMainLogicContract {
|
|||||||
channelServerConfiguration.byteBufPool(false);
|
channelServerConfiguration.byteBufPool(false);
|
||||||
return channelServerConfiguration;
|
return channelServerConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendStartChatMessage(@NotNull String username) {
|
||||||
|
if(AppHelper.getPeerDHT() == null) {
|
||||||
|
ObservableUtils.notifyUI(UIActions.NODE_IS_OFFLINE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String companionPeerID = getPeerIDByUsername(username);
|
||||||
|
if(companionPeerID == null) {
|
||||||
|
ObservableUtils.notifyUI(UIActions.PEER_NOT_EXIST);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PublicUserProfile recipientPublicProfile = getPublicProfile(companionPeerID);
|
||||||
|
if(recipientPublicProfile == null) {
|
||||||
|
ObservableUtils.notifyUI(UIActions.PEER_NOT_EXIST);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NewChatRequestMessage newChatRequestMessage = new NewChatRequestMessage(UUID.randomUUID().toString(), UUID.randomUUID().toString(), AppHelper.getPeerID(), AppHelper.getUsername(), System.currentTimeMillis(), 0);
|
||||||
|
try {
|
||||||
|
if(P2PUtils.put(companionPeerID + "_pendingChats", newChatRequestMessage.getChatID(), new Data(gson.toJson(newChatRequestMessage)))) {
|
||||||
|
Log.i(LOG_TAG, "# Create new offline chat request is successful! ChatID: " + newChatRequestMessage.getChatID());
|
||||||
|
} else {
|
||||||
|
Log.e(LOG_TAG, "# Failed to create offline chat request. ChatID: " + newChatRequestMessage.getChatID());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayList<String> admins = new ArrayList<>();
|
||||||
|
admins.add(AppHelper.getPeerID());
|
||||||
|
Data data = null;
|
||||||
|
try {
|
||||||
|
data = new Data(gson.toJson(new ChatMetadata(username, admins, new ArrayList<>())));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
data.protectEntry(keyPairManager.openMainKeyPair());
|
||||||
|
P2PUtils.put(newChatRequestMessage.getChatID() + "_metadata", null, data);
|
||||||
|
LocalDBWrapper.createChatEntry(newChatRequestMessage.getChatID(), username, newChatRequestMessage.getChatID() + "_metadata", newChatRequestMessage.getChatID() + "_members", 0);
|
||||||
|
ObservableUtils.notifyUI(UIActions.NEW_CHAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PublicUserProfile getPublicProfile(String peerID) {
|
||||||
|
PublicUserProfile publicProfile = null;
|
||||||
|
Map<Number640, Data> data = P2PUtils.get(peerID + "_profile");
|
||||||
|
if (data != null && data.size() == 1) {
|
||||||
|
try {
|
||||||
|
publicProfile = gson.fromJson((String) data.values().iterator().next().object(), PublicUserProfile.class);
|
||||||
|
} catch (ClassNotFoundException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return publicProfile;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getPeerIDByUsername(String username) {
|
||||||
|
Map<Number640, Data> usernameMap = P2PUtils.get(username);
|
||||||
|
if(usernameMap == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return (String) usernameMap.values().iterator().next().object();
|
||||||
|
} catch (ClassNotFoundException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,110 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.logic;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
|
|
||||||
import net.tomp2p.dht.PeerDHT;
|
|
||||||
import net.tomp2p.peers.Number640;
|
|
||||||
import net.tomp2p.storage.Data;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.CoreContracts;
|
|
||||||
import io.github.chronosx88.influence.helpers.AppHelper;
|
|
||||||
import io.github.chronosx88.influence.helpers.KeyPairManager;
|
|
||||||
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
|
||||||
import io.github.chronosx88.influence.helpers.ObservableUtils;
|
|
||||||
import io.github.chronosx88.influence.helpers.P2PUtils;
|
|
||||||
import io.github.chronosx88.influence.helpers.actions.UIActions;
|
|
||||||
import io.github.chronosx88.influence.models.ChatMetadata;
|
|
||||||
import io.github.chronosx88.influence.models.NewChatRequestMessage;
|
|
||||||
import io.github.chronosx88.influence.models.PublicUserProfile;
|
|
||||||
|
|
||||||
public class StartChatLogic implements CoreContracts.IStartChatLogicContract {
|
|
||||||
private PeerDHT peerDHT;
|
|
||||||
private Gson gson;
|
|
||||||
private KeyPairManager keyPairManager;
|
|
||||||
private final static String LOG_TAG = "StartChatLogic";
|
|
||||||
|
|
||||||
public StartChatLogic() {
|
|
||||||
peerDHT = AppHelper.getPeerDHT();
|
|
||||||
gson = new Gson();
|
|
||||||
keyPairManager = new KeyPairManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendStartChatMessage(String username) {
|
|
||||||
if(peerDHT == null) {
|
|
||||||
ObservableUtils.notifyUI(UIActions.NODE_IS_OFFLINE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
new Thread(() -> {
|
|
||||||
String peerID = getPeerIDByUsername(username);
|
|
||||||
if(peerID == null) {
|
|
||||||
ObservableUtils.notifyUI(UIActions.PEER_NOT_EXIST);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
PublicUserProfile recipientPublicProfile = getPublicProfile(peerID);
|
|
||||||
if(recipientPublicProfile == null) {
|
|
||||||
ObservableUtils.notifyUI(UIActions.PEER_NOT_EXIST);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
NewChatRequestMessage newChatRequestMessage = new NewChatRequestMessage(UUID.randomUUID().toString(), UUID.randomUUID().toString(), AppHelper.getPeerID(), AppHelper.getUsername(), System.currentTimeMillis(), 0);
|
|
||||||
try {
|
|
||||||
if(P2PUtils.put(peerID + "_pendingChats", newChatRequestMessage.getChatID(), new Data(gson.toJson(newChatRequestMessage)))) {
|
|
||||||
Log.i(LOG_TAG, "# Create new offline chat request is successful! ChatID: " + newChatRequestMessage.getChatID());
|
|
||||||
} else {
|
|
||||||
Log.e(LOG_TAG, "# Failed to create offline chat request. ChatID: " + newChatRequestMessage.getChatID());
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
ArrayList<String> admins = new ArrayList<>();
|
|
||||||
admins.add(AppHelper.getPeerID());
|
|
||||||
Data data = null;
|
|
||||||
try {
|
|
||||||
data = new Data(gson.toJson(new ChatMetadata(username, admins, new ArrayList<>())));
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
data.protectEntry(keyPairManager.openMainKeyPair());
|
|
||||||
P2PUtils.put(newChatRequestMessage.getChatID() + "_metadata", null, data);
|
|
||||||
LocalDBWrapper.createChatEntry(newChatRequestMessage.getChatID(), username, newChatRequestMessage.getChatID() + "_metadata", newChatRequestMessage.getChatID() + "_members", 0);
|
|
||||||
ObservableUtils.notifyUI(UIActions.NEW_CHAT);
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private PublicUserProfile getPublicProfile(String peerID) {
|
|
||||||
PublicUserProfile publicProfile = null;
|
|
||||||
Map<Number640, Data> data = P2PUtils.get(peerID + "_profile");
|
|
||||||
if (data != null && data.size() == 1) {
|
|
||||||
try {
|
|
||||||
publicProfile = gson.fromJson((String) data.values().iterator().next().object(), PublicUserProfile.class);
|
|
||||||
} catch (ClassNotFoundException | IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return publicProfile;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getPeerIDByUsername(String username) {
|
|
||||||
Map<Number640, Data> usernameMap = P2PUtils.get(username);
|
|
||||||
if(usernameMap == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return (String) usernameMap.values().iterator().next().object();
|
|
||||||
} catch (ClassNotFoundException | IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +1,21 @@
|
|||||||
package io.github.chronosx88.influence.presenters
|
package io.github.chronosx88.influence.presenters
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
import io.github.chronosx88.influence.R
|
import io.github.chronosx88.influence.R
|
||||||
import io.github.chronosx88.influence.contracts.CoreContracts
|
import io.github.chronosx88.influence.contracts.CoreContracts
|
||||||
|
import io.github.chronosx88.influence.contracts.observer.IObserver
|
||||||
import io.github.chronosx88.influence.helpers.AppHelper
|
import io.github.chronosx88.influence.helpers.AppHelper
|
||||||
|
import io.github.chronosx88.influence.helpers.actions.UIActions
|
||||||
import io.github.chronosx88.influence.logic.MainLogic
|
import io.github.chronosx88.influence.logic.MainLogic
|
||||||
|
import org.jetbrains.anko.doAsync
|
||||||
|
|
||||||
class MainPresenter(private val view: CoreContracts.IMainViewContract) : CoreContracts.IMainPresenterContract {
|
class MainPresenter(private val view: CoreContracts.IMainViewContract) : CoreContracts.IMainPresenterContract, IObserver {
|
||||||
private val logic: CoreContracts.IMainLogicContract = MainLogic()
|
private val logic: CoreContracts.IMainLogicContract = MainLogic()
|
||||||
|
|
||||||
|
init {
|
||||||
|
AppHelper.getObservable().register(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun initPeer() {
|
override fun initPeer() {
|
||||||
if (AppHelper.getPeerDHT() == null) {
|
if (AppHelper.getPeerDHT() == null) {
|
||||||
logic.initPeer()
|
logic.initPeer()
|
||||||
@ -17,6 +25,31 @@ class MainPresenter(private val view: CoreContracts.IMainViewContract) : CoreCon
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun startChatWithPeer(username: String) {
|
||||||
|
doAsync {
|
||||||
|
logic.sendStartChatMessage(username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleEvent(obj: JsonObject) {
|
||||||
|
when(obj.get("action").asInt) {
|
||||||
|
UIActions.PEER_NOT_EXIST -> {
|
||||||
|
view.showProgressBar(false)
|
||||||
|
view.showSnackbar("Данный узел не существует!")
|
||||||
|
}
|
||||||
|
|
||||||
|
UIActions.NEW_CHAT -> {
|
||||||
|
view.showProgressBar(false)
|
||||||
|
view.showSnackbar("Чат успешно создан!")
|
||||||
|
}
|
||||||
|
|
||||||
|
UIActions.NODE_IS_OFFLINE -> {
|
||||||
|
view.showProgressBar(false)
|
||||||
|
view.showSnackbar("Нода не запущена!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
logic.shutdownPeer()
|
logic.shutdownPeer()
|
||||||
}
|
}
|
||||||
|
@ -1,49 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.presenters;
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.CoreContracts;
|
|
||||||
import io.github.chronosx88.influence.contracts.observer.IObserver;
|
|
||||||
import io.github.chronosx88.influence.helpers.AppHelper;
|
|
||||||
import io.github.chronosx88.influence.helpers.actions.UIActions;
|
|
||||||
import io.github.chronosx88.influence.logic.StartChatLogic;
|
|
||||||
|
|
||||||
public class StartChatPresenter implements CoreContracts.IStartChatPresenterContract, IObserver {
|
|
||||||
private CoreContracts.IStartChatViewContract view;
|
|
||||||
private CoreContracts.IStartChatLogicContract logic;
|
|
||||||
|
|
||||||
public StartChatPresenter(CoreContracts.IStartChatViewContract view) {
|
|
||||||
this.view = view;
|
|
||||||
this.logic = new StartChatLogic();
|
|
||||||
AppHelper.getObservable().register(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void startChatWithPeer(String peerID) {
|
|
||||||
view.showProgressDialog(true);
|
|
||||||
logic.sendStartChatMessage(peerID);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleEvent(JsonObject object) {
|
|
||||||
switch (object.get("action").getAsInt()) {
|
|
||||||
case UIActions.PEER_NOT_EXIST: {
|
|
||||||
view.showProgressDialog(false);
|
|
||||||
view.showMessage("Данный узел не существует!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case UIActions.NEW_CHAT: {
|
|
||||||
view.showProgressDialog(false);
|
|
||||||
view.showMessage("Чат успешно создан!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case UIActions.NODE_IS_OFFLINE: {
|
|
||||||
view.showProgressDialog(false);
|
|
||||||
view.showMessage("Нода не запущена!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -6,13 +6,16 @@ import android.view.Menu;
|
|||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.EditText;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentTransaction;
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
@ -27,7 +30,7 @@ import io.github.chronosx88.influence.helpers.actions.UIActions;
|
|||||||
import io.github.chronosx88.influence.presenters.MainPresenter;
|
import io.github.chronosx88.influence.presenters.MainPresenter;
|
||||||
import io.github.chronosx88.influence.views.fragments.ChatListFragment;
|
import io.github.chronosx88.influence.views.fragments.ChatListFragment;
|
||||||
import io.github.chronosx88.influence.views.fragments.SettingsFragment;
|
import io.github.chronosx88.influence.views.fragments.SettingsFragment;
|
||||||
import io.github.chronosx88.influence.views.fragments.StartChatFragment;
|
import kotlin.Pair;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity implements IObserver, CoreContracts.IMainViewContract {
|
public class MainActivity extends AppCompatActivity implements IObserver, CoreContracts.IMainViewContract {
|
||||||
|
|
||||||
@ -48,9 +51,6 @@ public class MainActivity extends AppCompatActivity implements IObserver, CoreCo
|
|||||||
case R.id.action_settings:
|
case R.id.action_settings:
|
||||||
selectedFragment = new SettingsFragment();
|
selectedFragment = new SettingsFragment();
|
||||||
break;
|
break;
|
||||||
case R.id.action_start_chat:
|
|
||||||
selectedFragment = new StartChatFragment();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||||
@ -69,6 +69,19 @@ public class MainActivity extends AppCompatActivity implements IObserver, CoreCo
|
|||||||
BottomNavigationView navigation = findViewById(R.id.main_bottom_navigation);
|
BottomNavigationView navigation = findViewById(R.id.main_bottom_navigation);
|
||||||
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
|
navigation.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
|
||||||
|
|
||||||
|
FloatingActionButton fab = findViewById(R.id.add_chat);
|
||||||
|
fab.setOnClickListener((v) -> {
|
||||||
|
Pair<AlertDialog.Builder, EditText> pair = ViewUtils.INSTANCE.setupEditTextDialog(MainActivity.this, getString(R.string.input_companion_username));
|
||||||
|
pair.getFirst().setPositiveButton(getString(R.string.ok), (dialog, which) -> {
|
||||||
|
progressDialog.show();
|
||||||
|
presenter.startChatWithPeer(pair.getSecond().getText().toString());
|
||||||
|
});
|
||||||
|
pair.getFirst().setNegativeButton(getString(R.string.cancel), (dialog, which) -> {
|
||||||
|
dialog.cancel();
|
||||||
|
});
|
||||||
|
pair.getFirst().show();
|
||||||
|
});
|
||||||
|
|
||||||
getSupportFragmentManager()
|
getSupportFragmentManager()
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.replace(R.id.main_fragment_container, new ChatListFragment())
|
.replace(R.id.main_fragment_container, new ChatListFragment())
|
||||||
@ -155,17 +168,21 @@ public class MainActivity extends AppCompatActivity implements IObserver, CoreCo
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showSnackbar(@NotNull String message) {
|
public void showSnackbar(@NotNull String message) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
Snackbar.make(getRootView(), message, Snackbar.LENGTH_LONG)
|
Snackbar.make(getRootView(), message, Snackbar.LENGTH_LONG)
|
||||||
.show();
|
.show();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showProgressBar(boolean state) {
|
public void showProgressBar(boolean state) {
|
||||||
|
runOnUiThread(() -> {
|
||||||
if(state) {
|
if(state) {
|
||||||
progressDialog.show();
|
progressDialog.show();
|
||||||
} else {
|
} else {
|
||||||
progressDialog.dismiss();
|
progressDialog.dismiss();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private View getRootView() {
|
private View getRootView() {
|
||||||
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2019 ChronosX88
|
||||||
|
*
|
||||||
|
* 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 <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.github.chronosx88.influence.views
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import io.github.chronosx88.influence.R
|
||||||
|
|
||||||
|
object ViewUtils {
|
||||||
|
fun setupEditTextDialog(context: Context, message: String): Pair<AlertDialog.Builder, EditText> {
|
||||||
|
val alertDialog = AlertDialog.Builder(context)
|
||||||
|
alertDialog.setTitle(message)
|
||||||
|
|
||||||
|
val input = EditText(context)
|
||||||
|
val lp = LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT)
|
||||||
|
input.setSingleLine()
|
||||||
|
input.layoutParams = lp
|
||||||
|
|
||||||
|
alertDialog.setView(input)
|
||||||
|
|
||||||
|
return Pair(alertDialog, input)
|
||||||
|
}
|
||||||
|
}
|
@ -1,69 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.views.fragments;
|
|
||||||
|
|
||||||
import android.app.ProgressDialog;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.Button;
|
|
||||||
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
|
||||||
import com.google.android.material.textfield.TextInputLayout;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import io.github.chronosx88.influence.R;
|
|
||||||
import io.github.chronosx88.influence.contracts.CoreContracts;
|
|
||||||
import io.github.chronosx88.influence.presenters.StartChatPresenter;
|
|
||||||
|
|
||||||
public class StartChatFragment extends Fragment implements CoreContracts.IStartChatViewContract {
|
|
||||||
private TextInputLayout textInputPeerID;
|
|
||||||
private ProgressDialog progressDialog;
|
|
||||||
private Button createChatButton;
|
|
||||||
private StartChatPresenter presenter;
|
|
||||||
private Handler mainThreadHandler;
|
|
||||||
private CoordinatorLayout coordinatorLayout;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
return inflater.inflate(R.layout.start_chat_fragment, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
|
||||||
super.onViewCreated(view, savedInstanceState);
|
|
||||||
presenter = new StartChatPresenter(this);
|
|
||||||
textInputPeerID = view.findViewById(R.id.textInputPeerID);
|
|
||||||
progressDialog = new ProgressDialog(getActivity(), R.style.AlertDialogTheme);
|
|
||||||
progressDialog.setCancelable(false);
|
|
||||||
progressDialog.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
|
|
||||||
createChatButton = view.findViewById(R.id.create_chat_button);
|
|
||||||
createChatButton.setOnClickListener((v) -> {
|
|
||||||
presenter.startChatWithPeer(textInputPeerID.getEditText().getText().toString());
|
|
||||||
});
|
|
||||||
mainThreadHandler = new Handler(getContext().getMainLooper());
|
|
||||||
coordinatorLayout = getView().findViewById(R.id.start_chat_coordinator);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showMessage(String message) {
|
|
||||||
mainThreadHandler.post(() -> {
|
|
||||||
Snackbar.make(coordinatorLayout, message, Snackbar.LENGTH_SHORT).show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showProgressDialog(boolean enabled) {
|
|
||||||
mainThreadHandler.post(() -> {
|
|
||||||
if(enabled) {
|
|
||||||
progressDialog.show();
|
|
||||||
} else {
|
|
||||||
progressDialog.dismiss();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
22
app/src/main/res/drawable/ic_add_white_24dp.xml
Normal file
22
app/src/main/res/drawable/ic_add_white_24dp.xml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<!--
|
||||||
|
~ Copyright (C) 2019 ChronosX88
|
||||||
|
~
|
||||||
|
~ 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 <https://www.gnu.org/licenses/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||||
|
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="#FF000000" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||||
|
</vector>
|
@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -7,12 +7,15 @@
|
|||||||
tools:context=".views.MainActivity"
|
tools:context=".views.MainActivity"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/main_fragment_container"
|
android:id="@+id/main_fragment_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_weight="10"/>
|
android:layout_weight="10"/>
|
||||||
|
|
||||||
<com.google.android.material.bottomnavigation.BottomNavigationView
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
android:id="@+id/main_bottom_navigation"
|
android:id="@+id/main_bottom_navigation"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -22,3 +25,15 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_gravity="bottom"/>
|
android:layout_gravity="bottom"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
android:id="@+id/add_chat"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_marginBottom="68dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:src="@drawable/ic_add_white_24dp"/>
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@ -1,33 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/start_chat_coordinator"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
<LinearLayout
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="center"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/textInputPeerID"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center">
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:hint="@string/username_hint"/>
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/create_chat_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Создать чат"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -8,8 +8,4 @@
|
|||||||
android:id="@+id/action_settings"
|
android:id="@+id/action_settings"
|
||||||
android:icon="@drawable/ic_settings_white"
|
android:icon="@drawable/ic_settings_white"
|
||||||
android:title="Настройки" />
|
android:title="Настройки" />
|
||||||
<item
|
|
||||||
android:id="@+id/action_start_chat"
|
|
||||||
android:icon="@drawable/ic_person_add_white"
|
|
||||||
android:title="Начать чат" />
|
|
||||||
</menu>
|
</menu>
|
@ -9,4 +9,5 @@
|
|||||||
<string name="username_hint">Имя пользователя</string>
|
<string name="username_hint">Имя пользователя</string>
|
||||||
<string name="reconnect_network">Переподключиться к сети</string>
|
<string name="reconnect_network">Переподключиться к сети</string>
|
||||||
<string name="node_already_running">Узел уже запущен</string>
|
<string name="node_already_running">Узел уже запущен</string>
|
||||||
|
<string name="input_companion_username">Введите имя пользователя собеседника</string>
|
||||||
</resources>
|
</resources>
|
@ -8,4 +8,5 @@
|
|||||||
<string name="username_hint">Username</string>
|
<string name="username_hint">Username</string>
|
||||||
<string name="reconnect_network">Reconnect to the network</string>
|
<string name="reconnect_network">Reconnect to the network</string>
|
||||||
<string name="node_already_running">Node already running</string>
|
<string name="node_already_running">Node already running</string>
|
||||||
|
<string name="input_companion_username">Input interlocutor\'s username</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user