mirror of
https://github.com/ChronosX88/Influence-P2P.git
synced 2024-11-22 15:22:18 +00:00
Now basic chat functional are working! Fully replaced with XMPP.
This commit is contained in:
parent
1f0416fda4
commit
482d0be0c1
@ -64,6 +64,9 @@ dependencies {
|
|||||||
implementation 'org.igniterealtime.smack:smack-android:4.3.3'
|
implementation 'org.igniterealtime.smack:smack-android:4.3.3'
|
||||||
implementation 'org.igniterealtime.smack:smack-extensions:4.3.3'
|
implementation 'org.igniterealtime.smack:smack-extensions:4.3.3'
|
||||||
|
|
||||||
|
implementation 'com.github.stfalcon:chatkit:0.3.3'
|
||||||
|
implementation 'net.sourceforge.streamsupport:streamsupport:1.7.0'
|
||||||
|
|
||||||
}
|
}
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -2,39 +2,27 @@
|
|||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 2,
|
"version": 2,
|
||||||
"identityHash": "81501115d10a6dc46002667323359631",
|
"identityHash": "2409c873b47ccd635ed7d10e4d8604f8",
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"tableName": "messages",
|
"tableName": "messages",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`messageID` TEXT NOT NULL, `type` INTEGER NOT NULL, `chatID` TEXT, `senderID` TEXT, `username` TEXT, `timestamp` INTEGER NOT NULL, `text` TEXT, `isSent` INTEGER NOT NULL, `isRead` INTEGER NOT NULL, PRIMARY KEY(`messageID`))",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`messageID` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `jid` TEXT, `senderJid` TEXT, `timestamp` INTEGER NOT NULL, `text` TEXT, `isSent` INTEGER NOT NULL, `isRead` INTEGER NOT NULL)",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "messageID",
|
"fieldPath": "messageID",
|
||||||
"columnName": "messageID",
|
"columnName": "messageID",
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "type",
|
|
||||||
"columnName": "type",
|
|
||||||
"affinity": "INTEGER",
|
"affinity": "INTEGER",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "chatID",
|
"fieldPath": "jid",
|
||||||
"columnName": "chatID",
|
"columnName": "jid",
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "senderID",
|
"fieldPath": "senderJid",
|
||||||
"columnName": "senderID",
|
"columnName": "senderJid",
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "username",
|
|
||||||
"columnName": "username",
|
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
@ -67,55 +55,43 @@
|
|||||||
"columnNames": [
|
"columnNames": [
|
||||||
"messageID"
|
"messageID"
|
||||||
],
|
],
|
||||||
"autoGenerate": false
|
"autoGenerate": true
|
||||||
},
|
},
|
||||||
"indices": [],
|
"indices": [],
|
||||||
"foreignKeys": []
|
"foreignKeys": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tableName": "chats",
|
"tableName": "chats",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`chatID` TEXT NOT NULL, `name` TEXT, `metadataRef` TEXT, `membersRef` TEXT, `bannedUsers` TEXT, `chunkCursor` INTEGER NOT NULL, PRIMARY KEY(`chatID`))",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`jid` TEXT NOT NULL, `chatName` TEXT, `users` TEXT, `unreadMessagesCount` INTEGER NOT NULL, PRIMARY KEY(`jid`))",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "chatID",
|
"fieldPath": "jid",
|
||||||
"columnName": "chatID",
|
"columnName": "jid",
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "name",
|
"fieldPath": "chatName",
|
||||||
"columnName": "name",
|
"columnName": "chatName",
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "metadataRef",
|
"fieldPath": "users",
|
||||||
"columnName": "metadataRef",
|
"columnName": "users",
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": false
|
"notNull": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "membersRef",
|
"fieldPath": "unreadMessagesCount",
|
||||||
"columnName": "membersRef",
|
"columnName": "unreadMessagesCount",
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "bannedUsers",
|
|
||||||
"columnName": "bannedUsers",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "chunkCursor",
|
|
||||||
"columnName": "chunkCursor",
|
|
||||||
"affinity": "INTEGER",
|
"affinity": "INTEGER",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"primaryKey": {
|
"primaryKey": {
|
||||||
"columnNames": [
|
"columnNames": [
|
||||||
"chatID"
|
"jid"
|
||||||
],
|
],
|
||||||
"autoGenerate": false
|
"autoGenerate": false
|
||||||
},
|
},
|
||||||
@ -126,7 +102,7 @@
|
|||||||
"views": [],
|
"views": [],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"81501115d10a6dc46002667323359631\")"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"2409c873b47ccd635ed7d10e4d8604f8\")"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -56,9 +56,6 @@ public class XMPPConnection implements ConnectionListener {
|
|||||||
|
|
||||||
public enum ConnectionState {
|
public enum ConnectionState {
|
||||||
CONNECTED,
|
CONNECTED,
|
||||||
AUTHENTICATED,
|
|
||||||
CONNECTING,
|
|
||||||
DISCONNECTING,
|
|
||||||
DISCONNECTED
|
DISCONNECTED
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,6 +65,8 @@ public class XMPPConnection implements ConnectionListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public XMPPConnection(Context context) {
|
public XMPPConnection(Context context) {
|
||||||
|
this.prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
this.context = context;
|
||||||
String jid = prefs.getString("jid", null);
|
String jid = prefs.getString("jid", null);
|
||||||
String password = prefs.getString("pass", null);
|
String password = prefs.getString("pass", null);
|
||||||
if(jid != null && password != null) {
|
if(jid != null && password != null) {
|
||||||
@ -78,8 +77,6 @@ public class XMPPConnection implements ConnectionListener {
|
|||||||
credentials.password = password;
|
credentials.password = password;
|
||||||
}
|
}
|
||||||
networkHandler = new NetworkHandler(context);
|
networkHandler = new NetworkHandler(context);
|
||||||
prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
this.context = context;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void connect() throws XMPPException, SmackException, IOException {
|
public void connect() throws XMPPException, SmackException, IOException {
|
||||||
@ -97,6 +94,9 @@ public class XMPPConnection implements ConnectionListener {
|
|||||||
|
|
||||||
connection = new XMPPTCPConnection(conf);
|
connection = new XMPPTCPConnection(conf);
|
||||||
connection.addConnectionListener(this);
|
connection.addConnectionListener(this);
|
||||||
|
if(credentials.jabberHost.equals("") && credentials.password.equals("") && credentials.username.equals("")){
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
connection.connect();
|
connection.connect();
|
||||||
connection.login(credentials.username, credentials.password);
|
connection.login(credentials.username, credentials.password);
|
||||||
@ -121,26 +121,28 @@ public class XMPPConnection implements ConnectionListener {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connected(org.jivesoftware.smack.XMPPConnection connection) {
|
public void connected(org.jivesoftware.smack.XMPPConnection connection) {
|
||||||
XMPPConnectionService.connectionState = ConnectionState.CONNECTED;
|
XMPPConnectionService.CONNECTION_STATE = ConnectionState.CONNECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void authenticated(org.jivesoftware.smack.XMPPConnection connection, boolean resumed) {
|
public void authenticated(org.jivesoftware.smack.XMPPConnection connection, boolean resumed) {
|
||||||
XMPPConnectionService.sessionState = SessionState.LOGGED_IN;
|
XMPPConnectionService.SESSION_STATE = SessionState.LOGGED_IN;
|
||||||
prefs.edit().putBoolean("logged_in", true).apply();
|
prefs.edit().putBoolean("logged_in", true).apply();
|
||||||
|
context.sendBroadcast(new Intent(XMPPConnectionService.INTENT_AUTHENTICATED));
|
||||||
|
AppHelper.setJid(credentials.username + "@" + credentials.jabberHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connectionClosed() {
|
public void connectionClosed() {
|
||||||
XMPPConnectionService.connectionState = ConnectionState.DISCONNECTED;
|
XMPPConnectionService.CONNECTION_STATE = ConnectionState.DISCONNECTED;
|
||||||
XMPPConnectionService.sessionState = SessionState.LOGGED_OUT;
|
XMPPConnectionService.SESSION_STATE = SessionState.LOGGED_OUT;
|
||||||
prefs.edit().putBoolean("logged_in", false).apply();
|
prefs.edit().putBoolean("logged_in", false).apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connectionClosedOnError(Exception e) {
|
public void connectionClosedOnError(Exception e) {
|
||||||
XMPPConnectionService.connectionState = ConnectionState.DISCONNECTED;
|
XMPPConnectionService.CONNECTION_STATE = ConnectionState.DISCONNECTED;
|
||||||
XMPPConnectionService.sessionState = SessionState.LOGGED_OUT;
|
XMPPConnectionService.SESSION_STATE = SessionState.LOGGED_OUT;
|
||||||
prefs.edit().putBoolean("logged_in", false).apply();
|
prefs.edit().putBoolean("logged_in", false).apply();
|
||||||
Log.e(LOG_TAG, "Connection closed, exception occurred");
|
Log.e(LOG_TAG, "Connection closed, exception occurred");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -29,6 +29,8 @@ import org.jivesoftware.smack.XMPPException;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import io.github.chronosx88.influence.helpers.AppHelper;
|
||||||
|
|
||||||
public class XMPPConnectionService extends Service {
|
public class XMPPConnectionService extends Service {
|
||||||
public static final String INTENT_NEW_MESSAGE = "io.github.chronosx88.intents.new_message";
|
public static final String INTENT_NEW_MESSAGE = "io.github.chronosx88.intents.new_message";
|
||||||
public static final String INTENT_SEND_MESSAGE = "io.github.chronosx88.intents.send_message";
|
public static final String INTENT_SEND_MESSAGE = "io.github.chronosx88.intents.send_message";
|
||||||
@ -40,18 +42,16 @@ public class XMPPConnectionService extends Service {
|
|||||||
public static final String MESSAGE_BODY = "message_body";
|
public static final String MESSAGE_BODY = "message_body";
|
||||||
public static final String MESSAGE_RECIPIENT = "message_recipient";
|
public static final String MESSAGE_RECIPIENT = "message_recipient";
|
||||||
|
|
||||||
public static XMPPConnection.ConnectionState connectionState = XMPPConnection.ConnectionState.DISCONNECTED;
|
public static XMPPConnection.ConnectionState CONNECTION_STATE = XMPPConnection.ConnectionState.DISCONNECTED;
|
||||||
public static XMPPConnection.SessionState sessionState = XMPPConnection.SessionState.LOGGED_OUT;
|
public static XMPPConnection.SessionState SESSION_STATE = XMPPConnection.SessionState.LOGGED_OUT;
|
||||||
|
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
private Handler threadHandler;
|
private Handler threadHandler;
|
||||||
private boolean isThreadAlive = false;
|
private boolean isThreadAlive = false;
|
||||||
private XMPPConnection connection;
|
private XMPPConnection connection;
|
||||||
private Context context;
|
private Context context = AppHelper.getContext();
|
||||||
|
|
||||||
public XMPPConnectionService(Context context) {
|
public XMPPConnectionService() { }
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) { return null; }
|
public IBinder onBind(Intent intent) { return null; }
|
||||||
@ -89,9 +89,8 @@ public class XMPPConnectionService extends Service {
|
|||||||
connection.connect();
|
connection.connect();
|
||||||
} catch (IOException | SmackException | XMPPException e) {
|
} catch (IOException | SmackException | XMPPException e) {
|
||||||
Intent intent = new Intent(INTENT_AUTHENTICATION_FAILED);
|
Intent intent = new Intent(INTENT_AUTHENTICATION_FAILED);
|
||||||
|
context.sendBroadcast(intent);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
//Stop the service all together.
|
|
||||||
stopSelf();
|
stopSelf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package io.github.chronosx88.influence.contracts
|
package io.github.chronosx88.influence.contracts
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.view.MenuItem
|
import com.stfalcon.chatkit.dialogs.DialogsListAdapter
|
||||||
|
import com.stfalcon.chatkit.messages.MessagesListAdapter
|
||||||
|
|
||||||
import io.github.chronosx88.influence.helpers.ChatListAdapter
|
import io.github.chronosx88.influence.models.GenericDialog
|
||||||
|
import io.github.chronosx88.influence.models.GenericMessage
|
||||||
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
|
||||||
|
|
||||||
@ -15,28 +18,23 @@ interface CoreContracts {
|
|||||||
|
|
||||||
// -----ChatList-----
|
// -----ChatList-----
|
||||||
|
|
||||||
interface IChatListLogicContract {
|
interface IDialogListLogicContract {
|
||||||
fun loadAllChats(): List<ChatEntity>
|
fun loadAllChats(): List<ChatEntity>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IChatListPresenterContract {
|
interface IDialogListPresenterContract {
|
||||||
fun updateChatList()
|
|
||||||
fun openChat(chatID: String)
|
fun openChat(chatID: String)
|
||||||
fun onContextItemSelected(item: MenuItem)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IChatListViewContract {
|
interface IChatListViewContract {
|
||||||
fun setRecycleAdapter(adapter: ChatListAdapter)
|
fun setDialogAdapter(adapter: DialogsListAdapter<GenericDialog>)
|
||||||
fun startActivity(intent: Intent)
|
fun startActivity(intent: Intent)
|
||||||
fun updateChatList(adapter: ChatListAdapter, chats: List<ChatEntity>)
|
fun getActivityContext(): Context?
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----MainActivity-----
|
// -----MainActivity-----
|
||||||
|
|
||||||
interface IMainLogicContract {
|
interface IMainLogicContract {
|
||||||
fun initPeer()
|
|
||||||
fun sendStartChatMessage(username: String)
|
|
||||||
fun shutdownPeer()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IMainPresenterContract {
|
interface IMainPresenterContract {
|
||||||
@ -53,19 +51,17 @@ interface CoreContracts {
|
|||||||
// -----ChatActivity-----
|
// -----ChatActivity-----
|
||||||
|
|
||||||
interface IChatLogicContract {
|
interface IChatLogicContract {
|
||||||
fun sendMessage(message: MessageEntity)
|
fun sendMessage(text: String): MessageEntity
|
||||||
fun stopTrackingForNewMsgs()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IChatPresenterContract {
|
interface IChatPresenterContract {
|
||||||
fun sendMessage(text: String)
|
fun sendMessage(text: String): Boolean
|
||||||
fun updateAdapter()
|
fun loadLocalMessages()
|
||||||
fun onDestroy()
|
fun onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IChatViewContract {
|
interface IChatViewContract {
|
||||||
fun updateMessageList(message: MessageEntity)
|
fun setAdapter(adapter: MessagesListAdapter<GenericMessage>)
|
||||||
fun updateMessageList(messages: List<MessageEntity>)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----SettingsFragment-----
|
// -----SettingsFragment-----
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
package io.github.chronosx88.influence.contracts.observer;
|
package io.github.chronosx88.influence.contracts.observer;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public interface IObservable {
|
public interface IObservable {
|
||||||
void register(IObserver observer);
|
void register(IObserver observer);
|
||||||
void register(INetworkObserver networkObserver);
|
|
||||||
void unregister(IObserver observer);
|
void unregister(IObserver observer);
|
||||||
void unregister(INetworkObserver networkObserver);
|
void notifyUIObservers(JSONObject jsonObject);
|
||||||
void notifyUIObservers(JsonObject jsonObject);
|
|
||||||
void notifyNetworkObservers(Object object);
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
package io.github.chronosx88.influence.contracts.observer;
|
package io.github.chronosx88.influence.contracts.observer;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public interface IObserver {
|
public interface IObserver {
|
||||||
void handleEvent(JsonObject object);
|
void handleEvent(JSONObject object) throws JSONException;
|
||||||
}
|
}
|
@ -1,105 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.helpers;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.SortedSet;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import de.hdodenhof.circleimageview.CircleImageView;
|
|
||||||
import io.github.chronosx88.influence.R;
|
|
||||||
import io.github.chronosx88.influence.models.roomEntities.MessageEntity;
|
|
||||||
|
|
||||||
public class ChatAdapter extends RecyclerView.Adapter<ChatAdapter.ViewHolder> {
|
|
||||||
private final static int RIGHT_ITEM = 0;
|
|
||||||
private final static int LEFT_ITEM = 1;
|
|
||||||
private final static int TECHNICAL_MESSAGE = 2; // TODO
|
|
||||||
|
|
||||||
private final Context context = AppHelper.getContext();
|
|
||||||
private ArrayList<MessageEntity> messages = new ArrayList<>();
|
|
||||||
private static Comparator<MessageEntity> comparator = ((o1, o2) -> Long.compare(o1.timestamp, o2.timestamp));
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public ChatAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
||||||
if(viewType == RIGHT_ITEM) {
|
|
||||||
return new ChatAdapter.ViewHolder(LayoutInflater.from(context).inflate(R.layout.message_right_item, parent, false));
|
|
||||||
} else {
|
|
||||||
return new ChatAdapter.ViewHolder(LayoutInflater.from(context).inflate(R.layout.message_left_item, parent, false));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addMessage(MessageEntity message) {
|
|
||||||
if(message != null) {
|
|
||||||
for (MessageEntity messageEntity : messages) {
|
|
||||||
if(messageEntity.messageID.equals(message.messageID)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
messages.add(message);
|
|
||||||
Collections.sort(messages, comparator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addMessages(List<MessageEntity> messages) {
|
|
||||||
this.messages.addAll(messages);
|
|
||||||
Collections.sort(messages, comparator);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull ChatAdapter.ViewHolder holder, int position) {
|
|
||||||
// Setting message text
|
|
||||||
holder.messageText.setText(messages.get(position).text);
|
|
||||||
|
|
||||||
// Setting message time (HOUR:MINUTE)
|
|
||||||
DateFormat dateFormat = DateFormat.getTimeInstance(DateFormat.SHORT);
|
|
||||||
dateFormat.setTimeZone(TimeZone.getDefault());
|
|
||||||
String time = dateFormat.format(new Date(messages.get(position).timestamp));
|
|
||||||
holder.messageTime.setText(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return messages.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemViewType(int position) {
|
|
||||||
if(messages.get(position).senderID.equals(AppHelper.getPeerID())) {
|
|
||||||
return RIGHT_ITEM;
|
|
||||||
} else {
|
|
||||||
return LEFT_ITEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
TextView messageText;
|
|
||||||
CircleImageView profileImage;
|
|
||||||
TextView messageTime;
|
|
||||||
|
|
||||||
public ViewHolder(View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
messageText = itemView.findViewById(R.id.message_text);
|
|
||||||
profileImage = itemView.findViewById(R.id.profile_image);
|
|
||||||
messageTime = itemView.findViewById(R.id.message_time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.helpers;
|
|
||||||
|
|
||||||
import android.view.ContextMenu;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
import io.github.chronosx88.influence.R;
|
|
||||||
import io.github.chronosx88.influence.contracts.IItemClickListener;
|
|
||||||
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
|
||||||
|
|
||||||
public class ChatListAdapter extends RecyclerView.Adapter<ChatListAdapter.ChatListViewHolder> {
|
|
||||||
List<ChatEntity> chatList = new ArrayList<>();
|
|
||||||
public int onClickPosition = -1;
|
|
||||||
private IItemClickListener itemClickListener;
|
|
||||||
|
|
||||||
public ChatListAdapter(IItemClickListener itemClickListener) {
|
|
||||||
this.itemClickListener = itemClickListener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public ChatListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
||||||
View view = LayoutInflater.from(parent.getContext())
|
|
||||||
.inflate(R.layout.chat_item, parent, false);
|
|
||||||
return new ChatListViewHolder(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setChatList(List<ChatEntity> entities) {
|
|
||||||
chatList.clear();
|
|
||||||
chatList.addAll(entities);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChatEntity getItem(int position) {
|
|
||||||
return chatList.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull ChatListViewHolder holder, int position) {
|
|
||||||
holder.chatName.setText(chatList.get(position).name);
|
|
||||||
holder.onLongClick(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChatEntity getChatEntity(int position) {
|
|
||||||
return chatList.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return chatList.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
class ChatListViewHolder extends RecyclerView.ViewHolder implements View.OnCreateContextMenuListener {
|
|
||||||
TextView chatName;
|
|
||||||
|
|
||||||
public ChatListViewHolder(View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
chatName = itemView.findViewById(R.id.chat_name);
|
|
||||||
itemView.setOnCreateContextMenuListener(this);
|
|
||||||
itemView.setOnClickListener((v) -> {
|
|
||||||
itemClickListener.onItemClick(v, getAdapterPosition());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onLongClick(int position) {
|
|
||||||
itemView.setOnLongClickListener((v) -> {
|
|
||||||
onClickPosition = position;
|
|
||||||
itemView.showContextMenu();
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
|
||||||
menu.add(0, 0, 0, "Remove chat");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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.helpers;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.ObjectOutputStream;
|
||||||
|
|
||||||
|
public class JavaSerializer<T> {
|
||||||
|
public byte[] serialize(T object) {
|
||||||
|
ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArray);
|
||||||
|
objectOutputStream.writeObject(object);
|
||||||
|
objectOutputStream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return byteArray.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T deserialize(byte[] serializedObject) {
|
||||||
|
if(serializedObject == null)
|
||||||
|
return null;
|
||||||
|
ByteArrayInputStream inputStream = new ByteArrayInputStream(serializedObject);
|
||||||
|
Object object = null;
|
||||||
|
try {
|
||||||
|
ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
|
||||||
|
object = objectInputStream.readObject();
|
||||||
|
} catch (ClassNotFoundException | IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return (T) object;
|
||||||
|
}
|
||||||
|
}
|
@ -10,14 +10,14 @@ import java.security.NoSuchAlgorithmException;
|
|||||||
|
|
||||||
public class KeyPairManager {
|
public class KeyPairManager {
|
||||||
private File keyPairDir;
|
private File keyPairDir;
|
||||||
private Serializer<KeyPair> serializer;
|
private JavaSerializer<KeyPair> serializer;
|
||||||
|
|
||||||
public KeyPairManager() {
|
public KeyPairManager() {
|
||||||
this.keyPairDir = new File(AppHelper.getContext().getFilesDir().getAbsoluteFile(), "keyPairs");
|
this.keyPairDir = new File(AppHelper.getContext().getFilesDir().getAbsoluteFile(), "keyPairs");
|
||||||
if(!this.keyPairDir.exists()) {
|
if(!this.keyPairDir.exists()) {
|
||||||
this.keyPairDir.mkdir();
|
this.keyPairDir.mkdir();
|
||||||
}
|
}
|
||||||
this.serializer = new Serializer<>();
|
this.serializer = new JavaSerializer<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeyPair openMainKeyPair() {
|
public KeyPair openMainKeyPair() {
|
||||||
|
@ -13,7 +13,7 @@ public class LocalDBWrapper {
|
|||||||
private static RoomHelper dbInstance = AppHelper.getChatDB();
|
private static RoomHelper dbInstance = AppHelper.getChatDB();
|
||||||
|
|
||||||
public static void createChatEntry(String jid, String chatName) {
|
public static void createChatEntry(String jid, String chatName) {
|
||||||
dbInstance.chatDao().addChat(new ChatEntity(jid, chatName));
|
dbInstance.chatDao().addChat(new ChatEntity(jid, chatName, new ArrayList<>(), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long createMessageEntry(String jid, String senderJid, long timestamp, String text, boolean isSent, boolean isRead) {
|
public static long createMessageEntry(String jid, String senderJid, long timestamp, String text, boolean isSent, boolean isRead) {
|
||||||
|
@ -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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.github.chronosx88.influence.helpers;
|
||||||
|
|
||||||
|
public class ObservableActions {
|
||||||
|
public static final int NEW_CHAT_CREATED = 0x0;
|
||||||
|
}
|
@ -3,28 +3,48 @@ package io.github.chronosx88.influence.helpers;
|
|||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
public class ObservableUtils {
|
public class ObservableUtils {
|
||||||
public static void notifyUI(int action) {
|
public static void notifyUI(int action) {
|
||||||
JsonObject jsonObject = new JsonObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
jsonObject.addProperty("action", action);
|
try {
|
||||||
|
jsonObject.put("action", action);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
AppHelper.getObservable().notifyUIObservers(jsonObject);
|
AppHelper.getObservable().notifyUIObservers(jsonObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifyUI(int action, String... additional) {
|
public static void notifyUI(int action, String... additional) {
|
||||||
JsonObject jsonObject = new JsonObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
jsonObject.addProperty("action", action);
|
try {
|
||||||
JsonArray jsonArray = new JsonArray();
|
jsonObject.put("action", action);
|
||||||
for(String info : additional) {
|
} catch (JSONException e) {
|
||||||
jsonArray.add(info);
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
for(String info : additional) {
|
||||||
|
jsonArray.put(info);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
jsonObject.put("additional", jsonArray);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
jsonObject.add("additional", jsonArray);
|
|
||||||
AppHelper.getObservable().notifyUIObservers(jsonObject);
|
AppHelper.getObservable().notifyUIObservers(jsonObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void notifyUI(int action, int additional) {
|
public static void notifyUI(int action, int additional) {
|
||||||
JsonObject jsonObject = new JsonObject();
|
JSONObject jsonObject = new JSONObject();
|
||||||
jsonObject.addProperty("action", action);
|
try {
|
||||||
jsonObject.addProperty("additional", additional);
|
jsonObject.put("action", action);
|
||||||
|
jsonObject.put("additional", additional);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
AppHelper.getObservable().notifyUIObservers(jsonObject);
|
AppHelper.getObservable().notifyUIObservers(jsonObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,16 +8,18 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
import androidx.room.TypeConverter;
|
import androidx.room.TypeConverter;
|
||||||
|
|
||||||
|
import io.github.chronosx88.influence.models.GenericUser;
|
||||||
|
|
||||||
public class RoomTypeConverter {
|
public class RoomTypeConverter {
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
public static ArrayList<String> fromString(String value) {
|
public static ArrayList<GenericUser> fromString(String value) {
|
||||||
Type listType = new TypeToken<ArrayList<String>>() {}.getType();
|
Type listType = new TypeToken<ArrayList<String>>() {}.getType();
|
||||||
return new Gson().fromJson(value, listType);
|
return new Gson().fromJson(value, listType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@TypeConverter
|
@TypeConverter
|
||||||
public static String fromArrayList(ArrayList<String> list) {
|
public static <T> String fromArrayList(ArrayList<GenericUser> list) {
|
||||||
Gson gson = new Gson();
|
Gson gson = new Gson();
|
||||||
return gson.toJson(list);
|
return gson.toJson(list);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ 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 CoreContracts.IChatListLogicContract {
|
public class ChatListLogic implements CoreContracts.IDialogListLogicContract {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ChatEntity> loadAllChats() {
|
public List<ChatEntity> loadAllChats() {
|
||||||
|
@ -1,182 +1,39 @@
|
|||||||
package io.github.chronosx88.influence.logic;
|
package io.github.chronosx88.influence.logic;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import android.content.Intent;
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
|
|
||||||
import net.tomp2p.peers.Number640;
|
import com.instacart.library.truetime.TrueTime;
|
||||||
import net.tomp2p.storage.Data;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
|
import io.github.chronosx88.influence.XMPPConnection;
|
||||||
|
import io.github.chronosx88.influence.XMPPConnectionService;
|
||||||
import io.github.chronosx88.influence.contracts.CoreContracts;
|
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.LocalDBWrapper;
|
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
||||||
import io.github.chronosx88.influence.helpers.ObservableUtils;
|
|
||||||
import io.github.chronosx88.influence.helpers.actions.NetworkActions;
|
|
||||||
import io.github.chronosx88.influence.helpers.actions.UIActions;
|
|
||||||
import io.github.chronosx88.influence.models.JoinChatMessage;
|
|
||||||
import io.github.chronosx88.influence.models.NextChunkReference;
|
|
||||||
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 CoreContracts.IChatLogicContract {
|
public class ChatLogic implements CoreContracts.IChatLogicContract {
|
||||||
private static Gson gson = new Gson();
|
|
||||||
private String chatID;
|
private String chatID;
|
||||||
private volatile String newMessage = "";
|
|
||||||
private ChatEntity chatEntity;
|
private ChatEntity chatEntity;
|
||||||
private Thread checkNewMessagesThread = null;
|
//private KeyPairManager keyPairManager;
|
||||||
private KeyPairManager keyPairManager;
|
|
||||||
private Timer timer;
|
|
||||||
|
|
||||||
public ChatLogic(ChatEntity chatEntity) {
|
public ChatLogic(ChatEntity chatEntity) {
|
||||||
this.chatEntity = chatEntity;
|
this.chatEntity = chatEntity;
|
||||||
this.chatID = chatEntity.chatID;
|
this.chatID = chatEntity.jid;
|
||||||
TimerTask timerTask = new TimerTask() {
|
//this.keyPairManager = new KeyPairManager();
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
checkForNewMessages();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.timer = new Timer();
|
|
||||||
if(AppHelper.getPeerDHT() != null) {
|
|
||||||
timer.schedule(timerTask, 1, 1000);
|
|
||||||
}
|
|
||||||
this.keyPairManager = new KeyPairManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendMessage(MessageEntity message) {
|
public MessageEntity sendMessage(String text) {
|
||||||
if(AppHelper.getPeerDHT() == null) {
|
if (XMPPConnectionService.CONNECTION_STATE.equals(XMPPConnection.ConnectionState.CONNECTED)) {
|
||||||
ObservableUtils.notifyUI(UIActions.NODE_IS_OFFLINE);
|
Intent intent = new Intent(XMPPConnectionService.INTENT_SEND_MESSAGE);
|
||||||
return;
|
intent.putExtra(XMPPConnectionService.MESSAGE_BODY, text);
|
||||||
|
intent.putExtra(XMPPConnectionService.MESSAGE_RECIPIENT, chatEntity.jid);
|
||||||
|
AppHelper.getContext().sendBroadcast(intent);
|
||||||
|
long messageID = LocalDBWrapper.createMessageEntry(chatID, AppHelper.getJid(), TrueTime.now().getTime(), text, false, false);
|
||||||
|
return LocalDBWrapper.getMessageByID(messageID);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
new Thread(() -> {
|
|
||||||
Data data = null;
|
|
||||||
try {
|
|
||||||
data = new Data(gson.toJson(new TextMessage(message.senderID, message.messageID, message.chatID, message.username, message.timestamp, message.text, false)));
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
data.protectEntry(keyPairManager.getKeyPair("mainKeyPair"));
|
|
||||||
P2PUtils.put(chatID + "_messages" + chatEntity.chunkCursor, message.messageID, data);
|
|
||||||
try {
|
|
||||||
P2PUtils.put(chatID + "_newMessage", null, new Data(message.messageID));
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkForNewMessages() {
|
|
||||||
if(checkNewMessagesThread == null) {
|
|
||||||
checkNewMessagesThread = new Thread(() -> {
|
|
||||||
Map<Number640, Data> data = P2PUtils.get(chatID + "_newMessage");
|
|
||||||
if(data != null) {
|
|
||||||
for(Map.Entry<Number640, Data> entry : data.entrySet()) {
|
|
||||||
String newMessage = null;
|
|
||||||
try {
|
|
||||||
newMessage = (String) entry.getValue().object();
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if(!newMessage.equals(this.newMessage)) {
|
|
||||||
handleNewMessages(chatEntity.chunkCursor);
|
|
||||||
this.newMessage = newMessage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!checkNewMessagesThread.isAlive()) {
|
|
||||||
checkNewMessagesThread = new Thread(() -> {
|
|
||||||
Map<Number640, Data> data = P2PUtils.get(chatID + "_newMessage");
|
|
||||||
if(data != null) {
|
|
||||||
for(Map.Entry<Number640, Data> entry : data.entrySet()) {
|
|
||||||
String newMessage = null;
|
|
||||||
try {
|
|
||||||
newMessage = (String) entry.getValue().object();
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if(!newMessage.equals(this.newMessage)) {
|
|
||||||
handleNewMessages(chatEntity.chunkCursor);
|
|
||||||
this.newMessage = newMessage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
checkNewMessagesThread.start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleNewMessages(int chunkID) {
|
|
||||||
new Thread(() -> {
|
|
||||||
Map<Number640, Data> messages = P2PUtils.get(chatEntity.chatID + "_messages" + chunkID);
|
|
||||||
if (messages != null) {
|
|
||||||
for (Map.Entry<Number640, Data> message : messages.entrySet()) {
|
|
||||||
String json = null;
|
|
||||||
try {
|
|
||||||
json = (String) message.getValue().object();
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
switch (getMessageAction(json)) {
|
|
||||||
case NetworkActions.TEXT_MESSAGE: {
|
|
||||||
TextMessage textMessage = gson.fromJson(json, TextMessage.class);
|
|
||||||
LocalDBWrapper.createMessageEntry(NetworkActions.TEXT_MESSAGE, textMessage.getMessageID(), textMessage.getChatID(), textMessage.getUsername(), textMessage.getSenderID(), textMessage.getTimestamp(), textMessage.getText(), true, false);
|
|
||||||
ObservableUtils.notifyUI(UIActions.MESSAGE_RECEIVED, chatID, textMessage.getMessageID());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NetworkActions.JOIN_CHAT: {
|
|
||||||
JoinChatMessage joinChatMessage = gson.fromJson(json, JoinChatMessage.class);
|
|
||||||
LocalDBWrapper.createMessageEntry(NetworkActions.JOIN_CHAT, joinChatMessage.getMessageID(), joinChatMessage.getChatID(), joinChatMessage.getUsername(), joinChatMessage.getSenderID(), joinChatMessage.getTimestamp(), null, true, false);
|
|
||||||
ObservableUtils.notifyUI(UIActions.MESSAGE_RECEIVED, chatID, joinChatMessage.getMessageID());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NetworkActions.NEXT_CHUNK_REF: {
|
|
||||||
NextChunkReference nextChunkReference = gson.fromJson(json, NextChunkReference.class);
|
|
||||||
chatEntity.chunkCursor = nextChunkReference.getNextChunkID();
|
|
||||||
LocalDBWrapper.updateChatEntity(chatEntity);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(messages.size() > 10) {
|
|
||||||
String messageID = UUID.randomUUID().toString();
|
|
||||||
try {
|
|
||||||
int nextChunkCursor = chatEntity.chunkCursor + 1;
|
|
||||||
P2PUtils.put(chatEntity.chatID + "_messages" + chunkID, messageID, new Data(gson.toJson(new NextChunkReference(messageID, AppHelper.getPeerID(), AppHelper.getPeerID(), System.currentTimeMillis(), nextChunkCursor))));
|
|
||||||
P2PUtils.put(chatEntity.chatID + "_newMessage", null, new Data(messageID));
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getMessageAction(String json) {
|
|
||||||
JsonObject jsonObject = new JsonParser().parse(json).getAsJsonObject();
|
|
||||||
return jsonObject.get("action").getAsInt();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopTrackingForNewMsgs() {
|
|
||||||
timer.cancel();
|
|
||||||
timer.purge();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,83 +1,23 @@
|
|||||||
package io.github.chronosx88.influence.logic;
|
package io.github.chronosx88.influence.logic;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
|
|
||||||
import net.tomp2p.connection.Bindings;
|
|
||||||
import net.tomp2p.connection.ChannelClientConfiguration;
|
|
||||||
import net.tomp2p.connection.ChannelServerConfiguration;
|
|
||||||
import net.tomp2p.connection.Ports;
|
|
||||||
import net.tomp2p.connection.RSASignatureFactory;
|
|
||||||
import net.tomp2p.dht.PeerBuilderDHT;
|
|
||||||
import net.tomp2p.dht.PeerDHT;
|
|
||||||
import net.tomp2p.dht.Storage;
|
|
||||||
import net.tomp2p.futures.FutureBootstrap;
|
|
||||||
import net.tomp2p.futures.FutureDiscover;
|
|
||||||
import net.tomp2p.nat.FutureRelayNAT;
|
|
||||||
import net.tomp2p.nat.PeerBuilderNAT;
|
|
||||||
import net.tomp2p.nat.PeerNAT;
|
|
||||||
import net.tomp2p.p2p.PeerBuilder;
|
|
||||||
import net.tomp2p.peers.Number160;
|
|
||||||
import net.tomp2p.peers.Number640;
|
|
||||||
import net.tomp2p.peers.PeerAddress;
|
|
||||||
import net.tomp2p.relay.tcp.TCPRelayClientConfig;
|
|
||||||
import net.tomp2p.replication.IndirectReplication;
|
|
||||||
import net.tomp2p.storage.Data;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.Inet4Address;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.security.KeyPair;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.CoreContracts;
|
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.NetworkHandler;
|
|
||||||
import io.github.chronosx88.influence.helpers.ObservableUtils;
|
|
||||||
import io.github.chronosx88.influence.helpers.StorageBerkeleyDB;
|
|
||||||
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 MainLogic implements CoreContracts.IMainLogicContract {
|
public class MainLogic implements CoreContracts.IMainLogicContract {
|
||||||
private static final String LOG_TAG = MainLogic.class.getName();
|
private static final String LOG_TAG = MainLogic.class.getName();
|
||||||
|
|
||||||
private SharedPreferences preferences;
|
|
||||||
private Number160 peerID;
|
|
||||||
private PeerDHT peerDHT;
|
|
||||||
private Context context;
|
private Context context;
|
||||||
private InetAddress bootstrapAddress = null;
|
|
||||||
private PeerAddress bootstrapPeerAddress = null;
|
|
||||||
private Gson gson;
|
|
||||||
private IndirectReplication replication;
|
|
||||||
private KeyPairManager keyPairManager;
|
|
||||||
private Thread checkNewChatsThread = null;
|
|
||||||
private Storage storage;
|
|
||||||
|
|
||||||
public MainLogic() {
|
public MainLogic() {
|
||||||
this.context = AppHelper.getContext();
|
this.context = AppHelper.getContext();
|
||||||
this.preferences = context.getSharedPreferences("io.github.chronosx88.influence_preferences", context.MODE_PRIVATE);
|
|
||||||
gson = new Gson();
|
|
||||||
keyPairManager = new KeyPairManager();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/*@Override
|
||||||
public void initPeer() {
|
public void initPeer() {
|
||||||
org.apache.log4j.BasicConfigurator.configure();
|
org.apache.log4j.BasicConfigurator.configure();
|
||||||
|
|
||||||
@ -366,5 +306,5 @@ public class MainLogic implements CoreContracts.IMainLogicContract {
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,18 @@
|
|||||||
package io.github.chronosx88.influence.logic
|
package io.github.chronosx88.influence.logic
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import io.github.chronosx88.influence.contracts.CoreContracts
|
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.KeyPairManager
|
||||||
import io.github.chronosx88.influence.helpers.ObservableUtils
|
|
||||||
import io.github.chronosx88.influence.helpers.actions.UIActions
|
|
||||||
import net.tomp2p.peers.Number640
|
|
||||||
import net.tomp2p.storage.Data
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
class SettingsLogic : CoreContracts.ISettingsLogic {
|
class SettingsLogic : CoreContracts.ISettingsLogic {
|
||||||
|
|
||||||
override fun checkUsernameExists(username: String) : Boolean {
|
override fun checkUsernameExists(username: String) : Boolean {
|
||||||
if (AppHelper.getPeerDHT() == null) {
|
/*if (AppHelper.getPeerDHT() == null) {
|
||||||
ObservableUtils.notifyUI(UIActions.NODE_IS_OFFLINE)
|
ObservableUtils.notifyUI(UIActions.NODE_IS_OFFLINE)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
val usernameMap: MutableMap<Number640, Data>? = P2PUtils.get(username)
|
val usernameMap: MutableMap<Number640, Data>? = P2PUtils.get(username)
|
||||||
usernameMap ?: return false
|
usernameMap ?: return false
|
||||||
|
return true*/
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,7 +20,7 @@ class SettingsLogic : CoreContracts.ISettingsLogic {
|
|||||||
private val LOG_TAG: String = "SettingsLogic"
|
private val LOG_TAG: String = "SettingsLogic"
|
||||||
private val keyPairManager = KeyPairManager()
|
private val keyPairManager = KeyPairManager()
|
||||||
|
|
||||||
fun publishUsername(oldUsername: String?, username: String?) {
|
/*fun publishUsername(oldUsername: String?, username: String?) {
|
||||||
if (AppHelper.getPeerDHT() == null) {
|
if (AppHelper.getPeerDHT() == null) {
|
||||||
ObservableUtils.notifyUI(UIActions.NODE_IS_OFFLINE)
|
ObservableUtils.notifyUI(UIActions.NODE_IS_OFFLINE)
|
||||||
return
|
return
|
||||||
@ -53,6 +47,6 @@ class SettingsLogic : CoreContracts.ISettingsLogic {
|
|||||||
} ?: run {
|
} ?: run {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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.models;
|
||||||
|
|
||||||
|
import com.stfalcon.chatkit.commons.models.IDialog;
|
||||||
|
import com.stfalcon.chatkit.commons.models.IMessage;
|
||||||
|
import com.stfalcon.chatkit.commons.models.IUser;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
||||||
|
|
||||||
|
public class GenericDialog implements IDialog {
|
||||||
|
private String dialogID;
|
||||||
|
private String dialogPhoto = "";
|
||||||
|
private String dialogName;
|
||||||
|
private List<GenericUser> users;
|
||||||
|
private IMessage lastMessage;
|
||||||
|
private int unreadMessagesCount;
|
||||||
|
|
||||||
|
public GenericDialog(ChatEntity chatEntity) {
|
||||||
|
dialogID = chatEntity.jid;
|
||||||
|
dialogName = chatEntity.chatName;
|
||||||
|
users = new ArrayList<>();
|
||||||
|
unreadMessagesCount = chatEntity.unreadMessagesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return dialogID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDialogPhoto() {
|
||||||
|
return dialogPhoto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDialogName() {
|
||||||
|
return dialogName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends IUser> getUsers() {
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IMessage getLastMessage() {
|
||||||
|
return lastMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLastMessage(IMessage message) {
|
||||||
|
lastMessage = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getUnreadCount() {
|
||||||
|
return unreadMessagesCount;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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.models;
|
||||||
|
|
||||||
|
import com.stfalcon.chatkit.commons.models.IMessage;
|
||||||
|
import com.stfalcon.chatkit.commons.models.IUser;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import io.github.chronosx88.influence.models.roomEntities.MessageEntity;
|
||||||
|
|
||||||
|
public class GenericMessage implements IMessage {
|
||||||
|
private long messageID;
|
||||||
|
private IUser author;
|
||||||
|
private long timestamp;
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
public GenericMessage(MessageEntity messageEntity) {
|
||||||
|
this.messageID = messageEntity.messageID;
|
||||||
|
this.author = new GenericUser(messageEntity.senderJid, messageEntity.senderJid, "");
|
||||||
|
this.timestamp = messageEntity.timestamp;
|
||||||
|
this.text = messageEntity.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return String.valueOf(messageID);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IUser getUser() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getCreatedAt() {
|
||||||
|
return new Date(timestamp);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.models;
|
||||||
|
|
||||||
|
import com.stfalcon.chatkit.commons.models.IUser;
|
||||||
|
|
||||||
|
public class GenericUser implements IUser {
|
||||||
|
private String jid;
|
||||||
|
private String name;
|
||||||
|
private String avatar;
|
||||||
|
|
||||||
|
public GenericUser(String jid, String name, String avatar) {
|
||||||
|
this.jid = jid;
|
||||||
|
this.name = name;
|
||||||
|
this.avatar = avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return jid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAvatar() {
|
||||||
|
return avatar;
|
||||||
|
}
|
||||||
|
}
|
@ -5,13 +5,25 @@ import androidx.room.ColumnInfo;
|
|||||||
import androidx.room.Entity;
|
import androidx.room.Entity;
|
||||||
import androidx.room.PrimaryKey;
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import io.github.chronosx88.influence.models.GenericUser;
|
||||||
|
|
||||||
@Entity(tableName = "chats")
|
@Entity(tableName = "chats")
|
||||||
public class ChatEntity {
|
public class ChatEntity {
|
||||||
@PrimaryKey @NonNull public String jid;
|
@PrimaryKey @NonNull public String jid;
|
||||||
@ColumnInfo public String chatName;
|
@ColumnInfo public String chatName;
|
||||||
|
@ColumnInfo public ArrayList<GenericUser> users;
|
||||||
|
@ColumnInfo public int unreadMessagesCount;
|
||||||
|
|
||||||
public ChatEntity(@NonNull String jid, String chatName) {
|
public ChatEntity(@NonNull String jid, String chatName, ArrayList<GenericUser> users, int unreadMessagesCount) {
|
||||||
this.jid = jid;
|
this.jid = jid;
|
||||||
this.chatName = chatName;
|
this.chatName = chatName;
|
||||||
|
this.users = users;
|
||||||
|
this.unreadMessagesCount = unreadMessagesCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPrivateChat() {
|
||||||
|
return users.size() == 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,21 @@
|
|||||||
package io.github.chronosx88.influence.observable;
|
package io.github.chronosx88.influence.observable;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.observer.INetworkObserver;
|
|
||||||
import io.github.chronosx88.influence.contracts.observer.IObservable;
|
import io.github.chronosx88.influence.contracts.observer.IObservable;
|
||||||
import io.github.chronosx88.influence.contracts.observer.IObserver;
|
import io.github.chronosx88.influence.contracts.observer.IObserver;
|
||||||
|
|
||||||
public class MainObservable implements IObservable {
|
public class MainObservable implements IObservable {
|
||||||
public static final int UI_ACTIONS_CHANNEL = 0;
|
private ArrayList<IObserver> uiObservers = new ArrayList<>();
|
||||||
public static final int OTHER_ACTIONS_CHANNEL = 1;
|
|
||||||
|
|
||||||
private ArrayList<IObserver> uiObservers;
|
|
||||||
private ArrayList<INetworkObserver> networkObservers;
|
|
||||||
|
|
||||||
public MainObservable() {
|
|
||||||
this.uiObservers = new ArrayList<>();
|
|
||||||
this.networkObservers = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register(IObserver observer) {
|
public void register(IObserver observer) {
|
||||||
uiObservers.add(observer);
|
uiObservers.add(observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void register(INetworkObserver observer) {
|
|
||||||
networkObservers.add(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregister(IObserver observer) {
|
public void unregister(IObserver observer) {
|
||||||
@ -36,21 +23,13 @@ public class MainObservable implements IObservable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregister(INetworkObserver observer) {
|
public void notifyUIObservers(JSONObject jsonObject) {
|
||||||
networkObservers.remove(observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void notifyUIObservers(JsonObject jsonObject) {
|
|
||||||
for (IObserver observer : uiObservers) {
|
for (IObserver observer : uiObservers) {
|
||||||
observer.handleEvent(jsonObject);
|
try {
|
||||||
}
|
observer.handleEvent(jsonObject);
|
||||||
}
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace();
|
||||||
@Override
|
}
|
||||||
public void notifyNetworkObservers(Object object) {
|
|
||||||
for (INetworkObserver observer : networkObservers) {
|
|
||||||
observer.handleEvent(object);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
package io.github.chronosx88.influence.presenters;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
|
|
||||||
import io.github.chronosx88.influence.contracts.CoreContracts;
|
|
||||||
import io.github.chronosx88.influence.helpers.AppHelper;
|
|
||||||
import io.github.chronosx88.influence.helpers.ChatListAdapter;
|
|
||||||
import io.github.chronosx88.influence.helpers.LocalDBWrapper;
|
|
||||||
import io.github.chronosx88.influence.logic.ChatListLogic;
|
|
||||||
import io.github.chronosx88.influence.models.roomEntities.ChatEntity;
|
|
||||||
import io.github.chronosx88.influence.views.ChatActivity;
|
|
||||||
|
|
||||||
public class ChatListPresenter implements CoreContracts.IChatListPresenterContract {
|
|
||||||
private CoreContracts.IChatListViewContract view;
|
|
||||||
private CoreContracts.IChatListLogicContract logic;
|
|
||||||
private ChatListAdapter chatListAdapter;
|
|
||||||
|
|
||||||
public ChatListPresenter(CoreContracts.IChatListViewContract view) {
|
|
||||||
this.view = view;
|
|
||||||
chatListAdapter = new ChatListAdapter((v, p)-> {
|
|
||||||
openChat(chatListAdapter.getChatEntity(p).chatID);
|
|
||||||
});
|
|
||||||
this.logic = new ChatListLogic();
|
|
||||||
this.view.setRecycleAdapter(chatListAdapter);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateChatList() {
|
|
||||||
view.updateChatList(chatListAdapter, logic.loadAllChats());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void openChat(String chatID) {
|
|
||||||
Intent intent = new Intent(AppHelper.getContext(), ChatActivity.class);
|
|
||||||
intent.putExtra("chatID", chatID);
|
|
||||||
intent.putExtra("contactUsername", LocalDBWrapper.getChatByChatID(chatID).name);
|
|
||||||
view.startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onContextItemSelected(MenuItem item) {
|
|
||||||
switch(item.getItemId()) {
|
|
||||||
case 0: {
|
|
||||||
if(chatListAdapter.onClickPosition != -1) {
|
|
||||||
new Thread(() -> {
|
|
||||||
ChatEntity chat = chatListAdapter.getItem(chatListAdapter.onClickPosition);
|
|
||||||
AppHelper.getChatDB().chatDao().deleteChat(chat.chatID);
|
|
||||||
AppHelper.getChatDB().messageDao().deleteMessagesByChatID(chat.chatID);
|
|
||||||
view.updateChatList(chatListAdapter, logic.loadAllChats());
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,70 +1,76 @@
|
|||||||
package io.github.chronosx88.influence.presenters
|
package io.github.chronosx88.influence.presenters
|
||||||
|
|
||||||
import android.widget.Toast
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.JsonObject
|
import com.stfalcon.chatkit.commons.ImageLoader
|
||||||
import com.instacart.library.truetime.TrueTime
|
import com.stfalcon.chatkit.messages.MessagesListAdapter
|
||||||
|
import io.github.chronosx88.influence.R
|
||||||
import java.io.IOException
|
import io.github.chronosx88.influence.XMPPConnectionService
|
||||||
import java.util.ArrayList
|
|
||||||
import java.util.UUID
|
|
||||||
|
|
||||||
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.LocalDBWrapper
|
import io.github.chronosx88.influence.helpers.LocalDBWrapper
|
||||||
import io.github.chronosx88.influence.helpers.actions.NetworkActions
|
|
||||||
import io.github.chronosx88.influence.helpers.actions.UIActions
|
|
||||||
import io.github.chronosx88.influence.logic.ChatLogic
|
import io.github.chronosx88.influence.logic.ChatLogic
|
||||||
|
import io.github.chronosx88.influence.models.GenericDialog
|
||||||
|
import io.github.chronosx88.influence.models.GenericMessage
|
||||||
import io.github.chronosx88.influence.models.roomEntities.ChatEntity
|
import io.github.chronosx88.influence.models.roomEntities.ChatEntity
|
||||||
import org.jetbrains.anko.doAsync
|
import io.github.chronosx88.influence.models.roomEntities.MessageEntity
|
||||||
import org.jetbrains.anko.doAsyncResult
|
|
||||||
|
|
||||||
class ChatPresenter(private val view: CoreContracts.IChatViewContract, private val chatID: String) : CoreContracts.IChatPresenterContract, IObserver {
|
class ChatPresenter(private val view: CoreContracts.IChatViewContract, private val chatID: String) : CoreContracts.IChatPresenterContract {
|
||||||
private val logic: CoreContracts.IChatLogicContract
|
private val logic: CoreContracts.IChatLogicContract
|
||||||
private val chatEntity: ChatEntity?
|
private val chatEntity: ChatEntity?
|
||||||
private val gson: Gson
|
private val gson: Gson
|
||||||
|
private val chatAdapter: MessagesListAdapter<GenericMessage>
|
||||||
|
private val newMessageReceiver: BroadcastReceiver
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.logic = ChatLogic(LocalDBWrapper.getChatByChatID(chatID)!!)
|
this.logic = ChatLogic(LocalDBWrapper.getChatByChatID(chatID)!!)
|
||||||
this.chatEntity = LocalDBWrapper.getChatByChatID(chatID)
|
this.chatEntity = LocalDBWrapper.getChatByChatID(chatID)
|
||||||
|
|
||||||
AppHelper.getObservable().register(this)
|
|
||||||
gson = Gson()
|
gson = Gson()
|
||||||
}
|
chatAdapter = MessagesListAdapter(AppHelper.getJid(), ImageLoader { imageView, _, _ -> imageView.setImageResource(R.mipmap.ic_launcher) })
|
||||||
|
view.setAdapter(chatAdapter)
|
||||||
|
|
||||||
override fun sendMessage(text: String) {
|
newMessageReceiver = object : BroadcastReceiver() {
|
||||||
doAsync {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
val message = LocalDBWrapper.createMessageEntry(NetworkActions.TEXT_MESSAGE, UUID.randomUUID().toString(), chatID, AppHelper.getPeerID(), AppHelper.getPeerID(), TrueTime.now().time, text, false, false)
|
if(intent.getStringExtra(XMPPConnectionService.MESSAGE_CHATID).equals(chatEntity.jid)) {
|
||||||
logic.sendMessage(message!!)
|
val messageID = intent.getLongExtra(XMPPConnectionService.MESSAGE_ID, -1)
|
||||||
view.updateMessageList(message)
|
chatAdapter.addToStart(GenericMessage(LocalDBWrapper.getMessageByID(messageID)), true)
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleEvent(obj: JsonObject) {
|
|
||||||
when (obj.get("action").asInt) {
|
|
||||||
UIActions.MESSAGE_RECEIVED -> {
|
|
||||||
val jsonArray = obj.getAsJsonArray("additional")
|
|
||||||
if (jsonArray.get(0).asString != chatID) {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
val messageEntity = LocalDBWrapper.getMessageByID(jsonArray.get(1).asString)
|
|
||||||
view.updateMessageList(messageEntity!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
UIActions.NODE_IS_OFFLINE -> {
|
|
||||||
Toast.makeText(AppHelper.getContext(), "Нода не запущена!", Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val filter = IntentFilter()
|
||||||
|
filter.addAction(XMPPConnectionService.INTENT_NEW_MESSAGE)
|
||||||
|
AppHelper.getContext().registerReceiver(newMessageReceiver, filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun updateAdapter() {
|
override fun sendMessage(text: String): Boolean {
|
||||||
val entities = LocalDBWrapper.getMessagesByChatID(chatID)
|
val message: MessageEntity? = logic.sendMessage(text)
|
||||||
view.updateMessageList(entities ?: ArrayList())
|
if(message != null) {
|
||||||
|
chatAdapter.addToStart(GenericMessage(message), true)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun loadLocalMessages() {
|
||||||
|
val entities: List<MessageEntity>? = LocalDBWrapper.getMessagesByChatID(chatID)
|
||||||
|
val messages = ArrayList<GenericMessage>()
|
||||||
|
if(entities != null) {
|
||||||
|
entities.forEach {
|
||||||
|
messages.add(GenericMessage(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chatAdapter.addToEnd(messages, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
logic.stopTrackingForNewMsgs()
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupIncomingMessagesReceiver() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,96 @@
|
|||||||
|
package io.github.chronosx88.influence.presenters;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
|
||||||
|
import com.stfalcon.chatkit.dialogs.DialogsListAdapter;
|
||||||
|
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import io.github.chronosx88.influence.R;
|
||||||
|
import io.github.chronosx88.influence.XMPPConnectionService;
|
||||||
|
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.LocalDBWrapper;
|
||||||
|
import io.github.chronosx88.influence.helpers.ObservableActions;
|
||||||
|
import io.github.chronosx88.influence.logic.ChatListLogic;
|
||||||
|
import io.github.chronosx88.influence.models.GenericDialog;
|
||||||
|
import io.github.chronosx88.influence.views.ChatActivity;
|
||||||
|
import java8.util.stream.StreamSupport;
|
||||||
|
|
||||||
|
public class DialogListPresenter implements CoreContracts.IDialogListPresenterContract, IObserver {
|
||||||
|
private CoreContracts.IChatListViewContract view;
|
||||||
|
private CoreContracts.IDialogListLogicContract logic;
|
||||||
|
private DialogsListAdapter<GenericDialog> dialogListAdapter = new DialogsListAdapter<>((imageView, url, payload) -> {
|
||||||
|
imageView.setImageResource(R.mipmap.ic_launcher); // FIXME
|
||||||
|
});
|
||||||
|
private BroadcastReceiver incomingMessagesReceiver;
|
||||||
|
|
||||||
|
public DialogListPresenter(CoreContracts.IChatListViewContract view) {
|
||||||
|
this.view = view;
|
||||||
|
dialogListAdapter.setOnDialogClickListener(dialog -> openChat(dialog.getId()));
|
||||||
|
dialogListAdapter.setOnDialogLongClickListener(dialog -> {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(view.getActivityContext());
|
||||||
|
builder.setPositiveButton(R.string.ok, (dialog1, id) -> {
|
||||||
|
dialogListAdapter.deleteById(dialog.getId());
|
||||||
|
AppHelper.getChatDB().chatDao().deleteChat(dialog.getId());
|
||||||
|
AppHelper.getChatDB().messageDao().deleteMessagesByChatID(dialog.getId());
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(R.string.cancel, (dialog2, which) -> {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
builder.setMessage("Remove chat?");
|
||||||
|
builder.create().show();
|
||||||
|
});
|
||||||
|
this.logic = new ChatListLogic();
|
||||||
|
this.view.setDialogAdapter(dialogListAdapter);
|
||||||
|
ArrayList<GenericDialog> dialogs = new ArrayList<>();
|
||||||
|
StreamSupport.stream(logic.loadAllChats())
|
||||||
|
.forEach(chatEntity -> dialogs.add(new GenericDialog(chatEntity)));
|
||||||
|
dialogListAdapter.setItems(dialogs);
|
||||||
|
setupIncomingMessagesReceiver();
|
||||||
|
AppHelper.getObservable().register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void openChat(String chatID) {
|
||||||
|
Intent intent = new Intent(AppHelper.getContext(), ChatActivity.class);
|
||||||
|
intent.putExtra("chatID", chatID);
|
||||||
|
intent.putExtra("chatName", LocalDBWrapper.getChatByChatID(chatID).chatName);
|
||||||
|
view.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupIncomingMessagesReceiver() {
|
||||||
|
incomingMessagesReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
String chatID = intent.getStringExtra(XMPPConnectionService.MESSAGE_CHATID);
|
||||||
|
GenericDialog dialog = dialogListAdapter.getItemById(chatID);
|
||||||
|
if(dialog == null) {
|
||||||
|
dialogListAdapter.addItem(new GenericDialog(LocalDBWrapper.getChatByChatID(chatID)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
IntentFilter filter = new IntentFilter();
|
||||||
|
filter.addAction(XMPPConnectionService.INTENT_NEW_MESSAGE);
|
||||||
|
AppHelper.getContext().registerReceiver(incomingMessagesReceiver, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleEvent(JSONObject object) throws JSONException {
|
||||||
|
switch (object.getInt("action")) {
|
||||||
|
case ObservableActions.NEW_CHAT_CREATED: {
|
||||||
|
dialogListAdapter.addItem(new GenericDialog(LocalDBWrapper.getChatByChatID(object.getJSONArray("additional").optString(0))));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,56 +1,68 @@
|
|||||||
package io.github.chronosx88.influence.presenters
|
package io.github.chronosx88.influence.presenters
|
||||||
|
|
||||||
import com.google.gson.JsonObject
|
import android.app.ActivityManager
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
import io.github.chronosx88.influence.R
|
import io.github.chronosx88.influence.R
|
||||||
|
import io.github.chronosx88.influence.XMPPConnectionService
|
||||||
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.helpers.LocalDBWrapper
|
||||||
|
import io.github.chronosx88.influence.helpers.ObservableActions
|
||||||
|
import io.github.chronosx88.influence.helpers.ObservableUtils
|
||||||
import io.github.chronosx88.influence.logic.MainLogic
|
import io.github.chronosx88.influence.logic.MainLogic
|
||||||
|
import io.github.chronosx88.influence.views.LoginActivity
|
||||||
import org.jetbrains.anko.doAsync
|
import org.jetbrains.anko.doAsync
|
||||||
|
|
||||||
class MainPresenter(private val view: CoreContracts.IMainViewContract) : CoreContracts.IMainPresenterContract, IObserver {
|
class MainPresenter(private val view: CoreContracts.IMainViewContract) : CoreContracts.IMainPresenterContract {
|
||||||
private val logic: CoreContracts.IMainLogicContract = MainLogic()
|
private val logic: CoreContracts.IMainLogicContract = MainLogic()
|
||||||
|
private var broadcastReceiver: BroadcastReceiver? = null
|
||||||
|
|
||||||
init {
|
|
||||||
AppHelper.getObservable().register(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun initPeer() {
|
override fun initPeer() {
|
||||||
if (AppHelper.getPeerDHT() == null) {
|
broadcastReceiver = object : BroadcastReceiver() {
|
||||||
logic.initPeer()
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
} else {
|
val action = intent.action
|
||||||
view.showSnackbar(AppHelper.getContext().getString(R.string.node_already_running))
|
when (action) {
|
||||||
view.showProgressBar(false)
|
XMPPConnectionService.INTENT_AUTHENTICATED -> {
|
||||||
|
view.showProgressBar(false)
|
||||||
|
}
|
||||||
|
XMPPConnectionService.INTENT_AUTHENTICATION_FAILED -> {
|
||||||
|
view.showProgressBar(false)
|
||||||
|
val intent = Intent(AppHelper.getContext(), LoginActivity::class.java)
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
|
AppHelper.getContext().startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
val filter = IntentFilter()
|
||||||
|
filter.addAction(XMPPConnectionService.INTENT_AUTHENTICATED)
|
||||||
|
filter.addAction(XMPPConnectionService.INTENT_AUTHENTICATION_FAILED)
|
||||||
|
AppHelper.getContext().registerReceiver(broadcastReceiver, filter)
|
||||||
|
|
||||||
|
AppHelper.getContext().startService(Intent(AppHelper.getContext(), XMPPConnectionService::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startChatWithPeer(username: String) {
|
override fun startChatWithPeer(username: String) {
|
||||||
doAsync {
|
LocalDBWrapper.createChatEntry(username, username)
|
||||||
logic.sendStartChatMessage(username)
|
ObservableUtils.notifyUI(ObservableActions.NEW_CHAT_CREATED, 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()
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
private fun isServiceRunning(serviceClass: Class<*>): Boolean {
|
||||||
|
val manager = AppHelper.getContext().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
|
||||||
|
for (service in manager.getRunningServices(Integer.MAX_VALUE)) {
|
||||||
|
if (serviceClass.name == service.service.className) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,17 @@
|
|||||||
package io.github.chronosx88.influence.presenters
|
package io.github.chronosx88.influence.presenters
|
||||||
|
|
||||||
import android.content.SharedPreferences
|
|
||||||
import android.os.Handler
|
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.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.ObservableUtils
|
|
||||||
import io.github.chronosx88.influence.helpers.actions.UIActions
|
|
||||||
import io.github.chronosx88.influence.logic.SettingsLogic
|
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 {
|
class SettingsPresenter(private val view: CoreContracts.ISettingsView) : CoreContracts.ISettingsPresenter {
|
||||||
private val mainThreadHandler: Handler = Handler(AppHelper.getContext().mainLooper)
|
private val mainThreadHandler: Handler = Handler(AppHelper.getContext().mainLooper)
|
||||||
private val logic: SettingsLogic = SettingsLogic()
|
private val logic: SettingsLogic = SettingsLogic()
|
||||||
|
|
||||||
init {
|
|
||||||
AppHelper.getObservable().register(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateUsername(username: String) {
|
override fun updateUsername(username: String) {
|
||||||
view.loadingScreen(true)
|
/*view.loadingScreen(true)
|
||||||
val editor: SharedPreferences.Editor = AppHelper.getPreferences().edit()
|
val editor: SharedPreferences.Editor = AppHelper.getPreferences().edit()
|
||||||
|
|
||||||
GlobalScope.launch {
|
GlobalScope.launch {
|
||||||
@ -52,23 +41,6 @@ class SettingsPresenter(private val view: CoreContracts.ISettingsView) : CoreCon
|
|||||||
} else {
|
} else {
|
||||||
ObservableUtils.notifyUI(UIActions.USERNAME_ISNT_AVAILABLE)
|
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))
|
|
||||||
view.refreshScreen()
|
|
||||||
}
|
|
||||||
UIActions.USERNAME_ISNT_AVAILABLE -> {
|
|
||||||
view.loadingScreen(false)
|
|
||||||
view.showMessage(AppHelper.getContext().getString(R.string.username_isnt_saved))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mainThreadHandler.post(post)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,25 +2,25 @@ package io.github.chronosx88.influence.views
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.widget.EditText
|
|
||||||
import android.widget.ImageButton
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.appcompat.widget.Toolbar
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import com.stfalcon.chatkit.commons.ImageLoader
|
||||||
|
import com.stfalcon.chatkit.messages.MessageInput
|
||||||
|
import com.stfalcon.chatkit.messages.MessagesList
|
||||||
|
import com.stfalcon.chatkit.messages.MessagesListAdapter
|
||||||
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.helpers.ChatAdapter
|
import io.github.chronosx88.influence.helpers.AppHelper
|
||||||
|
import io.github.chronosx88.influence.models.GenericMessage
|
||||||
import io.github.chronosx88.influence.models.roomEntities.MessageEntity
|
import io.github.chronosx88.influence.models.roomEntities.MessageEntity
|
||||||
import io.github.chronosx88.influence.presenters.ChatPresenter
|
import io.github.chronosx88.influence.presenters.ChatPresenter
|
||||||
|
|
||||||
class ChatActivity : AppCompatActivity(), CoreContracts.IChatViewContract {
|
class ChatActivity : AppCompatActivity(), CoreContracts.IChatViewContract {
|
||||||
private var chatAdapter: ChatAdapter? = null
|
private var messageList: MessagesList? = null
|
||||||
private var messageList: RecyclerView? = null
|
private var messageInput: MessageInput? = null
|
||||||
private var sendMessageButton: ImageButton? = null
|
private var chatNameTextView: TextView? = null
|
||||||
private var messageTextEdit: EditText? = null
|
|
||||||
private var contactUsernameTextView: TextView? = null
|
|
||||||
private var presenter: ChatPresenter? = null
|
private var presenter: ChatPresenter? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -29,45 +29,21 @@ class ChatActivity : AppCompatActivity(), CoreContracts.IChatViewContract {
|
|||||||
|
|
||||||
val intent = intent
|
val intent = intent
|
||||||
|
|
||||||
presenter = ChatPresenter(this, intent.getStringExtra("chatID"))
|
|
||||||
val toolbar = findViewById<Toolbar>(R.id.toolbar_chat_activity)
|
val toolbar = findViewById<Toolbar>(R.id.toolbar_chat_activity)
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
supportActionBar!!.setTitle("")
|
supportActionBar!!.setTitle("")
|
||||||
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar!!.setHomeButtonEnabled(true)
|
supportActionBar!!.setHomeButtonEnabled(true)
|
||||||
messageList = findViewById(R.id.message_list)
|
messageList = findViewById(R.id.messages_list)
|
||||||
chatAdapter = ChatAdapter()
|
|
||||||
presenter!!.updateAdapter()
|
|
||||||
messageList!!.adapter = chatAdapter
|
|
||||||
messageList!!.layoutManager = LinearLayoutManager(this)
|
messageList!!.layoutManager = LinearLayoutManager(this)
|
||||||
contactUsernameTextView = findViewById(R.id.appbar_username)
|
chatNameTextView = findViewById(R.id.appbar_username)
|
||||||
messageTextEdit = findViewById(R.id.message_input)
|
messageInput = findViewById(R.id.message_input)
|
||||||
sendMessageButton = findViewById(R.id.send_button)
|
messageInput!!.setInputListener {
|
||||||
sendMessageButton!!.setOnClickListener sendMessageButton@{
|
presenter!!.sendMessage(it.toString())
|
||||||
if (messageTextEdit!!.text.toString() == "") {
|
|
||||||
return@sendMessageButton
|
|
||||||
}
|
|
||||||
presenter!!.sendMessage(messageTextEdit!!.text.toString())
|
|
||||||
messageTextEdit!!.setText("")
|
|
||||||
}
|
|
||||||
contactUsernameTextView!!.text = intent.getStringExtra("contactUsername")
|
|
||||||
messageList!!.scrollToPosition(chatAdapter!!.itemCount - 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateMessageList(message: MessageEntity) {
|
|
||||||
runOnUiThread {
|
|
||||||
chatAdapter!!.addMessage(message)
|
|
||||||
messageList!!.scrollToPosition(chatAdapter!!.itemCount - 1)
|
|
||||||
chatAdapter!!.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun updateMessageList(messages: List<MessageEntity>) {
|
|
||||||
runOnUiThread {
|
|
||||||
chatAdapter!!.addMessages(messages)
|
|
||||||
messageList!!.scrollToPosition(chatAdapter!!.itemCount - 1)
|
|
||||||
chatAdapter!!.notifyDataSetChanged()
|
|
||||||
}
|
}
|
||||||
|
chatNameTextView!!.text = intent.getStringExtra("chatName")
|
||||||
|
presenter = ChatPresenter(this, intent.getStringExtra("chatID"))
|
||||||
|
presenter!!.loadLocalMessages()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
@ -84,4 +60,8 @@ class ChatActivity : AppCompatActivity(), CoreContracts.IChatViewContract {
|
|||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
presenter!!.onDestroy()
|
presenter!!.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun setAdapter(adapter: MessagesListAdapter<GenericMessage>) {
|
||||||
|
messageList!!.setAdapter(adapter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ import android.text.TextUtils;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
|
||||||
@ -51,6 +50,8 @@ public class LoginActivity extends AppCompatActivity implements CoreContracts.IL
|
|||||||
passwordEditText = findViewById(R.id.login_password);
|
passwordEditText = findViewById(R.id.login_password);
|
||||||
signInButton = findViewById(R.id.sign_in_button);
|
signInButton = findViewById(R.id.sign_in_button);
|
||||||
progressDialog = new ProgressDialog(LoginActivity.this);
|
progressDialog = new ProgressDialog(LoginActivity.this);
|
||||||
|
progressDialog.setCancelable(false);
|
||||||
|
progressDialog.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
|
||||||
signInButton.setOnClickListener((v) -> {
|
signInButton.setOnClickListener((v) -> {
|
||||||
if(checkLoginCredentials()) {
|
if(checkLoginCredentials()) {
|
||||||
saveLoginCredentials();
|
saveLoginCredentials();
|
||||||
@ -82,7 +83,7 @@ public class LoginActivity extends AppCompatActivity implements CoreContracts.IL
|
|||||||
}
|
}
|
||||||
case XMPPConnectionService.INTENT_AUTHENTICATION_FAILED: {
|
case XMPPConnectionService.INTENT_AUTHENTICATION_FAILED: {
|
||||||
loadingScreen(false);
|
loadingScreen(false);
|
||||||
passwordEditText.setError("Invalid JID/Password");
|
jidEditText.setError("Invalid JID/Password/Server");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,59 +7,51 @@ 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.EditText;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
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;
|
||||||
|
|
||||||
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.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.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.ObservableActions;
|
||||||
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.DialogListFragment;
|
||||||
import io.github.chronosx88.influence.views.fragments.SettingsFragment;
|
import io.github.chronosx88.influence.views.fragments.SettingsFragment;
|
||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity implements CoreContracts.IMainViewContract {
|
public class MainActivity extends AppCompatActivity implements CoreContracts.IMainViewContract, IObserver {
|
||||||
|
|
||||||
private CoreContracts.IMainPresenterContract presenter;
|
private CoreContracts.IMainPresenterContract presenter;
|
||||||
private ProgressDialog progressDialog;
|
private ProgressDialog progressDialog;
|
||||||
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener
|
private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = (item) -> {
|
||||||
= new BottomNavigationView.OnNavigationItemSelectedListener() {
|
Fragment selectedFragment = null;
|
||||||
|
|
||||||
@Override
|
switch (item.getItemId()) {
|
||||||
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
case R.id.action_chats:
|
||||||
|
selectedFragment = new DialogListFragment();
|
||||||
Fragment selectedFragment = null;
|
break;
|
||||||
|
case R.id.action_settings:
|
||||||
switch (item.getItemId()) {
|
selectedFragment = new SettingsFragment();
|
||||||
case R.id.action_chats:
|
break;
|
||||||
selectedFragment = new ChatListFragment();
|
|
||||||
break;
|
|
||||||
case R.id.action_settings:
|
|
||||||
selectedFragment = new SettingsFragment();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
|
||||||
transaction.replace(R.id.main_fragment_container, selectedFragment);
|
|
||||||
transaction.commit();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||||
|
transaction.replace(R.id.main_fragment_container, selectedFragment);
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -73,7 +65,7 @@ public class MainActivity extends AppCompatActivity implements CoreContracts.IMa
|
|||||||
fab.setOnClickListener((v) -> {
|
fab.setOnClickListener((v) -> {
|
||||||
Pair<AlertDialog.Builder, EditText> pair = ViewUtils.INSTANCE.setupEditTextDialog(MainActivity.this, getString(R.string.input_companion_username));
|
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) -> {
|
pair.getFirst().setPositiveButton(getString(R.string.ok), (dialog, which) -> {
|
||||||
progressDialog.show();
|
showProgressBar(true);
|
||||||
presenter.startChatWithPeer(pair.getSecond().getText().toString());
|
presenter.startChatWithPeer(pair.getSecond().getText().toString());
|
||||||
});
|
});
|
||||||
pair.getFirst().setNegativeButton(getString(R.string.cancel), (dialog, which) -> {
|
pair.getFirst().setNegativeButton(getString(R.string.cancel), (dialog, which) -> {
|
||||||
@ -84,17 +76,17 @@ public class MainActivity extends AppCompatActivity implements CoreContracts.IMa
|
|||||||
|
|
||||||
getSupportFragmentManager()
|
getSupportFragmentManager()
|
||||||
.beginTransaction()
|
.beginTransaction()
|
||||||
.replace(R.id.main_fragment_container, new ChatListFragment())
|
.replace(R.id.main_fragment_container, new DialogListFragment())
|
||||||
.commit();
|
.commit();
|
||||||
|
|
||||||
presenter = new MainPresenter(this);
|
presenter = new MainPresenter(this);
|
||||||
|
|
||||||
|
|
||||||
progressDialog = new ProgressDialog(MainActivity.this, R.style.AlertDialogTheme);
|
progressDialog = new ProgressDialog(MainActivity.this, R.style.AlertDialogTheme);
|
||||||
progressDialog.setCancelable(false);
|
progressDialog.setCancelable(false);
|
||||||
progressDialog.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
|
progressDialog.setProgressStyle(android.R.style.Widget_ProgressBar_Small);
|
||||||
progressDialog.show();
|
progressDialog.show();
|
||||||
presenter.initPeer();
|
presenter.initPeer();
|
||||||
|
AppHelper.getObservable().register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -120,10 +112,7 @@ public class MainActivity extends AppCompatActivity implements CoreContracts.IMa
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showSnackbar(@NotNull String message) {
|
public void showSnackbar(@NotNull String message) {
|
||||||
runOnUiThread(() -> {
|
runOnUiThread(() -> Snackbar.make(getRootView(), message, Snackbar.LENGTH_LONG).show());
|
||||||
Snackbar.make(getRootView(), message, Snackbar.LENGTH_LONG)
|
|
||||||
.show();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -149,4 +138,14 @@ public class MainActivity extends AppCompatActivity implements CoreContracts.IMa
|
|||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleEvent(JSONObject object) throws JSONException {
|
||||||
|
switch (object.getInt("action")) {
|
||||||
|
case ObservableActions.NEW_CHAT_CREATED: {
|
||||||
|
showProgressBar(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,76 +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 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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,39 @@
|
|||||||
|
package io.github.chronosx88.influence.views.fragments
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import com.stfalcon.chatkit.dialogs.DialogsList
|
||||||
|
import com.stfalcon.chatkit.dialogs.DialogsListAdapter
|
||||||
|
import io.github.chronosx88.influence.R
|
||||||
|
import io.github.chronosx88.influence.contracts.CoreContracts
|
||||||
|
import io.github.chronosx88.influence.models.GenericDialog
|
||||||
|
import io.github.chronosx88.influence.presenters.DialogListPresenter
|
||||||
|
|
||||||
|
|
||||||
|
class DialogListFragment : Fragment(), CoreContracts.IChatListViewContract {
|
||||||
|
private var presenter: CoreContracts.IDialogListPresenterContract? = null
|
||||||
|
private var dialogList: DialogsList? = null
|
||||||
|
|
||||||
|
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)
|
||||||
|
dialogList = view.findViewById(R.id.dialogsList)
|
||||||
|
presenter = DialogListPresenter(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setDialogAdapter(adapter: DialogsListAdapter<GenericDialog>) {
|
||||||
|
dialogList!!.setAdapter(adapter)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getActivityContext(): Context? {
|
||||||
|
return context
|
||||||
|
}
|
||||||
|
}
|
@ -33,12 +33,12 @@ public class SettingsFragment extends PreferenceFragmentCompat implements CoreCo
|
|||||||
presenter = new SettingsPresenter(this);
|
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());
|
||||||
getPreferenceScreen().getPreference(0).setOnPreferenceClickListener((preference -> {
|
getPreferenceScreen().getPreference(0).setOnPreferenceClickListener((preference -> {
|
||||||
ClipboardManager clipboard = (ClipboardManager) AppHelper.getContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
ClipboardManager clipboard = (ClipboardManager) AppHelper.getActivityContext().getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
ClipData clip = ClipData.newPlainText("", AppHelper.getPeerID());
|
ClipData clip = ClipData.newPlainText("", AppHelper.getPeerID());
|
||||||
clipboard.setPrimaryClip(clip);
|
clipboard.setPrimaryClip(clip);
|
||||||
Toast.makeText(AppHelper.getContext(), "Скопировано в буфер обмена!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(AppHelper.getActivityContext(), "Скопировано в буфер обмена!", Toast.LENGTH_SHORT).show();
|
||||||
return false;
|
return false;
|
||||||
}));
|
}));
|
||||||
getPreferenceScreen().getPreference(1).setSummary(AppHelper.getUsername());
|
getPreferenceScreen().getPreference(1).setSummary(AppHelper.getUsername());
|
||||||
@ -49,7 +49,7 @@ public class SettingsFragment extends PreferenceFragmentCompat implements CoreCo
|
|||||||
getPreferenceScreen().getPreference(1).setOnPreferenceChangeListener((p, nV) -> {
|
getPreferenceScreen().getPreference(1).setOnPreferenceChangeListener((p, nV) -> {
|
||||||
getPreferenceScreen().getPreference(1).setSummary((String) nV);
|
getPreferenceScreen().getPreference(1).setSummary((String) nV);
|
||||||
return true;
|
return true;
|
||||||
});
|
});*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -38,38 +38,26 @@
|
|||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<com.stfalcon.chatkit.messages.MessagesList
|
||||||
android:id="@+id/message_list"
|
android:id="@+id/messages_list"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_below="@id/appbar_chat_activity"
|
android:layout_above="@+id/message_input"/>
|
||||||
android:layout_above="@+id/chat_activity_bottom_container"/>
|
|
||||||
|
|
||||||
<RelativeLayout
|
<View
|
||||||
android:id="@+id/chat_activity_bottom_container"
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_above="@+id/message_input"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:background="@android:color/darker_gray"/>
|
||||||
|
|
||||||
|
<com.stfalcon.chatkit.messages.MessageInput
|
||||||
|
android:id="@+id/message_input"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:background="#FFFFFF"
|
app:inputHint="@string/hint_enter_a_message"
|
||||||
android:orientation="horizontal"
|
app:showAttachmentButton="true"/>
|
||||||
android:padding="5dp">
|
|
||||||
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/message_input"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:layout_toLeftOf="@+id/send_button"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:hint="Type a message..." />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/send_button"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:background="@drawable/ic_send_green_24dp" />
|
|
||||||
</RelativeLayout>
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
@ -3,8 +3,8 @@
|
|||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<com.stfalcon.chatkit.dialogs.DialogsList
|
||||||
android:id="@+id/chatlist_container"
|
android:id="@+id/dialogsList"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"/>
|
android:layout_height="match_parent"/>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
@ -10,4 +10,5 @@
|
|||||||
<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>
|
<string name="input_companion_username">Введите имя пользователя собеседника</string>
|
||||||
|
<string name="hint_enter_a_message">Введите сообщение...</string>
|
||||||
</resources>
|
</resources>
|
@ -9,4 +9,5 @@
|
|||||||
<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>
|
<string name="input_companion_username">Input interlocutor\'s username</string>
|
||||||
|
<string name="hint_enter_a_message">Enter message...</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user