mirror of
https://github.com/ChronosX88/Influence-P2P.git
synced 2024-11-25 00:22:17 +00:00
[BIG COMMIT] Made a username system and slightly fixed the signature system. Refactor.
This commit is contained in:
parent
1eb1f0c0bc
commit
99409e1a13
@ -29,6 +29,7 @@ android {
|
|||||||
exclude 'META-INF/io.netty.versions.properties'
|
exclude 'META-INF/io.netty.versions.properties'
|
||||||
exclude 'LICENSE-EPL-1.0.txt'
|
exclude 'LICENSE-EPL-1.0.txt'
|
||||||
exclude 'LICENSE-EDL-1.0.txt'
|
exclude 'LICENSE-EDL-1.0.txt'
|
||||||
|
exclude 'META-INF/atomicfu.kotlin_module'
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@ -40,20 +41,19 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0-alpha02'
|
implementation 'androidx.appcompat:appcompat:1.1.0-alpha02'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
|
|
||||||
implementation "androidx.room:room-runtime:2.1.0-alpha04"
|
implementation "androidx.room:room-runtime:2.1.0-alpha04"
|
||||||
annotationProcessor "androidx.room:room-compiler:2.1.0-alpha04"
|
annotationProcessor "androidx.room:room-compiler:2.1.0-alpha04"
|
||||||
implementation 'org.slf4j:slf4j-log4j12:1.7.26'
|
implementation 'org.slf4j:slf4j-log4j12:1.7.26'
|
||||||
implementation group: 'com.h2database', name: 'h2-mvstore', version: '1.4.197'
|
|
||||||
implementation 'net.tomp2p:tomp2p-all:5.0-Beta8'
|
implementation 'net.tomp2p:tomp2p-all:5.0-Beta8'
|
||||||
implementation 'com.google.android.material:material:1.1.0-alpha04'
|
implementation 'com.google.android.material:material:1.1.0-alpha04'
|
||||||
implementation 'androidx.preference:preference:1.1.0-alpha03'
|
implementation 'androidx.preference:preference:1.1.0-alpha03'
|
||||||
implementation 'com.google.code.gson:gson:2.8.5'
|
implementation 'com.google.code.gson:gson:2.8.5'
|
||||||
implementation group: 'org.springframework.security', name: 'spring-security-crypto', version: '3.1.0.RELEASE'
|
|
||||||
implementation 'de.hdodenhof:circleimageview:3.0.0'
|
implementation 'de.hdodenhof:circleimageview:3.0.0'
|
||||||
implementation group: 'org.objenesis', name: 'objenesis', version: '2.6'
|
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation 'com.android.support:multidex:1.0.3'
|
implementation 'com.android.support:multidex:1.0.3'
|
||||||
|
implementation "org.jetbrains.anko:anko:0.10.8"
|
||||||
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.0'
|
||||||
|
implementation 'com.esotericsoftware:kryo:5.0.0-RC1'
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -3,14 +3,16 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="io.github.chronosx88.influence">
|
package="io.github.chronosx88.influence">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".helpers.AppHelper"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
android:roundIcon="@mipmap/ic_launcher_round"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme">
|
||||||
android:name=".helpers.AppHelper">
|
|
||||||
<activity android:name=".views.MainActivity">
|
<activity android:name=".views.MainActivity">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
@ -20,7 +22,7 @@
|
|||||||
</activity>
|
</activity>
|
||||||
<activity
|
<activity
|
||||||
android:name=".views.ChatActivity"
|
android:name=".views.ChatActivity"
|
||||||
android:theme="@style/NoWindowActionBar"/>
|
android:theme="@style/NoWindowActionBar" />
|
||||||
</application>
|
</application>
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
|
||||||
</manifest>
|
</manifest>
|
@ -0,0 +1,91 @@
|
|||||||
|
package io.github.chronosx88.influence.contracts
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.view.MenuItem
|
||||||
|
|
||||||
|
import io.github.chronosx88.influence.helpers.ChatListAdapter
|
||||||
|
import io.github.chronosx88.influence.models.roomEntities.ChatEntity
|
||||||
|
import io.github.chronosx88.influence.models.roomEntities.MessageEntity
|
||||||
|
|
||||||
|
interface CoreContracts {
|
||||||
|
|
||||||
|
// -----ChatList-----
|
||||||
|
|
||||||
|
interface IChatListLogicContract {
|
||||||
|
fun loadAllChats(): List<ChatEntity>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IChatListPresenterContract {
|
||||||
|
fun updateChatList()
|
||||||
|
fun openChat(chatID: String)
|
||||||
|
fun onContextItemSelected(item: MenuItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IChatListViewContract {
|
||||||
|
fun setRecycleAdapter(adapter: ChatListAdapter)
|
||||||
|
fun startActivity(intent: Intent)
|
||||||
|
fun updateChatList(adapter: ChatListAdapter, chats: List<ChatEntity>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----StartChat-----
|
||||||
|
|
||||||
|
interface IStartChatLogicContract {
|
||||||
|
fun sendStartChatMessage(peerID: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStartChatPresenterContract {
|
||||||
|
fun startChatWithPeer(peerID: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IStartChatViewContract {
|
||||||
|
fun showMessage(message: String)
|
||||||
|
fun showProgressDialog(enabled: Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----MainActivity-----
|
||||||
|
|
||||||
|
interface IMainLogicContract {
|
||||||
|
fun initPeer()
|
||||||
|
fun shutdownPeer()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IMainPresenterContract {
|
||||||
|
fun initPeer()
|
||||||
|
fun onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IMainViewContract//
|
||||||
|
|
||||||
|
// -----ChatActivity-----
|
||||||
|
|
||||||
|
interface IChatLogicContract {
|
||||||
|
fun sendMessage(message: MessageEntity)
|
||||||
|
fun stopTrackingForNewMsgs()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IChatPresenterContract {
|
||||||
|
fun sendMessage(text: String)
|
||||||
|
fun updateAdapter()
|
||||||
|
fun onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IChatViewContract {
|
||||||
|
fun updateMessageList(message: MessageEntity)
|
||||||
|
fun updateMessageList(messages: List<MessageEntity>)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----SettingsFragment-----
|
||||||
|
|
||||||
|
interface ISettingsLogic {
|
||||||
|
fun checkUsernameExists(username: String) : Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISettingsPresenter {
|
||||||
|
fun updateUsername(username: String)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISettingsView {
|
||||||
|
fun loadingScreen(state: Boolean)
|
||||||
|
fun showMessage(message: String)
|
||||||
|
}
|
||||||
|
}
|
@ -1,8 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.chatactivity;
|
|
||||||
|
|
||||||
import io.github.chronosx88.influence.models.roomEntities.MessageEntity;
|
|
||||||
|
|
||||||
public interface IChatLogicContract {
|
|
||||||
void sendMessage(MessageEntity message);
|
|
||||||
void stopTrackingForNewMsgs();
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.chatactivity;
|
|
||||||
|
|
||||||
public interface IChatPresenterContract {
|
|
||||||
void sendMessage(String text);
|
|
||||||
void updateAdapter();
|
|
||||||
void onDestroy();
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.chatactivity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import io.github.chronosx88.influence.models.roomEntities.MessageEntity;
|
|
||||||
|
|
||||||
public interface IChatViewContract {
|
|
||||||
void updateMessageList(MessageEntity message);
|
|
||||||
void updateMessageList(List<MessageEntity> messages);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.chatlist;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
|
||||||
|
|
||||||
public interface IChatListLogicContract {
|
|
||||||
List<ChatEntity> loadAllChats();
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.chatlist;
|
|
||||||
|
|
||||||
import android.view.MenuItem;
|
|
||||||
|
|
||||||
public interface IChatListPresenterContract {
|
|
||||||
void updateChatList();
|
|
||||||
void openChat(String chatID);
|
|
||||||
void onContextItemSelected(MenuItem item);
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.chatlist;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import io.github.chronosx88.influence.helpers.ChatListAdapter;
|
|
||||||
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
|
||||||
|
|
||||||
public interface IChatListViewContract {
|
|
||||||
void setRecycleAdapter(ChatListAdapter adapter);
|
|
||||||
void startActivity(Intent intent);
|
|
||||||
void updateChatList(ChatListAdapter adapter, List<ChatEntity> chats);
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.mainactivity;
|
|
||||||
|
|
||||||
public interface IMainLogicContract {
|
|
||||||
void initPeer();
|
|
||||||
void shutdownPeer();
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.mainactivity;
|
|
||||||
|
|
||||||
public interface IMainPresenterContract {
|
|
||||||
void initPeer();
|
|
||||||
void onDestroy();
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.mainactivity;
|
|
||||||
|
|
||||||
public interface IMainViewContract {
|
|
||||||
//
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.startchat;
|
|
||||||
|
|
||||||
public interface IStartChatLogicContract {
|
|
||||||
void sendStartChatMessage(String peerID);
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.startchat;
|
|
||||||
|
|
||||||
public interface IStartChatPresenterContract {
|
|
||||||
void startChatWithPeer(String peerID);
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.contracts.startchat;
|
|
||||||
|
|
||||||
public interface IStartChatViewContract {
|
|
||||||
void showMessage(String message);
|
|
||||||
void showProgressDialog(boolean enabled);
|
|
||||||
}
|
|
@ -2,6 +2,7 @@ package io.github.chronosx88.influence.helpers;
|
|||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
|
||||||
import net.tomp2p.dht.PeerDHT;
|
import net.tomp2p.dht.PeerDHT;
|
||||||
|
|
||||||
@ -10,7 +11,7 @@ import androidx.room.Room;
|
|||||||
import io.github.chronosx88.influence.observable.MainObservable;
|
import io.github.chronosx88.influence.observable.MainObservable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extended Application class which designed for getting various objects from anywhere in the application.
|
* Extended Application class which designed for centralized getting various objects from anywhere in the application.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class AppHelper extends MultiDexApplication {
|
public class AppHelper extends MultiDexApplication {
|
||||||
@ -20,6 +21,8 @@ public class AppHelper extends MultiDexApplication {
|
|||||||
private static PeerDHT peerDHT;
|
private static PeerDHT peerDHT;
|
||||||
private static RoomHelper chatDB;
|
private static RoomHelper chatDB;
|
||||||
private static NetworkHandler networkHandler;
|
private static NetworkHandler networkHandler;
|
||||||
|
private static String username = "";
|
||||||
|
private static SharedPreferences preferences;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
@ -29,10 +32,13 @@ public class AppHelper extends MultiDexApplication {
|
|||||||
chatDB = Room.databaseBuilder(getApplicationContext(), RoomHelper.class, "chatDB")
|
chatDB = Room.databaseBuilder(getApplicationContext(), RoomHelper.class, "chatDB")
|
||||||
.allowMainThreadQueries()
|
.allowMainThreadQueries()
|
||||||
.build();
|
.build();
|
||||||
|
preferences = getApplicationContext().getSharedPreferences("io.github.chronosx88.influence_preferences", MODE_PRIVATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void storePeerID(String peerID1) { peerID = peerID1; }
|
public static void storePeerID(String peerID1) { peerID = peerID1; }
|
||||||
|
|
||||||
|
public static void updateUsername(String username1) { username = username1; }
|
||||||
|
|
||||||
public static void storePeerDHT(PeerDHT peerDHT1) { peerDHT = peerDHT1; }
|
public static void storePeerDHT(PeerDHT peerDHT1) { peerDHT = peerDHT1; }
|
||||||
|
|
||||||
public static Context getContext() {
|
public static Context getContext() {
|
||||||
@ -43,9 +49,15 @@ public class AppHelper extends MultiDexApplication {
|
|||||||
|
|
||||||
public static String getPeerID() { return peerID; }
|
public static String getPeerID() { return peerID; }
|
||||||
|
|
||||||
|
public static String getUsername() { return username; }
|
||||||
|
|
||||||
public static PeerDHT getPeerDHT() { return peerDHT; }
|
public static PeerDHT getPeerDHT() { return peerDHT; }
|
||||||
|
|
||||||
public static RoomHelper getChatDB() { return chatDB; }
|
public static RoomHelper getChatDB() { return chatDB; }
|
||||||
|
|
||||||
public static void initNetworkHandler() { networkHandler = new NetworkHandler(); }
|
public static void initNetworkHandler() { networkHandler = new NetworkHandler(); }
|
||||||
|
|
||||||
|
public static SharedPreferences getPreferences() {
|
||||||
|
return preferences;
|
||||||
|
}
|
||||||
}
|
}
|
@ -7,6 +7,7 @@ import io.netty.buffer.Unpooled
|
|||||||
import net.tomp2p.connection.SignatureFactory
|
import net.tomp2p.connection.SignatureFactory
|
||||||
import net.tomp2p.storage.AlternativeCompositeByteBuf
|
import net.tomp2p.storage.AlternativeCompositeByteBuf
|
||||||
import net.tomp2p.storage.Data
|
import net.tomp2p.storage.Data
|
||||||
|
import org.mapdb.DataInput2
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.nio.ByteBuffer
|
import java.nio.ByteBuffer
|
||||||
import java.security.InvalidKeyException
|
import java.security.InvalidKeyException
|
||||||
@ -27,7 +28,7 @@ class DataSerializerEx(private val signatureFactory: SignatureFactory) : EntryBi
|
|||||||
data = Data.decodeHeader(buf, signatureFactory)
|
data = Data.decodeHeader(buf, signatureFactory)
|
||||||
}
|
}
|
||||||
val len = data.length()
|
val len = data.length()
|
||||||
val me = ByteArray(len)
|
var me = ByteArray(len)
|
||||||
try {
|
try {
|
||||||
inputStream.read(me)
|
inputStream.read(me)
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
@ -39,6 +40,14 @@ class DataSerializerEx(private val signatureFactory: SignatureFactory) : EntryBi
|
|||||||
if (!retVal) {
|
if (!retVal) {
|
||||||
Log.e(LOG_TAG, "# ERROR: Data could not be deserialized!")
|
Log.e(LOG_TAG, "# ERROR: Data could not be deserialized!")
|
||||||
}
|
}
|
||||||
|
val dataInput = DataInputStream(inputStream)
|
||||||
|
me = ByteArray(signatureFactory.signatureSize())
|
||||||
|
dataInput.readFully(me)
|
||||||
|
buf = Unpooled.wrappedBuffer(me)
|
||||||
|
retVal = data.decodeDone(buf, signatureFactory);
|
||||||
|
if(!retVal) {
|
||||||
|
throw IOException("signature could not be read")
|
||||||
|
}
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
@ -25,7 +25,6 @@ public class KeyPairManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public KeyPair getKeyPair(String keyPairName) {
|
public KeyPair getKeyPair(String keyPairName) {
|
||||||
KeyPair keyPair = null;
|
|
||||||
keyPairName = keyPairName + ".kp";
|
keyPairName = keyPairName + ".kp";
|
||||||
File keyPairFile = new File(keyPairDir, keyPairName);
|
File keyPairFile = new File(keyPairDir, keyPairName);
|
||||||
if (!keyPairFile.exists()) {
|
if (!keyPairFile.exists()) {
|
||||||
@ -52,7 +51,9 @@ public class KeyPairManager {
|
|||||||
KeyPair keyPair = null;
|
KeyPair keyPair = null;
|
||||||
try {
|
try {
|
||||||
keyPairFile.createNewFile();
|
keyPairFile.createNewFile();
|
||||||
keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
|
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||||
|
keyPairGenerator.initialize(1024);
|
||||||
|
keyPair = keyPairGenerator.generateKeyPair();
|
||||||
FileOutputStream outputStream = new FileOutputStream(keyPairFile);
|
FileOutputStream outputStream = new FileOutputStream(keyPairFile);
|
||||||
outputStream.write(serializer.serialize(keyPair));
|
outputStream.write(serializer.serialize(keyPair));
|
||||||
outputStream.close();
|
outputStream.close();
|
||||||
|
@ -58,7 +58,7 @@ public class NetworkHandler implements INetworkObserver {
|
|||||||
|
|
||||||
LocalDBWrapper.createChatEntry(
|
LocalDBWrapper.createChatEntry(
|
||||||
newChatRequestMessage.getChatID(),
|
newChatRequestMessage.getChatID(),
|
||||||
newChatRequestMessage.getSenderID(),
|
newChatRequestMessage.getUsername(),
|
||||||
newChatRequestMessage.getChatID() + "_metadata",
|
newChatRequestMessage.getChatID() + "_metadata",
|
||||||
newChatRequestMessage.getChatID() + "_members",
|
newChatRequestMessage.getChatID() + "_members",
|
||||||
newChatRequestMessage.getChunkID()
|
newChatRequestMessage.getChunkID()
|
||||||
@ -67,7 +67,7 @@ public class NetworkHandler implements INetworkObserver {
|
|||||||
P2PUtils.remove(AppHelper.getPeerID() + "_pendingChats", newChatRequestMessage.getChatID());
|
P2PUtils.remove(AppHelper.getPeerID() + "_pendingChats", newChatRequestMessage.getChatID());
|
||||||
String messageID = UUID.randomUUID().toString();
|
String messageID = UUID.randomUUID().toString();
|
||||||
try {
|
try {
|
||||||
P2PUtils.put(newChatRequestMessage.getChatID() + "_messages", messageID, new Data(gson.toJson(new JoinChatMessage(AppHelper.getPeerID(), AppHelper.getPeerID(), newChatRequestMessage.getChatID(), System.currentTimeMillis()))).protectEntry(keyPairManager.openMainKeyPair()));
|
P2PUtils.put(newChatRequestMessage.getChatID() + "_messages", messageID, new Data(gson.toJson(new JoinChatMessage(AppHelper.getPeerID(), AppHelper.getUsername() == null ? AppHelper.getPeerID() : AppHelper.getUsername(), newChatRequestMessage.getChatID(), System.currentTimeMillis()))).protectEntry(keyPairManager.openMainKeyPair()));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -75,6 +75,4 @@ public class NetworkHandler implements INetworkObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -13,34 +13,14 @@ import net.tomp2p.peers.Number640;
|
|||||||
import net.tomp2p.peers.PeerAddress;
|
import net.tomp2p.peers.PeerAddress;
|
||||||
import net.tomp2p.storage.Data;
|
import net.tomp2p.storage.Data;
|
||||||
|
|
||||||
|
import java.security.KeyPair;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class P2PUtils {
|
public class P2PUtils {
|
||||||
private static Gson gson = new Gson();
|
private static Gson gson = new Gson();
|
||||||
private static PeerDHT peerDHT = AppHelper.getPeerDHT();
|
private static PeerDHT peerDHT = AppHelper.getPeerDHT();
|
||||||
|
|
||||||
public static boolean ping(PeerAddress recipientPeerAddress) {
|
|
||||||
// For connection opening
|
|
||||||
for (int i = 0; i < 5; i++) {
|
|
||||||
peerDHT
|
|
||||||
.peer()
|
|
||||||
.ping()
|
|
||||||
.peerAddress(recipientPeerAddress)
|
|
||||||
.start()
|
|
||||||
.awaitUninterruptibly();
|
|
||||||
}
|
|
||||||
|
|
||||||
FuturePing ping = peerDHT
|
|
||||||
.peer()
|
|
||||||
.ping()
|
|
||||||
.peerAddress(recipientPeerAddress)
|
|
||||||
.start()
|
|
||||||
.awaitUninterruptibly();
|
|
||||||
return ping.isSuccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean put(String locationKey, String contentKey, Data data) {
|
public static boolean put(String locationKey, String contentKey, Data data) {
|
||||||
data.signed(false);
|
|
||||||
FuturePut futurePut = peerDHT
|
FuturePut futurePut = peerDHT
|
||||||
.put(Number160.createHash(locationKey))
|
.put(Number160.createHash(locationKey))
|
||||||
.data(contentKey == null ? Number160.ZERO : Number160.createHash(contentKey), data)
|
.data(contentKey == null ? Number160.ZERO : Number160.createHash(contentKey), data)
|
||||||
@ -49,6 +29,16 @@ public class P2PUtils {
|
|||||||
return futurePut.isSuccess();
|
return futurePut.isSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean put(String locationKey, String contentKey, Data data, KeyPair keyPair) {
|
||||||
|
FuturePut futurePut = peerDHT
|
||||||
|
.put(Number160.createHash(locationKey))
|
||||||
|
.data(contentKey == null ? Number160.ZERO : Number160.createHash(contentKey), data)
|
||||||
|
.keyPair(keyPair)
|
||||||
|
.start()
|
||||||
|
.awaitUninterruptibly();
|
||||||
|
return futurePut.isSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
public static Map<Number640, Data> get(String locationKey) {
|
public static Map<Number640, Data> get(String locationKey) {
|
||||||
FutureGet futureGet = peerDHT
|
FutureGet futureGet = peerDHT
|
||||||
.get(Number160.createHash(locationKey))
|
.get(Number160.createHash(locationKey))
|
||||||
@ -61,16 +51,6 @@ public class P2PUtils {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean send(PeerAddress address, String data) {
|
|
||||||
FutureDirect futureDirect = peerDHT
|
|
||||||
.peer()
|
|
||||||
.sendDirect(address)
|
|
||||||
.object(data)
|
|
||||||
.start()
|
|
||||||
.awaitUninterruptibly();
|
|
||||||
return futureDirect.isSuccess();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean remove(String locationKey, String contentKey) {
|
public static boolean remove(String locationKey, String contentKey) {
|
||||||
FutureRemove futureRemove = peerDHT
|
FutureRemove futureRemove = peerDHT
|
||||||
.remove(Number160.createHash(locationKey))
|
.remove(Number160.createHash(locationKey))
|
||||||
@ -79,4 +59,14 @@ public class P2PUtils {
|
|||||||
.awaitUninterruptibly();
|
.awaitUninterruptibly();
|
||||||
return futureRemove.isRemoved();
|
return futureRemove.isRemoved();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean remove(String locationKey, String contentKey, KeyPair keyPair) {
|
||||||
|
FutureRemove futureRemove = peerDHT
|
||||||
|
.remove(Number160.createHash(locationKey))
|
||||||
|
.keyPair(keyPair)
|
||||||
|
.contentKey(contentKey == null ? null : Number160.createHash(contentKey))
|
||||||
|
.start()
|
||||||
|
.awaitUninterruptibly();
|
||||||
|
return futureRemove.isRemoved();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ class StorageBerkeleyDB(peerId: Number160, path : File, signatureFactory: Signat
|
|||||||
|
|
||||||
storageCheckIntervalMillis = 60 * 1000
|
storageCheckIntervalMillis = 60 * 1000
|
||||||
|
|
||||||
dataMap = StoredSortedMap(dataMapDB, Serializer<Number640>(), DataSerializerEx(signatureFactory), true)
|
dataMap = StoredSortedMap(dataMapDB, Serializer<Number640>(), DataSerializer(signatureFactory), true)
|
||||||
timeoutMap = StoredSortedMap(timeoutMapDB, Serializer<Number640>(), Serializer<Long>(), true)
|
timeoutMap = StoredSortedMap(timeoutMapDB, Serializer<Number640>(), Serializer<Long>(), true)
|
||||||
timeoutMapRev = StoredSortedMap(timeoutMapRevDB, Serializer<Long>(), Serializer<Set<Number640>>(), true)
|
timeoutMapRev = StoredSortedMap(timeoutMapRevDB, Serializer<Long>(), Serializer<Set<Number640>>(), true)
|
||||||
protectedDomainMap = StoredSortedMap(protectedDomainMapDB, Serializer<Number320>(), Serializer<PublicKey>(), true)
|
protectedDomainMap = StoredSortedMap(protectedDomainMapDB, Serializer<Number320>(), Serializer<PublicKey>(), true)
|
||||||
@ -89,8 +89,8 @@ class StorageBerkeleyDB(peerId: Number160, path : File, signatureFactory: Signat
|
|||||||
return dataMap.subMap(from, true, to, true).size
|
return dataMap.subMap(from, true, to, true).size
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findContentForResponsiblePeerID(peerID: Number160?): MutableSet<Number160> {
|
override fun findContentForResponsiblePeerID(peerID: Number160?): MutableSet<Number160>? {
|
||||||
return responsibilityMapRev[peerID] as MutableSet<Number160>
|
return responsibilityMapRev[peerID] as MutableSet<Number160>?
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun findPeerIDsForResponsibleContent(locationKey: Number160?): Number160? {
|
override fun findPeerIDsForResponsibleContent(locationKey: Number160?): Number160? {
|
||||||
|
@ -12,4 +12,6 @@ public class UIActions {
|
|||||||
public static final int SUCCESSFUL_CREATE_CHAT = 0x8;
|
public static final int SUCCESSFUL_CREATE_CHAT = 0x8;
|
||||||
public static final int MESSAGE_RECEIVED = 0x9;
|
public static final int MESSAGE_RECEIVED = 0x9;
|
||||||
public static final int NODE_IS_OFFLINE = 0x10;
|
public static final int NODE_IS_OFFLINE = 0x10;
|
||||||
|
public static final int USERNAME_ISNT_AVAILABLE = 0x11;
|
||||||
|
public static final int USERNAME_AVAILABLE = 0x12;
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ package io.github.chronosx88.influence.logic;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.chatlist.IChatListLogicContract;
|
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.models.roomEntities.ChatEntity;
|
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
||||||
|
|
||||||
public class ChatListLogic implements IChatListLogicContract {
|
public class ChatListLogic implements CoreContracts.IChatListLogicContract {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ChatEntity> loadAllChats() {
|
public List<ChatEntity> loadAllChats() {
|
||||||
|
@ -13,7 +13,7 @@ import java.util.Timer;
|
|||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.chatactivity.IChatLogicContract;
|
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.KeyPairManager;
|
import io.github.chronosx88.influence.helpers.KeyPairManager;
|
||||||
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
||||||
@ -27,7 +27,7 @@ import io.github.chronosx88.influence.models.TextMessage;
|
|||||||
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
||||||
import io.github.chronosx88.influence.models.roomEntities.MessageEntity;
|
import io.github.chronosx88.influence.models.roomEntities.MessageEntity;
|
||||||
|
|
||||||
public class ChatLogic implements IChatLogicContract {
|
public class ChatLogic implements CoreContracts.IChatLogicContract {
|
||||||
private static Gson gson = new Gson();
|
private static Gson gson = new Gson();
|
||||||
private String chatID;
|
private String chatID;
|
||||||
private String newMessage = "";
|
private String newMessage = "";
|
||||||
|
@ -22,6 +22,8 @@ import net.tomp2p.peers.Number160;
|
|||||||
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.AutoReplication;
|
import net.tomp2p.replication.AutoReplication;
|
||||||
|
import net.tomp2p.replication.IndirectReplication;
|
||||||
|
import net.tomp2p.replication.Replication;
|
||||||
import net.tomp2p.storage.Data;
|
import net.tomp2p.storage.Data;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -34,7 +36,7 @@ import java.util.Timer;
|
|||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.mainactivity.IMainLogicContract;
|
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;
|
||||||
@ -44,8 +46,8 @@ 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.PublicUserProfile;
|
import io.github.chronosx88.influence.models.PublicUserProfile;
|
||||||
|
|
||||||
public class MainLogic implements IMainLogicContract {
|
public class MainLogic implements CoreContracts.IMainLogicContract {
|
||||||
private static final String LOG_TAG = "MainLogic";
|
private static final String LOG_TAG = MainLogic.class.getName();
|
||||||
|
|
||||||
private SharedPreferences preferences;
|
private SharedPreferences preferences;
|
||||||
private Number160 peerID;
|
private Number160 peerID;
|
||||||
@ -54,7 +56,7 @@ public class MainLogic implements IMainLogicContract {
|
|||||||
private InetAddress bootstrapAddress = null;
|
private InetAddress bootstrapAddress = null;
|
||||||
private PeerAddress bootstrapPeerAddress = null;
|
private PeerAddress bootstrapPeerAddress = null;
|
||||||
private Gson gson;
|
private Gson gson;
|
||||||
private AutoReplication replication;
|
private IndirectReplication replication;
|
||||||
private KeyPairManager keyPairManager;
|
private KeyPairManager keyPairManager;
|
||||||
private Thread checkNewChatsThread = null;
|
private Thread checkNewChatsThread = null;
|
||||||
private StorageBerkeleyDB storage;
|
private StorageBerkeleyDB storage;
|
||||||
@ -142,11 +144,13 @@ public class MainLogic implements IMainLogicContract {
|
|||||||
jsonObject.addProperty("action", UIActions.BOOTSTRAP_SUCCESS);
|
jsonObject.addProperty("action", UIActions.BOOTSTRAP_SUCCESS);
|
||||||
AppHelper.getObservable().notifyUIObservers(jsonObject);
|
AppHelper.getObservable().notifyUIObservers(jsonObject);
|
||||||
AppHelper.storePeerID(preferences.getString("peerID", null));
|
AppHelper.storePeerID(preferences.getString("peerID", null));
|
||||||
|
AppHelper.updateUsername(preferences.getString("username", null));
|
||||||
AppHelper.storePeerDHT(peerDHT);
|
AppHelper.storePeerDHT(peerDHT);
|
||||||
AppHelper.initNetworkHandler();
|
AppHelper.initNetworkHandler();
|
||||||
setReceiveHandler();
|
setReceiveHandler();
|
||||||
gson = new Gson();
|
gson = new Gson();
|
||||||
publicProfileToDHT();
|
publicProfileToDHT();
|
||||||
|
SettingsLogic.Companion.publishUsername(AppHelper.getUsername(), AppHelper.getUsername());
|
||||||
NetworkHandler.handlePendingChatRequests();
|
NetworkHandler.handlePendingChatRequests();
|
||||||
TimerTask timerTask = new TimerTask() {
|
TimerTask timerTask = new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
@ -163,7 +167,7 @@ public class MainLogic implements IMainLogicContract {
|
|||||||
};
|
};
|
||||||
Timer timer = new Timer();
|
Timer timer = new Timer();
|
||||||
timer.schedule(timerTask, 1, 5000);
|
timer.schedule(timerTask, 1, 5000);
|
||||||
replication = new AutoReplication(peerDHT.peer()).start();
|
replication = new IndirectReplication(peerDHT).start();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@ -224,7 +228,7 @@ public class MainLogic implements IMainLogicContract {
|
|||||||
public void shutdownPeer() {
|
public void shutdownPeer() {
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
if(replication != null) {
|
if(replication != null) {
|
||||||
replication.shutdown().start();
|
replication.shutdown();
|
||||||
}
|
}
|
||||||
peerDHT.peer().announceShutdown().start().awaitUninterruptibly();
|
peerDHT.peer().announceShutdown().start().awaitUninterruptibly();
|
||||||
peerDHT.peer().shutdown().awaitUninterruptibly();
|
peerDHT.peer().shutdown().awaitUninterruptibly();
|
||||||
@ -245,7 +249,7 @@ public class MainLogic implements IMainLogicContract {
|
|||||||
|
|
||||||
private void publicProfileToDHT() {
|
private void publicProfileToDHT() {
|
||||||
KeyPair mainKeyPair = keyPairManager.openMainKeyPair();
|
KeyPair mainKeyPair = keyPairManager.openMainKeyPair();
|
||||||
PublicUserProfile userProfile = new PublicUserProfile(AppHelper.getPeerID(), peerDHT.peerAddress());
|
PublicUserProfile userProfile = new PublicUserProfile(AppHelper.getUsername(), peerDHT.peerAddress());
|
||||||
Data serializedUserProfile = null;
|
Data serializedUserProfile = null;
|
||||||
try {
|
try {
|
||||||
serializedUserProfile = new Data(gson.toJson(userProfile))
|
serializedUserProfile = new Data(gson.toJson(userProfile))
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
package io.github.chronosx88.influence.logic
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
|
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.P2PUtils
|
||||||
|
import net.tomp2p.peers.Number640
|
||||||
|
import net.tomp2p.storage.Data
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class SettingsLogic : CoreContracts.ISettingsLogic {
|
||||||
|
|
||||||
|
override fun checkUsernameExists(username: String) : Boolean {
|
||||||
|
val usernameMap: MutableMap<Number640, Data>? = P2PUtils.get(username)
|
||||||
|
usernameMap ?: return false
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val LOG_TAG: String = "SettingsLogic"
|
||||||
|
private val keyPairManager = KeyPairManager()
|
||||||
|
|
||||||
|
fun publishUsername(oldUsername: String?, username: String?) {
|
||||||
|
val mainKeyPair = keyPairManager.openMainKeyPair()
|
||||||
|
if(oldUsername != null || !oldUsername.equals("")) {
|
||||||
|
P2PUtils.remove(oldUsername, null, mainKeyPair)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (username.equals("") || username == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var data: Data? = null
|
||||||
|
try {
|
||||||
|
data = Data(AppHelper.getPeerID())
|
||||||
|
} catch (e: IOException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
|
||||||
|
data!!.protectEntry(mainKeyPair)
|
||||||
|
|
||||||
|
val isSuccess = P2PUtils.put(username, null, data, mainKeyPair)
|
||||||
|
Log.i(LOG_TAG, if (isSuccess) "Username $username is published!" else "Username $username isn't published!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -13,7 +13,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.startchat.IStartChatLogicContract;
|
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.KeyPairManager;
|
import io.github.chronosx88.influence.helpers.KeyPairManager;
|
||||||
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
||||||
@ -24,7 +24,7 @@ import io.github.chronosx88.influence.models.ChatMetadata;
|
|||||||
import io.github.chronosx88.influence.models.NewChatRequestMessage;
|
import io.github.chronosx88.influence.models.NewChatRequestMessage;
|
||||||
import io.github.chronosx88.influence.models.PublicUserProfile;
|
import io.github.chronosx88.influence.models.PublicUserProfile;
|
||||||
|
|
||||||
public class StartChatLogic implements IStartChatLogicContract {
|
public class StartChatLogic implements CoreContracts.IStartChatLogicContract {
|
||||||
private PeerDHT peerDHT;
|
private PeerDHT peerDHT;
|
||||||
private Gson gson;
|
private Gson gson;
|
||||||
private KeyPairManager keyPairManager;
|
private KeyPairManager keyPairManager;
|
||||||
@ -37,20 +37,25 @@ public class StartChatLogic implements IStartChatLogicContract {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendStartChatMessage(String peerID) {
|
public void sendStartChatMessage(String username) {
|
||||||
if(peerDHT == null) {
|
if(peerDHT == null) {
|
||||||
ObservableUtils.notifyUI(UIActions.NODE_IS_OFFLINE);
|
ObservableUtils.notifyUI(UIActions.NODE_IS_OFFLINE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
|
String peerID = getPeerIDByUsername(username);
|
||||||
|
if(peerID == null) {
|
||||||
|
ObservableUtils.notifyUI(UIActions.PEER_NOT_EXIST);
|
||||||
|
return;
|
||||||
|
}
|
||||||
PublicUserProfile recipientPublicProfile = getPublicProfile(peerID);
|
PublicUserProfile recipientPublicProfile = getPublicProfile(peerID);
|
||||||
if(recipientPublicProfile == null) {
|
if(recipientPublicProfile == null) {
|
||||||
ObservableUtils.notifyUI(UIActions.PEER_NOT_EXIST);
|
ObservableUtils.notifyUI(UIActions.PEER_NOT_EXIST);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NewChatRequestMessage newChatRequestMessage = new NewChatRequestMessage(UUID.randomUUID().toString(), UUID.randomUUID().toString(), AppHelper.getPeerID(), AppHelper.getPeerID(), System.currentTimeMillis(), 0);
|
NewChatRequestMessage newChatRequestMessage = new NewChatRequestMessage(UUID.randomUUID().toString(), UUID.randomUUID().toString(), AppHelper.getPeerID(), AppHelper.getUsername(), System.currentTimeMillis(), 0);
|
||||||
try {
|
try {
|
||||||
if(P2PUtils.put(peerID + "_pendingChats", newChatRequestMessage.getChatID(), new Data(gson.toJson(newChatRequestMessage)))) {
|
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());
|
Log.i(LOG_TAG, "# Create new offline chat request is successful! ChatID: " + newChatRequestMessage.getChatID());
|
||||||
@ -65,13 +70,13 @@ public class StartChatLogic implements IStartChatLogicContract {
|
|||||||
admins.add(AppHelper.getPeerID());
|
admins.add(AppHelper.getPeerID());
|
||||||
Data data = null;
|
Data data = null;
|
||||||
try {
|
try {
|
||||||
data = new Data(gson.toJson(new ChatMetadata(peerID, admins, new ArrayList<>())));
|
data = new Data(gson.toJson(new ChatMetadata(username, admins, new ArrayList<>())));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
data.protectEntry(keyPairManager.openMainKeyPair());
|
data.protectEntry(keyPairManager.openMainKeyPair());
|
||||||
P2PUtils.put(newChatRequestMessage.getChatID() + "_metadata", null, data);
|
P2PUtils.put(newChatRequestMessage.getChatID() + "_metadata", null, data);
|
||||||
LocalDBWrapper.createChatEntry(newChatRequestMessage.getChatID(), peerID, newChatRequestMessage.getChatID() + "_metadata", newChatRequestMessage.getChatID() + "_members", 0);
|
LocalDBWrapper.createChatEntry(newChatRequestMessage.getChatID(), username, newChatRequestMessage.getChatID() + "_metadata", newChatRequestMessage.getChatID() + "_members", 0);
|
||||||
ObservableUtils.notifyUI(UIActions.NEW_CHAT);
|
ObservableUtils.notifyUI(UIActions.NEW_CHAT);
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
@ -89,4 +94,17 @@ public class StartChatLogic implements IStartChatLogicContract {
|
|||||||
}
|
}
|
||||||
return null;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,7 @@ package io.github.chronosx88.influence.presenters;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.chatlist.IChatListLogicContract;
|
import io.github.chronosx88.influence.contracts.CoreContracts;
|
||||||
import io.github.chronosx88.influence.contracts.chatlist.IChatListPresenterContract;
|
|
||||||
import io.github.chronosx88.influence.contracts.chatlist.IChatListViewContract;
|
|
||||||
import io.github.chronosx88.influence.helpers.AppHelper;
|
import io.github.chronosx88.influence.helpers.AppHelper;
|
||||||
import io.github.chronosx88.influence.helpers.ChatListAdapter;
|
import io.github.chronosx88.influence.helpers.ChatListAdapter;
|
||||||
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
||||||
@ -13,12 +11,12 @@ import io.github.chronosx88.influence.logic.ChatListLogic;
|
|||||||
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
||||||
import io.github.chronosx88.influence.views.ChatActivity;
|
import io.github.chronosx88.influence.views.ChatActivity;
|
||||||
|
|
||||||
public class ChatListPresenter implements IChatListPresenterContract {
|
public class ChatListPresenter implements CoreContracts.IChatListPresenterContract {
|
||||||
private IChatListViewContract view;
|
private CoreContracts.IChatListViewContract view;
|
||||||
private IChatListLogicContract logic;
|
private CoreContracts.IChatListLogicContract logic;
|
||||||
private ChatListAdapter chatListAdapter;
|
private ChatListAdapter chatListAdapter;
|
||||||
|
|
||||||
public ChatListPresenter(IChatListViewContract view) {
|
public ChatListPresenter(CoreContracts.IChatListViewContract view) {
|
||||||
this.view = view;
|
this.view = view;
|
||||||
chatListAdapter = new ChatListAdapter((v, p)-> {
|
chatListAdapter = new ChatListAdapter((v, p)-> {
|
||||||
openChat(chatListAdapter.getChatEntity(p).chatID);
|
openChat(chatListAdapter.getChatEntity(p).chatID);
|
||||||
|
@ -10,9 +10,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.chatactivity.IChatLogicContract;
|
import io.github.chronosx88.influence.contracts.CoreContracts;
|
||||||
import io.github.chronosx88.influence.contracts.chatactivity.IChatPresenterContract;
|
|
||||||
import io.github.chronosx88.influence.contracts.chatactivity.IChatViewContract;
|
|
||||||
import io.github.chronosx88.influence.contracts.observer.IObserver;
|
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.LocalDBWrapper;
|
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
||||||
@ -22,14 +20,14 @@ import io.github.chronosx88.influence.logic.ChatLogic;
|
|||||||
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
||||||
import io.github.chronosx88.influence.models.roomEntities.MessageEntity;
|
import io.github.chronosx88.influence.models.roomEntities.MessageEntity;
|
||||||
|
|
||||||
public class ChatPresenter implements IChatPresenterContract, IObserver {
|
public class ChatPresenter implements CoreContracts.IChatPresenterContract, IObserver {
|
||||||
private IChatLogicContract logic;
|
private CoreContracts.IChatLogicContract logic;
|
||||||
private IChatViewContract view;
|
private CoreContracts.IChatViewContract view;
|
||||||
private ChatEntity chatEntity;
|
private ChatEntity chatEntity;
|
||||||
private String chatID;
|
private String chatID;
|
||||||
private Gson gson;
|
private Gson gson;
|
||||||
|
|
||||||
public ChatPresenter(IChatViewContract view, String chatID) {
|
public ChatPresenter(CoreContracts.IChatViewContract view, String chatID) {
|
||||||
this.logic = new ChatLogic(LocalDBWrapper.getChatByChatID(chatID));
|
this.logic = new ChatLogic(LocalDBWrapper.getChatByChatID(chatID));
|
||||||
this.view = view;
|
this.view = view;
|
||||||
this.chatID = chatID;
|
this.chatID = chatID;
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
package io.github.chronosx88.influence.presenters;
|
package io.github.chronosx88.influence.presenters;
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.mainactivity.IMainLogicContract;
|
import io.github.chronosx88.influence.contracts.CoreContracts;
|
||||||
import io.github.chronosx88.influence.contracts.mainactivity.IMainPresenterContract;
|
|
||||||
import io.github.chronosx88.influence.contracts.mainactivity.IMainViewContract;
|
|
||||||
import io.github.chronosx88.influence.logic.MainLogic;
|
import io.github.chronosx88.influence.logic.MainLogic;
|
||||||
|
|
||||||
public class MainPresenter implements IMainPresenterContract {
|
public class MainPresenter implements CoreContracts.IMainPresenterContract {
|
||||||
private IMainLogicContract logic;
|
private CoreContracts.IMainLogicContract logic;
|
||||||
private IMainViewContract view;
|
private CoreContracts.IMainViewContract view;
|
||||||
|
|
||||||
public MainPresenter(IMainViewContract view) {
|
public MainPresenter(CoreContracts.IMainViewContract view) {
|
||||||
this.view = view;
|
this.view = view;
|
||||||
logic = new MainLogic();
|
logic = new MainLogic();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,64 @@
|
|||||||
|
package io.github.chronosx88.influence.presenters
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import android.os.Handler
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import io.github.chronosx88.influence.R
|
||||||
|
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.ObservableUtils
|
||||||
|
import io.github.chronosx88.influence.helpers.actions.UIActions
|
||||||
|
import io.github.chronosx88.influence.logic.SettingsLogic
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
class SettingsPresenter(private val view: CoreContracts.ISettingsView) : CoreContracts.ISettingsPresenter, IObserver {
|
||||||
|
private val mainThreadHandler: Handler = Handler(AppHelper.getContext().mainLooper)
|
||||||
|
private val logic: SettingsLogic = SettingsLogic()
|
||||||
|
|
||||||
|
init {
|
||||||
|
AppHelper.getObservable().register(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateUsername(username: String) {
|
||||||
|
view.loadingScreen(true)
|
||||||
|
GlobalScope.launch {
|
||||||
|
if(!logic.checkUsernameExists(username)) {
|
||||||
|
// Save username in SharedPreferences
|
||||||
|
val editor: SharedPreferences.Editor = AppHelper.getPreferences().edit()
|
||||||
|
val oldUsername = AppHelper.getPreferences().getString("username", null)
|
||||||
|
if(username.equals("")) {
|
||||||
|
editor.remove("username")
|
||||||
|
} else {
|
||||||
|
editor.putString("username", username)
|
||||||
|
}
|
||||||
|
editor.apply()
|
||||||
|
AppHelper.updateUsername(if (username.equals("")) null else username)
|
||||||
|
|
||||||
|
// Publish username on DHT network
|
||||||
|
SettingsLogic.publishUsername(oldUsername, username)
|
||||||
|
|
||||||
|
ObservableUtils.notifyUI(UIActions.USERNAME_AVAILABLE)
|
||||||
|
} else {
|
||||||
|
ObservableUtils.notifyUI(UIActions.USERNAME_ISNT_AVAILABLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleEvent(json: JsonObject) {
|
||||||
|
val post = {
|
||||||
|
when (json.get("action").asInt) {
|
||||||
|
UIActions.USERNAME_AVAILABLE -> {
|
||||||
|
view.loadingScreen(false)
|
||||||
|
view.showMessage(AppHelper.getContext().getString(R.string.username_saved))
|
||||||
|
}
|
||||||
|
UIActions.USERNAME_ISNT_AVAILABLE -> {
|
||||||
|
view.loadingScreen(false)
|
||||||
|
view.showMessage(AppHelper.getContext().getString(R.string.username_isnt_saved))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mainThreadHandler.post(post)
|
||||||
|
}
|
||||||
|
}
|
@ -2,19 +2,17 @@ package io.github.chronosx88.influence.presenters;
|
|||||||
|
|
||||||
import com.google.gson.JsonObject;
|
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.contracts.observer.IObserver;
|
||||||
import io.github.chronosx88.influence.contracts.startchat.IStartChatLogicContract;
|
|
||||||
import io.github.chronosx88.influence.contracts.startchat.IStartChatPresenterContract;
|
|
||||||
import io.github.chronosx88.influence.contracts.startchat.IStartChatViewContract;
|
|
||||||
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.helpers.actions.UIActions;
|
||||||
import io.github.chronosx88.influence.logic.StartChatLogic;
|
import io.github.chronosx88.influence.logic.StartChatLogic;
|
||||||
|
|
||||||
public class StartChatPresenter implements IStartChatPresenterContract, IObserver {
|
public class StartChatPresenter implements CoreContracts.IStartChatPresenterContract, IObserver {
|
||||||
private IStartChatViewContract view;
|
private CoreContracts.IStartChatViewContract view;
|
||||||
private IStartChatLogicContract logic;
|
private CoreContracts.IStartChatLogicContract logic;
|
||||||
|
|
||||||
public StartChatPresenter(IStartChatViewContract view) {
|
public StartChatPresenter(CoreContracts.IStartChatViewContract view) {
|
||||||
this.view = view;
|
this.view = view;
|
||||||
this.logic = new StartChatLogic();
|
this.logic = new StartChatLogic();
|
||||||
AppHelper.getObservable().register(this);
|
AppHelper.getObservable().register(this);
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.views;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.ImageButton;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.appcompat.widget.Toolbar;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import io.github.chronosx88.influence.R;
|
|
||||||
import io.github.chronosx88.influence.contracts.chatactivity.IChatViewContract;
|
|
||||||
import io.github.chronosx88.influence.helpers.ChatAdapter;
|
|
||||||
import io.github.chronosx88.influence.models.roomEntities.MessageEntity;
|
|
||||||
import io.github.chronosx88.influence.presenters.ChatPresenter;
|
|
||||||
|
|
||||||
public class ChatActivity extends AppCompatActivity implements IChatViewContract {
|
|
||||||
private ChatAdapter chatAdapter;
|
|
||||||
private RecyclerView messageList;
|
|
||||||
private ImageButton sendMessageButton;
|
|
||||||
private EditText messageTextEdit;
|
|
||||||
private TextView contactUsernameTextView;
|
|
||||||
private ChatPresenter presenter;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
setContentView(R.layout.activity_chat);
|
|
||||||
|
|
||||||
Intent intent = getIntent();
|
|
||||||
|
|
||||||
presenter = new ChatPresenter(this, intent.getStringExtra("chatID"));
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar_chat_activity);
|
|
||||||
setSupportActionBar(toolbar);
|
|
||||||
getSupportActionBar().setTitle("");
|
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
getSupportActionBar().setHomeButtonEnabled(true);
|
|
||||||
messageList = findViewById(R.id.message_list);
|
|
||||||
chatAdapter = new ChatAdapter();
|
|
||||||
presenter.updateAdapter();
|
|
||||||
messageList.setAdapter(chatAdapter);
|
|
||||||
messageList.setLayoutManager(new LinearLayoutManager(this));
|
|
||||||
contactUsernameTextView = findViewById(R.id.appbar_username);
|
|
||||||
messageTextEdit = findViewById(R.id.message_input);
|
|
||||||
sendMessageButton = findViewById(R.id.send_button);
|
|
||||||
sendMessageButton.setOnClickListener((v) -> {
|
|
||||||
if(messageTextEdit.getText().toString().equals("")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
presenter.sendMessage(messageTextEdit.getText().toString());
|
|
||||||
messageTextEdit.setText("");
|
|
||||||
messageList.scrollToPosition(chatAdapter.getItemCount()-1);
|
|
||||||
});
|
|
||||||
contactUsernameTextView.setText(intent.getStringExtra("contactUsername"));
|
|
||||||
messageList.scrollToPosition(chatAdapter.getItemCount()-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateMessageList(MessageEntity message) {
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
chatAdapter.addMessage(message);
|
|
||||||
chatAdapter.notifyDataSetChanged();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateMessageList(List<MessageEntity> messages) {
|
|
||||||
runOnUiThread(() -> {
|
|
||||||
chatAdapter.addMessages(messages);
|
|
||||||
chatAdapter.notifyDataSetChanged();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
switch(item.getItemId()) {
|
|
||||||
case android.R.id.home:
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDestroy() {
|
|
||||||
super.onDestroy();
|
|
||||||
presenter.onDestroy();
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,86 @@
|
|||||||
|
package io.github.chronosx88.influence.views
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.widget.EditText
|
||||||
|
import android.widget.ImageButton
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.appcompat.widget.Toolbar
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import io.github.chronosx88.influence.R
|
||||||
|
import io.github.chronosx88.influence.contracts.CoreContracts
|
||||||
|
import io.github.chronosx88.influence.helpers.ChatAdapter
|
||||||
|
import io.github.chronosx88.influence.models.roomEntities.MessageEntity
|
||||||
|
import io.github.chronosx88.influence.presenters.ChatPresenter
|
||||||
|
|
||||||
|
class ChatActivity : AppCompatActivity(), CoreContracts.IChatViewContract {
|
||||||
|
private var chatAdapter: ChatAdapter? = null
|
||||||
|
private var messageList: RecyclerView? = null
|
||||||
|
private var sendMessageButton: ImageButton? = null
|
||||||
|
private var messageTextEdit: EditText? = null
|
||||||
|
private var contactUsernameTextView: TextView? = null
|
||||||
|
private var presenter: ChatPresenter? = null
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
setContentView(R.layout.activity_chat)
|
||||||
|
|
||||||
|
val intent = intent
|
||||||
|
|
||||||
|
presenter = ChatPresenter(this, intent.getStringExtra("chatID"))
|
||||||
|
val toolbar = findViewById<Toolbar>(R.id.toolbar_chat_activity)
|
||||||
|
setSupportActionBar(toolbar)
|
||||||
|
supportActionBar!!.setTitle("")
|
||||||
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||||
|
supportActionBar!!.setHomeButtonEnabled(true)
|
||||||
|
messageList = findViewById(R.id.message_list)
|
||||||
|
chatAdapter = ChatAdapter()
|
||||||
|
presenter!!.updateAdapter()
|
||||||
|
messageList!!.adapter = chatAdapter
|
||||||
|
messageList!!.layoutManager = LinearLayoutManager(this)
|
||||||
|
contactUsernameTextView = findViewById(R.id.appbar_username)
|
||||||
|
messageTextEdit = findViewById(R.id.message_input)
|
||||||
|
sendMessageButton = findViewById(R.id.send_button)
|
||||||
|
sendMessageButton!!.setOnClickListener sendMessageButton@{
|
||||||
|
if (messageTextEdit!!.text.toString() == "") {
|
||||||
|
return@sendMessageButton
|
||||||
|
}
|
||||||
|
presenter!!.sendMessage(messageTextEdit!!.text.toString())
|
||||||
|
messageTextEdit!!.setText("")
|
||||||
|
messageList!!.scrollToPosition(chatAdapter!!.itemCount - 1)
|
||||||
|
}
|
||||||
|
contactUsernameTextView!!.text = intent.getStringExtra("contactUsername")
|
||||||
|
messageList!!.scrollToPosition(chatAdapter!!.itemCount - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateMessageList(message: MessageEntity) {
|
||||||
|
runOnUiThread {
|
||||||
|
chatAdapter!!.addMessage(message)
|
||||||
|
chatAdapter!!.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateMessageList(messages: List<MessageEntity>) {
|
||||||
|
runOnUiThread {
|
||||||
|
chatAdapter!!.addMessages(messages)
|
||||||
|
chatAdapter!!.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
when (item.itemId) {
|
||||||
|
android.R.id.home -> {
|
||||||
|
finish()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
presenter!!.onDestroy()
|
||||||
|
}
|
||||||
|
}
|
@ -13,8 +13,7 @@ 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;
|
||||||
import io.github.chronosx88.influence.R;
|
import io.github.chronosx88.influence.R;
|
||||||
import io.github.chronosx88.influence.contracts.mainactivity.IMainPresenterContract;
|
import io.github.chronosx88.influence.contracts.CoreContracts;
|
||||||
import io.github.chronosx88.influence.contracts.mainactivity.IMainViewContract;
|
|
||||||
import io.github.chronosx88.influence.contracts.observer.IObserver;
|
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.helpers.actions.UIActions;
|
||||||
@ -23,9 +22,9 @@ 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 io.github.chronosx88.influence.views.fragments.StartChatFragment;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity implements IObserver, IMainViewContract {
|
public class MainActivity extends AppCompatActivity implements IObserver, CoreContracts.IMainViewContract {
|
||||||
|
|
||||||
private IMainPresenterContract presenter;
|
private CoreContracts.IMainPresenterContract presenter;
|
||||||
private ProgressDialog progressDialog;
|
private ProgressDialog progressDialog;
|
||||||
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
|
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
|
||||||
= new BottomNavigationView.OnNavigationItemSelectedListener() {
|
= new BottomNavigationView.OnNavigationItemSelectedListener() {
|
||||||
|
@ -1,92 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.views.fragments;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import io.github.chronosx88.influence.R;
|
|
||||||
import io.github.chronosx88.influence.contracts.chatlist.IChatListPresenterContract;
|
|
||||||
import io.github.chronosx88.influence.contracts.chatlist.IChatListViewContract;
|
|
||||||
import io.github.chronosx88.influence.contracts.observer.IObserver;
|
|
||||||
import io.github.chronosx88.influence.helpers.AppHelper;
|
|
||||||
import io.github.chronosx88.influence.helpers.ChatListAdapter;
|
|
||||||
import io.github.chronosx88.influence.helpers.actions.UIActions;
|
|
||||||
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
|
||||||
import io.github.chronosx88.influence.presenters.ChatListPresenter;
|
|
||||||
|
|
||||||
public class ChatListFragment extends Fragment implements IChatListViewContract, IObserver {
|
|
||||||
private IChatListPresenterContract presenter;
|
|
||||||
private RecyclerView chatList;
|
|
||||||
private Handler mainThreadHandler;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
AppHelper.getObservable().register(this);
|
|
||||||
this.mainThreadHandler = new Handler(getContext().getMainLooper());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
return inflater.inflate(R.layout.chatlist_fragment, container, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
|
||||||
super.onViewCreated(view, savedInstanceState);
|
|
||||||
chatList = view.findViewById(R.id.chatlist_container);
|
|
||||||
chatList.setLayoutManager(new LinearLayoutManager(getContext()));
|
|
||||||
presenter = new ChatListPresenter(this);
|
|
||||||
presenter.updateChatList();
|
|
||||||
registerForContextMenu(chatList);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setRecycleAdapter(ChatListAdapter adapter) {
|
|
||||||
chatList.setAdapter(adapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
presenter.updateChatList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleEvent(JsonObject object) {
|
|
||||||
switch (object.get("action").getAsInt()) {
|
|
||||||
case UIActions.SUCCESSFUL_CREATE_CHAT:
|
|
||||||
case UIActions.NEW_CHAT: {
|
|
||||||
presenter.updateChatList();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateChatList(ChatListAdapter adapter, List<ChatEntity> chats) {
|
|
||||||
mainThreadHandler.post(() -> {
|
|
||||||
adapter.setChatList(chats);
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onContextItemSelected(@NonNull MenuItem item) {
|
|
||||||
presenter.onContextItemSelected(item);
|
|
||||||
return super.onContextItemSelected(item);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,76 @@
|
|||||||
|
package io.github.chronosx88.influence.views.fragments
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.os.Handler
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import io.github.chronosx88.influence.R
|
||||||
|
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.ChatListAdapter
|
||||||
|
import io.github.chronosx88.influence.helpers.actions.UIActions
|
||||||
|
import io.github.chronosx88.influence.models.roomEntities.ChatEntity
|
||||||
|
import io.github.chronosx88.influence.presenters.ChatListPresenter
|
||||||
|
|
||||||
|
class ChatListFragment : Fragment(), CoreContracts.IChatListViewContract, IObserver {
|
||||||
|
private var presenter: CoreContracts.IChatListPresenterContract? = null
|
||||||
|
private var chatList: RecyclerView? = null
|
||||||
|
private var mainThreadHandler: Handler? = null
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
AppHelper.getObservable().register(this)
|
||||||
|
this.mainThreadHandler = Handler(context!!.mainLooper)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?): View? {
|
||||||
|
return inflater.inflate(R.layout.chatlist_fragment, container, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
chatList = view.findViewById(R.id.chatlist_container)
|
||||||
|
chatList!!.layoutManager = LinearLayoutManager(context)
|
||||||
|
presenter = ChatListPresenter(this)
|
||||||
|
presenter!!.updateChatList()
|
||||||
|
registerForContextMenu(chatList!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setRecycleAdapter(adapter: ChatListAdapter) {
|
||||||
|
chatList!!.adapter = adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
presenter!!.updateChatList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleEvent(`object`: JsonObject) {
|
||||||
|
when (`object`.get("action").asInt) {
|
||||||
|
UIActions.SUCCESSFUL_CREATE_CHAT, UIActions.NEW_CHAT -> {
|
||||||
|
presenter!!.updateChatList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateChatList(adapter: ChatListAdapter, chats: List<ChatEntity>) {
|
||||||
|
mainThreadHandler!!.post {
|
||||||
|
adapter.setChatList(chats)
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onContextItemSelected(item: MenuItem): Boolean {
|
||||||
|
presenter!!.onContextItemSelected(item)
|
||||||
|
return super.onContextItemSelected(item)
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,33 @@
|
|||||||
package io.github.chronosx88.influence.views.fragments;
|
package io.github.chronosx88.influence.views.fragments;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.ProgressDialog;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
import io.github.chronosx88.influence.R;
|
import io.github.chronosx88.influence.R;
|
||||||
|
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.presenters.SettingsPresenter;
|
||||||
|
|
||||||
public class SettingsFragment extends PreferenceFragmentCompat {
|
public class SettingsFragment extends PreferenceFragmentCompat implements CoreContracts.ISettingsView {
|
||||||
|
private ProgressDialog progressDialog;
|
||||||
|
private SettingsPresenter presenter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle bundle, String s) {
|
public void onCreatePreferences(Bundle bundle, String s) {
|
||||||
|
progressDialog = new ProgressDialog(getContext(), R.style.AlertDialogTheme);
|
||||||
|
progressDialog.setCancelable(false);
|
||||||
|
progressDialog.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
|
||||||
|
presenter = new SettingsPresenter(this);
|
||||||
// Load the Preferences from the XML file
|
// Load the Preferences from the XML file
|
||||||
addPreferencesFromResource(R.xml.main_settings);
|
addPreferencesFromResource(R.xml.main_settings);
|
||||||
getPreferenceScreen().getPreference(0).setSummary(AppHelper.getPeerID());
|
getPreferenceScreen().getPreference(0).setSummary(AppHelper.getPeerID());
|
||||||
@ -24,5 +38,42 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
|||||||
Toast.makeText(AppHelper.getContext(), "Скопировано в буфер обмена!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(AppHelper.getContext(), "Скопировано в буфер обмена!", Toast.LENGTH_SHORT).show();
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
|
getPreferenceScreen().getPreference(1).setSummary(AppHelper.getUsername());
|
||||||
|
getPreferenceScreen().getPreference(1).setOnPreferenceClickListener((v) -> {
|
||||||
|
setupUsernameEditDialog().show();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadingScreen(boolean state) {
|
||||||
|
if(state)
|
||||||
|
progressDialog.show();
|
||||||
|
else
|
||||||
|
progressDialog.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showMessage(@NotNull String message) {
|
||||||
|
Toast.makeText(AppHelper.getContext(), message, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AlertDialog.Builder setupUsernameEditDialog() {
|
||||||
|
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getContext());
|
||||||
|
alertDialog.setTitle(getContext().getString(R.string.username_settings));
|
||||||
|
|
||||||
|
final EditText input = new EditText(getContext());
|
||||||
|
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
LinearLayout.LayoutParams.MATCH_PARENT);
|
||||||
|
input.setSingleLine();
|
||||||
|
input.setLayoutParams(lp);
|
||||||
|
alertDialog.setView(input);
|
||||||
|
|
||||||
|
alertDialog.setPositiveButton(getContext().getString(R.string.ok), (dialog, which) -> presenter.updateUsername(input.getText().toString()));
|
||||||
|
|
||||||
|
alertDialog.setNegativeButton(getContext().getString(R.string.cancel), (dialog, which) -> dialog.cancel());
|
||||||
|
|
||||||
|
return alertDialog;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,10 @@ import androidx.annotation.Nullable;
|
|||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import io.github.chronosx88.influence.R;
|
import io.github.chronosx88.influence.R;
|
||||||
import io.github.chronosx88.influence.contracts.startchat.IStartChatViewContract;
|
import io.github.chronosx88.influence.contracts.CoreContracts;
|
||||||
import io.github.chronosx88.influence.presenters.StartChatPresenter;
|
import io.github.chronosx88.influence.presenters.StartChatPresenter;
|
||||||
|
|
||||||
public class StartChatFragment extends Fragment implements IStartChatViewContract {
|
public class StartChatFragment extends Fragment implements CoreContracts.IStartChatViewContract {
|
||||||
private TextInputLayout textInputPeerID;
|
private TextInputLayout textInputPeerID;
|
||||||
private ProgressDialog progressDialog;
|
private ProgressDialog progressDialog;
|
||||||
private Button createChatButton;
|
private Button createChatButton;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:hint="Peer ID"/>
|
android:hint="@string/username_hint"/>
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
10
app/src/main/res/values-ru-rRU/strings.xml
Normal file
10
app/src/main/res/values-ru-rRU/strings.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">Influence</string>
|
||||||
|
<string name="username_saved">Ваше имя пользователя успешно сохранено!</string>
|
||||||
|
<string name="username_isnt_saved">К сожалению, это имя пользователя занято.</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Отмена</string>
|
||||||
|
<string name="username_settings">Ваше имя пользователя</string>
|
||||||
|
<string name="username_hint">Имя пользователя</string>
|
||||||
|
</resources>
|
@ -1,3 +1,9 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">Influence</string>
|
<string name="app_name">Influence</string>
|
||||||
|
<string name="username_saved">Your username saved successfully!</string>
|
||||||
|
<string name="username_isnt_saved">Sorry, this username is busy.</string>
|
||||||
|
<string name="ok">OK</string>
|
||||||
|
<string name="cancel">Cancel</string>
|
||||||
|
<string name="username_settings">Your username</string>
|
||||||
|
<string name="username_hint">Username</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -4,6 +4,10 @@
|
|||||||
android:key="peerID"
|
android:key="peerID"
|
||||||
android:title="Мой Peer ID"
|
android:title="Мой Peer ID"
|
||||||
android:summary=""/>
|
android:summary=""/>
|
||||||
|
<Preference
|
||||||
|
android:key="username"
|
||||||
|
android:title="Мой username"
|
||||||
|
android:summary=""/>
|
||||||
<EditTextPreference
|
<EditTextPreference
|
||||||
android:key="bootstrapAddress"
|
android:key="bootstrapAddress"
|
||||||
android:title="Адрес Bootstrap-ноды"
|
android:title="Адрес Bootstrap-ноды"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.21'
|
ext.kotlin_version = '1.3.30'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
|
Loading…
Reference in New Issue
Block a user