Merge branch 'develop' into b/incorrect_color_change
This commit is contained in:
		| @@ -1,6 +1,7 @@ | |||||||
| package envoy.client; | package envoy.client; | ||||||
|  |  | ||||||
| import java.util.logging.Logger; | import java.util.HashMap; | ||||||
|  | import java.util.Map; | ||||||
|  |  | ||||||
| import javax.ws.rs.client.ClientBuilder; | import javax.ws.rs.client.ClientBuilder; | ||||||
| import javax.ws.rs.client.Entity; | import javax.ws.rs.client.Entity; | ||||||
| @@ -10,6 +11,7 @@ import javax.xml.bind.JAXBContext; | |||||||
| import javax.xml.bind.JAXBException; | import javax.xml.bind.JAXBException; | ||||||
| import javax.xml.bind.Marshaller; | import javax.xml.bind.Marshaller; | ||||||
|  |  | ||||||
|  | import envoy.exception.EnvoyException; | ||||||
| import envoy.schema.ObjectFactory; | import envoy.schema.ObjectFactory; | ||||||
| import envoy.schema.Sync; | import envoy.schema.Sync; | ||||||
| import envoy.schema.User; | import envoy.schema.User; | ||||||
| @@ -29,14 +31,28 @@ public class Client { | |||||||
| 	private ObjectFactory	objectFactory	= new ObjectFactory(); | 	private ObjectFactory	objectFactory	= new ObjectFactory(); | ||||||
| 	private Config			config; | 	private Config			config; | ||||||
| 	private User			sender, recipient; | 	private User			sender, recipient; | ||||||
|  | 	private boolean			online			= false; | ||||||
|  |  | ||||||
| 	private static final Logger logger = Logger.getLogger(Client.class.getSimpleName()); | 	/** | ||||||
|  | 	 * Initializes the client. At this state, the client user has yet to be | ||||||
|  | 	 * initialized, which can be done by calling {@link Client#onlineInit(String). | ||||||
|  | 	 *  | ||||||
|  | 	 * @param config The {@link Config} instance to use in this client | ||||||
|  | 	 * @since Envoy v0.2-alpha | ||||||
|  | 	 */ | ||||||
|  | 	public Client(Config config) { this.config = config; } | ||||||
|  |  | ||||||
| 	public Client(Config config, String username) { | 	/** | ||||||
| 		this.config	= config; | 	 * Enters the online mode by acquiring a user ID from the server. | ||||||
| 		sender		= getUser(username); | 	 *  | ||||||
|  | 	 * @param userName the name of the client user | ||||||
| 		logger.info("ID: " + sender.getID()); | 	 * @throws EnvoyException if the online mode could not be entered or the request | ||||||
|  | 	 *                        failed for some other reason | ||||||
|  | 	 * @since Envoy v0.2-alpha | ||||||
|  | 	 */ | ||||||
|  | 	public void onlineInit(String userName) throws EnvoyException { | ||||||
|  | 		sender	= getUser(userName); | ||||||
|  | 		online	= true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	private <T, R> R post(String uri, T body, Class<R> responseBodyClass) { | 	private <T, R> R post(String uri, T body, Class<R> responseBodyClass) { | ||||||
| @@ -48,28 +64,26 @@ public class Client { | |||||||
| 		client.close(); | 		client.close(); | ||||||
|  |  | ||||||
| 		return responseBody; | 		return responseBody; | ||||||
|  |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Returns a {@link Sync} with all users on the server. | 	 * @return a {@code Map<String, User>} of all users on the server with their | ||||||
| 	 *  | 	 *         user names as keys | ||||||
| 	 * @return Sync - List of all users on the server. | 	 * @since Envoy v0.2-alpha | ||||||
| 	 * @since Envoy v0.1-alpha |  | ||||||
| 	 */ | 	 */ | ||||||
| 	public Sync getUsersListXml() { | 	public Map<String, User> getUsers() { | ||||||
| 		Sync	sendSync	= objectFactory.createSync(); | 		Sync	sendSync	= objectFactory.createSync(); | ||||||
| 		User	user		= objectFactory.createUser(); | 		User	user		= objectFactory.createUser(); | ||||||
| 		user.setID(-1); | 		user.setID(-1); | ||||||
| 		sendSync.getUsers().add(user); | 		sendSync.getUsers().add(user); | ||||||
|  |  | ||||||
| 		Sync returnSendSync = post( | 		Sync returnSync = post(String.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), 0), | ||||||
| 				String |  | ||||||
| 					.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), 0), |  | ||||||
| 				sendSync, | 				sendSync, | ||||||
| 				Sync.class); | 				Sync.class); | ||||||
| 		return returnSendSync; |  | ||||||
|  |  | ||||||
|  | 		Map<String, User> users = new HashMap<>(); | ||||||
|  | 		returnSync.getUsers().forEach(u -> users.put(u.getName(), u)); | ||||||
|  | 		return users; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -77,29 +91,29 @@ public class Client { | |||||||
| 	 *  | 	 *  | ||||||
| 	 * @param name - the name of the {@link User} | 	 * @param name - the name of the {@link User} | ||||||
| 	 * @return a {@link User} with the specified name | 	 * @return a {@link User} with the specified name | ||||||
|  | 	 * @throws EnvoyException if the server does not return the requested ID | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	private User getUser(String name) { | 	private User getUser(String name) throws EnvoyException { | ||||||
|  | 		// Create a sync with only a user with the requested name | ||||||
| 		Sync	senderSync	= objectFactory.createSync(); | 		Sync	senderSync	= objectFactory.createSync(); | ||||||
| 		User	user		= objectFactory.createUser(); | 		User	user		= objectFactory.createUser(); | ||||||
| 		user.setName(name); | 		user.setName(name); | ||||||
| 		senderSync.getUsers().add(user); | 		senderSync.getUsers().add(user); | ||||||
|  |  | ||||||
| 		Sync returnSenderSync = post( | 		try { | ||||||
| 				String | 			Sync sync = post(String.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), 0), | ||||||
| 					.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), 0), | 					senderSync, | ||||||
| 				senderSync, | 					Sync.class); | ||||||
| 				Sync.class); |  | ||||||
|  |  | ||||||
| 		User returnSender = objectFactory.createUser(); | 			// Expecting a single user with an ID | ||||||
|  | 			if (sync.getUsers().size() == 1) { | ||||||
| 		if (returnSenderSync.getUsers().size() == 1) { | 				online = true; | ||||||
| 			returnSender = returnSenderSync.getUsers().get(0); | 				return sync.getUsers().get(0); | ||||||
| 		} else { | 			} else throw new EnvoyException("Unexpected response from Envoy Server"); | ||||||
| 			logger.warning("ERROR exiting..."); | 		} catch (Exception e) { | ||||||
|  | 			throw new EnvoyException("Could not connect to server", e); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		return returnSender; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -134,11 +148,15 @@ public class Client { | |||||||
| 	 * their updated UserStatus to the client.) <br> | 	 * their updated UserStatus to the client.) <br> | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @param userId the id of the {@link Client} who sends the {@link Sync} | 	 * @param userId the id of the {@link Client} who sends the {@link Sync} | ||||||
| 	 * @param sync the sync object (yet to be converted from java class to sync.xml) | 	 * @param sync   the sync object (yet to be converted from java class to | ||||||
|  | 	 *               sync.xml) | ||||||
| 	 * @return a returnSync.xml file | 	 * @return a returnSync.xml file | ||||||
|  | 	 * @throws EnvoyException if the client is not in online mode | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Sync sendSync(long userId, Sync sync) { | 	public Sync sendSync(long userId, Sync sync) throws EnvoyException { | ||||||
|  | 		if(!isOnline()) | ||||||
|  | 			throw new EnvoyException("Client is not in online mode"); | ||||||
| 		// Print sync XML to console | 		// Print sync XML to console | ||||||
| 		JAXBContext jc; | 		JAXBContext jc; | ||||||
| 		try { | 		try { | ||||||
| @@ -151,10 +169,7 @@ public class Client { | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Send sync | 		// Send sync | ||||||
| 		return post(String | 		return post(String.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), userId), sync, Sync.class); | ||||||
| 			.format("%s:%d/envoy-server/rest/sync/syncData?userId=%d", config.getServer(), config.getPort(), userId), |  | ||||||
| 				sync, |  | ||||||
| 				Sync.class); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -163,6 +178,14 @@ public class Client { | |||||||
| 	 */ | 	 */ | ||||||
| 	public User getSender() { return sender; } | 	public User getSender() { return sender; } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Sets the client user which is used to send messages. | ||||||
|  | 	 *  | ||||||
|  | 	 * @param sender the client user to set | ||||||
|  | 	 * @since Envoy v0.2-alpha | ||||||
|  | 	 */ | ||||||
|  | 	public void setSender(User sender) { this.sender = sender; } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return the current recipient of the current chat. | 	 * @return the current recipient of the current chat. | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| @@ -172,7 +195,7 @@ public class Client { | |||||||
| 	/** | 	/** | ||||||
| 	 * Sets the recipient. | 	 * Sets the recipient. | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @param recipient - the recipient to set | 	 * @param recipient the recipient to set | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public void setRecipient(User recipient) { this.recipient = recipient; } | 	public void setRecipient(User recipient) { this.recipient = recipient; } | ||||||
| @@ -182,4 +205,10 @@ public class Client { | |||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public boolean hasRecipient() { return recipient != null; } | 	public boolean hasRecipient() { return recipient != null; } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @return {@code true} if a connection to the server could be established | ||||||
|  | 	 * @since Envoy v0.2-alpha | ||||||
|  | 	 */ | ||||||
|  | 	public boolean isOnline() { return online; } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -3,6 +3,8 @@ package envoy.client; | |||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.util.Properties; | import java.util.Properties; | ||||||
|  |  | ||||||
|  | import envoy.exception.EnvoyException; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Project: <strong>envoy-client</strong><br> |  * Project: <strong>envoy-client</strong><br> | ||||||
|  * File: <strong>Config.java</strong><br> |  * File: <strong>Config.java</strong><br> | ||||||
| @@ -29,17 +31,26 @@ public class Config { | |||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Defaults to the {@code client.properties} file for information. | 	 * Defaults to the {@code client.properties} file for information. | ||||||
|  | 	 * This file contains information about | ||||||
|  | 	 * the server and port, as well as the path to the local | ||||||
|  | 	 * database and the synchronization timeout | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @param properties a {@link Properties} object containing information about | 	 * @throws EnvoyException if the {@code client.properties} file could not be | ||||||
| 	 *                   the server and port, as well as the path to the local | 	 *                        loaded | ||||||
| 	 *                   database and the synchronization timeout |  | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public void load(Properties properties) { | 	public void load() throws EnvoyException { | ||||||
| 		if (properties.containsKey("server")) server = properties.getProperty("server"); | 		ClassLoader loader = getClass().getClassLoader(); | ||||||
| 		if (properties.containsKey("port")) port = Integer.parseInt(properties.getProperty("port")); | 		try { | ||||||
| 		localDB		= new File(properties.getProperty("localDB", ".\\localDB")); | 			Properties properties = new Properties(); | ||||||
| 		syncTimeout	= Integer.parseInt(properties.getProperty("syncTimeout", "1000")); | 			properties.load(loader.getResourceAsStream("client.properties")); | ||||||
|  | 			if (properties.containsKey("server")) server = properties.getProperty("server"); | ||||||
|  | 			if (properties.containsKey("port")) port = Integer.parseInt(properties.getProperty("port")); | ||||||
|  | 			localDB		= new File(properties.getProperty("localDB", ".\\localDB")); | ||||||
|  | 			syncTimeout	= Integer.parseInt(properties.getProperty("syncTimeout", "1000")); | ||||||
|  | 		} catch (Exception e) { | ||||||
|  | 			throw new EnvoyException("Failed to load client.properties", e); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| @@ -47,9 +58,10 @@ public class Config { | |||||||
| 	 * -s, --port / -p and --localDB / -db. | 	 * -s, --port / -p and --localDB / -db. | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @param args the command line arguments to parse | 	 * @param args the command line arguments to parse | ||||||
|  | 	 * @throws EnvoyException if the command line arguments contain an unknown token | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public void load(String[] args) { | 	public void load(String[] args) throws EnvoyException { | ||||||
| 		for (int i = 0; i < args.length; i++) | 		for (int i = 0; i < args.length; i++) | ||||||
| 			switch (args[i]) { | 			switch (args[i]) { | ||||||
| 				case "--server": | 				case "--server": | ||||||
| @@ -64,6 +76,8 @@ public class Config { | |||||||
| 				case "-db": | 				case "-db": | ||||||
| 					localDB = new File(args[++i]); | 					localDB = new File(args[++i]); | ||||||
| 					break; | 					break; | ||||||
|  | 				default: | ||||||
|  | 					throw new EnvoyException("Unknown token " + args[i] + " found"); | ||||||
| 			} | 			} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -71,9 +85,7 @@ public class Config { | |||||||
| 	 * @return {@code true} if server, port and localDB directory are known. | 	 * @return {@code true} if server, port and localDB directory are known. | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public boolean isInitialized() { | 	public boolean isInitialized() { return server != null && !server.isEmpty() && port > 0 && port < 65566 && localDB != null; } | ||||||
| 		return server != null && !server.isEmpty() && port > 0 && port < 65566 && localDB != null; |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return the host name of the Envoy server | 	 * @return the host name of the Envoy server | ||||||
| @@ -114,7 +126,7 @@ public class Config { | |||||||
| 	/** | 	/** | ||||||
| 	 * Changes the default local database. | 	 * Changes the default local database. | ||||||
| 	 * Exclusively intended for development purposes. | 	 * Exclusively intended for development purposes. | ||||||
|    	 * | 	 * | ||||||
| 	 * @param localDB the file containing the local database | 	 * @param localDB the file containing the local database | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 **/ | 	 **/ | ||||||
|   | |||||||
| @@ -8,7 +8,9 @@ import java.io.ObjectInputStream; | |||||||
| import java.io.ObjectOutputStream; | import java.io.ObjectOutputStream; | ||||||
| import java.time.Instant; | import java.time.Instant; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
|  | import java.util.HashMap; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | import java.util.Map; | ||||||
| import java.util.logging.Logger; | import java.util.logging.Logger; | ||||||
|  |  | ||||||
| import javax.xml.datatype.DatatypeConfigurationException; | import javax.xml.datatype.DatatypeConfigurationException; | ||||||
| @@ -34,9 +36,11 @@ import envoy.schema.User; | |||||||
|  */ |  */ | ||||||
| public class LocalDB { | public class LocalDB { | ||||||
|  |  | ||||||
| 	private File			localDB; | 	private File				localDBDir, localDBFile, usersFile; | ||||||
| 	private User			sender; | 	private User				user; | ||||||
| 	private List<Chat>		chats			= new ArrayList<>(); | 	private Map<String, User>	users	= new HashMap<>(); | ||||||
|  | 	private List<Chat>			chats	= new ArrayList<>(); | ||||||
|  |  | ||||||
| 	private ObjectFactory	objectFactory	= new ObjectFactory(); | 	private ObjectFactory	objectFactory	= new ObjectFactory(); | ||||||
| 	private DatatypeFactory	datatypeFactory; | 	private DatatypeFactory	datatypeFactory; | ||||||
|  |  | ||||||
| @@ -44,67 +48,94 @@ public class LocalDB { | |||||||
| 	private Sync	sync				= objectFactory.createSync(); | 	private Sync	sync				= objectFactory.createSync(); | ||||||
| 	private Sync	readMessages		= objectFactory.createSync(); | 	private Sync	readMessages		= objectFactory.createSync(); | ||||||
|  |  | ||||||
|     private static final Logger logger = Logger.getLogger(LocalDB.class.getSimpleName()); | 	private static final Logger logger = Logger.getLogger(LocalDB.class.getSimpleName()); | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Constructs an empty local database. | 	 * Constructs an empty local database. To serialize any chats to the file | ||||||
|  | 	 * system, call {@link LocalDB#initializeDBFile(File)}. | ||||||
| 	 * | 	 * | ||||||
| 	 * @param sender the user that is logged in with this client | 	 * @param localDBDir the directory in which to store users and chats | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public LocalDB(User sender) { | 	public LocalDB(File localDBDir) throws IOException { | ||||||
| 		this.sender = sender; | 		this.localDBDir = localDBDir; | ||||||
|  |  | ||||||
| 		try { | 		try { | ||||||
| 			datatypeFactory = DatatypeFactory.newInstance(); | 			datatypeFactory = DatatypeFactory.newInstance(); | ||||||
| 		} catch (DatatypeConfigurationException e) { | 		} catch (DatatypeConfigurationException e) { | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		// Initialize local database directory | ||||||
|  | 		if (localDBDir.exists() && !localDBDir.isDirectory()) | ||||||
|  | 			throw new IOException(String.format("LocalDBDir '%s' is not a directory!", localDBDir.getAbsolutePath())); | ||||||
|  | 		usersFile = new File(localDBDir, "users.db"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Initializes the local database and fills it with values | 	 * Creates a database file for a user-specific list of chats. | ||||||
| 	 * if the user has already sent or received messages. |  | ||||||
| 	 * | 	 * | ||||||
| 	 * @param localDBDir the directory where we wish to save/load the database from. | 	 * @throws NullPointerException if the client user is not yet specified | ||||||
| 	 * @throws EnvoyException if the directory selected is not an actual directory. |  | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public void initializeDBFile(File localDBDir) throws EnvoyException { | 	public void initializeDBFile() { | ||||||
| 		if (localDBDir.exists() && !localDBDir.isDirectory()) | 		if (user == null) throw new NullPointerException("Client user is null"); | ||||||
| 			throw new EnvoyException(String.format("LocalDBDir '%s' is not a directory!", localDBDir.getAbsolutePath())); | 		localDBFile = new File(localDBDir, user.getID() + ".db"); | ||||||
| 		localDB = new File(localDBDir, sender.getID() + ".db"); |  | ||||||
| 		if (localDB.exists()) loadFromLocalDB(); |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Saves the database into a file for future use. | 	 * Stores all users to the local database. If the client user is specified, the | ||||||
|  | 	 * chats related to this user are stored as well. | ||||||
| 	 * | 	 * | ||||||
| 	 * @throws IOException if something went wrong during saving | 	 * @throws IOException if something went wrong during saving | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public void saveToLocalDB() throws IOException { | 	public void save() throws IOException { | ||||||
| 		localDB.getParentFile().mkdirs(); | 		// Save users | ||||||
| 		localDB.createNewFile(); | 		write(usersFile, users); | ||||||
| 		try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(localDB))) { |  | ||||||
| 			out.writeObject(chats); | 		// Save chats | ||||||
| 		} catch (IOException ex) { | 		write(localDBFile, chats); | ||||||
| 			throw ex; |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * Loads all users that are stored in the local database. | ||||||
|  | 	 *  | ||||||
|  | 	 * @throws EnvoyException if the loading process failed | ||||||
|  | 	 * @since Envoy v0.2-alpha | ||||||
|  | 	 */ | ||||||
|  | 	@SuppressWarnings("unchecked") | ||||||
|  | 	public void loadUsers() throws EnvoyException { users = read(usersFile, HashMap.class); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Loads all chats saved by Envoy for the client user. | 	 * Loads all chats saved by Envoy for the client user. | ||||||
| 	 * | 	 * | ||||||
| 	 * @throws EnvoyException if something fails while loading. | 	 * @throws EnvoyException if the loading process failed | ||||||
| 	 * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	@SuppressWarnings("unchecked") | 	@SuppressWarnings("unchecked") | ||||||
| 	private void loadFromLocalDB() throws EnvoyException { | 	public void loadChats() throws EnvoyException { chats = read(localDBFile, ArrayList.class); } | ||||||
| 		try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(localDB))) { |  | ||||||
| 			Object obj = in.readObject(); | 	private <T> T read(File file, Class<T> serializedClass) throws EnvoyException { | ||||||
| 			if (obj instanceof ArrayList<?>) chats = (ArrayList<Chat>) obj; | 		if (file == null) throw new NullPointerException("File is null"); | ||||||
|  | 		try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(file))) { | ||||||
|  | 			return serializedClass.cast(in.readObject()); | ||||||
| 		} catch (ClassNotFoundException | IOException e) { | 		} catch (ClassNotFoundException | IOException e) { | ||||||
| 			throw new EnvoyException(e); | 			throw new EnvoyException("Could not load serialized object", e); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	private <T> void write(File file, T obj) throws IOException { | ||||||
|  | 		if (file == null) throw new NullPointerException("File is null"); | ||||||
|  | 		if (obj == null) throw new NullPointerException("Object to serialize is null"); | ||||||
|  | 		if (!file.exists()) { | ||||||
|  | 			file.getParentFile().mkdirs(); | ||||||
|  | 			file.createNewFile(); | ||||||
|  | 		} | ||||||
|  | 		try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file))) { | ||||||
|  | 			out.writeObject(obj); | ||||||
|  | 		} catch (IOException e) { | ||||||
|  | 			throw e; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -118,7 +149,7 @@ public class LocalDB { | |||||||
| 	 */ | 	 */ | ||||||
| 	public Message createMessage(String textContent, long recipientID) { | 	public Message createMessage(String textContent, long recipientID) { | ||||||
| 		Message.Metadata metaData = objectFactory.createMessageMetadata(); | 		Message.Metadata metaData = objectFactory.createMessageMetadata(); | ||||||
| 		metaData.setSender(sender.getID()); | 		metaData.setSender(user.getID()); | ||||||
| 		metaData.setRecipient(recipientID); | 		metaData.setRecipient(recipientID); | ||||||
| 		metaData.setState(MessageState.WAITING); | 		metaData.setState(MessageState.WAITING); | ||||||
| 		metaData.setDate(datatypeFactory.newXMLGregorianCalendar(Instant.now().toString())); | 		metaData.setDate(datatypeFactory.newXMLGregorianCalendar(Instant.now().toString())); | ||||||
| @@ -134,13 +165,13 @@ public class LocalDB { | |||||||
| 		return message; | 		return message; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|     /** | 	/** | ||||||
| 	 * Creates a {@link Sync} object filled with the changes that occurred to the | 	 * Creates a {@link Sync} object filled with the changes that occurred to the | ||||||
| 	 * local database since the last synchronization. | 	 * local database since the last synchronization. | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @param userId the ID of the user that is synchronized by this client | 	 * @param userId the ID of the user that is synchronized by this client | ||||||
| 	 * @return {@link Sync} object filled with the current changes | 	 * @return {@link Sync} object filled with the current changes | ||||||
|      * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public Sync fillSync(long userId) { | 	public Sync fillSync(long userId) { | ||||||
| 		addWaitingMessagesToSync(); | 		addWaitingMessagesToSync(); | ||||||
| @@ -156,7 +187,7 @@ public class LocalDB { | |||||||
| 	 * Applies the changes carried by a {@link Sync} object to the local database | 	 * Applies the changes carried by a {@link Sync} object to the local database | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @param returnSync the {@link Sync} object to apply | 	 * @param returnSync the {@link Sync} object to apply | ||||||
|      * @since Envoy v0.1-alpha | 	 * @since Envoy v0.1-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public void applySync(Sync returnSync) { | 	public void applySync(Sync returnSync) { | ||||||
| 		for (int i = 0; i < returnSync.getMessages().size(); i++) { | 		for (int i = 0; i < returnSync.getMessages().size(); i++) { | ||||||
| @@ -280,6 +311,17 @@ public class LocalDB { | |||||||
| 	 */ | 	 */ | ||||||
| 	public void clearUnreadMessagesSync() { unreadMessagesSync.getMessages().clear(); } | 	public void clearUnreadMessagesSync() { unreadMessagesSync.getMessages().clear(); } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @return a {@code Map<String, User>} of all users stored locally with their user names as keys | ||||||
|  | 	 * @since Envoy v0.2-alpha | ||||||
|  | 	 */ | ||||||
|  | 	public Map<String, User> getUsers() { return users; } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @param users the users to set | ||||||
|  | 	 */ | ||||||
|  | 	public void setUsers(Map<String, User> users) { this.users = users; } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return all saved {@link Chat} objects that list the client user as the | 	 * @return all saved {@link Chat} objects that list the client user as the | ||||||
| 	 *         sender | 	 *         sender | ||||||
| @@ -288,8 +330,19 @@ public class LocalDB { | |||||||
| 	public List<Chat> getChats() { return chats; } | 	public List<Chat> getChats() { return chats; } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return the {@link User} who initialized the local database | 	 * @param chats the chats to set | ||||||
| 	 * @since Envoy v0.1-alpha |  | ||||||
| 	 */ | 	 */ | ||||||
| 	public User getUser() { return sender; } | 	public void setChats(List<Chat> chats) { this.chats = chats; } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @return the {@link User} who initialized the local database | ||||||
|  | 	 * @since Envoy v0.2-alpha | ||||||
|  | 	 */ | ||||||
|  | 	public User getUser() { return user; } | ||||||
|  |  | ||||||
|  | 	/** | ||||||
|  | 	 * @param user the user to set | ||||||
|  | 	 * @since Envoy v0.2-alpha | ||||||
|  | 	 */ | ||||||
|  | 	public void setUser(User user) { this.user = user; } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -26,8 +26,6 @@ import envoy.client.ui.Theme; | |||||||
| public class Settings { | public class Settings { | ||||||
|  |  | ||||||
| 	// Actual settings accessible by the rest of the application | 	// Actual settings accessible by the rest of the application | ||||||
| 	private String				username; |  | ||||||
| 	private String				email; |  | ||||||
| 	private boolean				enterToSend	= true; | 	private boolean				enterToSend	= true; | ||||||
| 	private Map<String, Theme>	themes; | 	private Map<String, Theme>	themes; | ||||||
| 	private String				currentTheme; | 	private String				currentTheme; | ||||||
| @@ -65,17 +63,15 @@ public class Settings { | |||||||
|  |  | ||||||
| 	@SuppressWarnings("unchecked") | 	@SuppressWarnings("unchecked") | ||||||
| 	private void load() { | 	private void load() { | ||||||
| 		setUsername(prefs.get("username", "")); |  | ||||||
| 		setEmail(prefs.get("email", "")); |  | ||||||
| 		setEnterToSend(prefs.getBoolean("enterToSend", true)); | 		setEnterToSend(prefs.getBoolean("enterToSend", true)); | ||||||
| 		setCurrentTheme(prefs.get("theme", "dark")); | 		setCurrentTheme(prefs.get("theme", "dark")); | ||||||
|  |  | ||||||
| 		// Load themes from theme file | 		// Load themes from theme file | ||||||
| 		try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(themeFile))) { | 		try (ObjectInputStream in = new ObjectInputStream(new FileInputStream(themeFile))) { | ||||||
| 			Object obj = in.readObject(); | 			Object obj = in.readObject(); | ||||||
| 			if(obj instanceof HashMap) themes = (Map<String, Theme>) obj; | 			if (obj instanceof HashMap) themes = (Map<String, Theme>) obj; | ||||||
| 		} catch (IOException | ClassNotFoundException e) { | 		} catch (IOException | ClassNotFoundException e) { | ||||||
| 			themes = new HashMap<>(); | 			themes			= new HashMap<>(); | ||||||
| 			currentTheme	= "dark"; | 			currentTheme	= "dark"; | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
| 		} | 		} | ||||||
| @@ -90,20 +86,18 @@ public class Settings { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * updates prefs when save button is clicked | 	 * Updates the preferences when the save button is clicked. | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @throws IOException | 	 * @throws IOException | ||||||
| 	 * @since Envoy v0.2-alpha | 	 * @since Envoy v0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public void save() throws IOException{ | 	public void save() throws IOException { | ||||||
| 		prefs.put("username", getUsername()); |  | ||||||
| 		prefs.put("email", getEmail()); |  | ||||||
| 		prefs.put("theme", currentTheme); | 		prefs.put("theme", currentTheme); | ||||||
| 		prefs.putBoolean("enterToSend", isEnterToSend()); | 		prefs.putBoolean("enterToSend", isEnterToSend()); | ||||||
| 		 |  | ||||||
| 		// Save themes to theme file | 		// Save themes to theme file | ||||||
| 		themeFile.createNewFile(); | 		themeFile.createNewFile(); | ||||||
| 		try(ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(themeFile))) { | 		try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(themeFile))) { | ||||||
| 			out.writeObject(themes); | 			out.writeObject(themes); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| @@ -133,30 +127,6 @@ public class Settings { | |||||||
| 	 */ | 	 */ | ||||||
| 	public void setCurrentTheme(String themeName) { currentTheme = themeName; } | 	public void setCurrentTheme(String themeName) { currentTheme = themeName; } | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * @return the user name |  | ||||||
| 	 * @since Envoy v0.2-alpha |  | ||||||
| 	 */ |  | ||||||
| 	public String getUsername() { return username; } |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * @param username the user name to set |  | ||||||
| 	 * @since Envoy v0.2-alpha |  | ||||||
| 	 */ |  | ||||||
| 	public void setUsername(String username) { this.username = username; } |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * @return the email associated with that user. |  | ||||||
| 	 * @since Envoy v0.2-alpha |  | ||||||
| 	 */ |  | ||||||
| 	public String getEmail() { return email; } |  | ||||||
|  |  | ||||||
| 	/** |  | ||||||
| 	 * @param email the email to set |  | ||||||
| 	 * @since Envoy v0.2-alpha |  | ||||||
| 	 */ |  | ||||||
| 	public void setEmail(String email) { this.email = email; } |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return true, if "enter" suffices to send a message, else it has to be "ctrl" | 	 * @return true, if "enter" suffices to send a message, else it has to be "ctrl" | ||||||
| 	 *         + "enter" | 	 *         + "enter" | ||||||
|   | |||||||
| @@ -32,7 +32,6 @@ import envoy.client.Config; | |||||||
| import envoy.client.LocalDB; | import envoy.client.LocalDB; | ||||||
| import envoy.client.Settings; | import envoy.client.Settings; | ||||||
| import envoy.schema.Message; | import envoy.schema.Message; | ||||||
| import envoy.schema.Sync; |  | ||||||
| import envoy.schema.User; | import envoy.schema.User; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -54,15 +53,15 @@ public class ChatWindow extends JFrame { | |||||||
| 	private LocalDB	localDB; | 	private LocalDB	localDB; | ||||||
| 	// GUI components | 	// GUI components | ||||||
| 	private JPanel			contentPane				= new JPanel(); | 	private JPanel			contentPane				= new JPanel(); | ||||||
| 	private PrimaryTextArea	messageEnterTextArea; | 	private PrimaryTextArea	messageEnterTextArea	= new PrimaryTextArea(space); | ||||||
| 	private JList<User>		userList				= new JList<>(); | 	private JList<User>		userList				= new JList<>(); | ||||||
| 	private Chat			currentChat; | 	private Chat			currentChat; | ||||||
| 	private JList<Message>	messageList				= new JList<>(); | 	private JList<Message>	messageList				= new JList<>(); | ||||||
| 	private JScrollPane		scrollPane				= new JScrollPane(); | 	private JScrollPane		scrollPane				= new JScrollPane(); | ||||||
| 	private JTextPane		textPane				= new JTextPane(); | 	private JTextPane		textPane				= new JTextPane(); | ||||||
| 	// private JCheckBox jCbChangeMode; | 	// private JCheckBox jCbChangeMode; | ||||||
| 	private PrimaryButton	postButton; | 	private PrimaryButton	postButton		= new PrimaryButton("Post"); | ||||||
| 	private PrimaryButton	settingsButton; | 	private PrimaryButton	settingsButton	= new PrimaryButton("Settings"); | ||||||
|  |  | ||||||
| 	private static int space = 4; | 	private static int space = 4; | ||||||
|  |  | ||||||
| @@ -84,7 +83,7 @@ public class ChatWindow extends JFrame { | |||||||
| 			@Override | 			@Override | ||||||
| 			public void windowClosing(WindowEvent evt) { | 			public void windowClosing(WindowEvent evt) { | ||||||
| 				try { | 				try { | ||||||
| 					localDB.saveToLocalDB(); | 					localDB.save(); | ||||||
| 					Settings.getInstance().save(); | 					Settings.getInstance().save(); | ||||||
| 				} catch (IOException e1) { | 				} catch (IOException e1) { | ||||||
| 					e1.printStackTrace(); | 					e1.printStackTrace(); | ||||||
| @@ -124,23 +123,18 @@ public class ChatWindow extends JFrame { | |||||||
| 		gbc_scrollPane.insets = new Insets(space, space, space, space); | 		gbc_scrollPane.insets = new Insets(space, space, space, space); | ||||||
| 		contentPane.add(scrollPane, gbc_scrollPane); | 		contentPane.add(scrollPane, gbc_scrollPane); | ||||||
|  |  | ||||||
| 		// Checks for changed Message |  | ||||||
| 		messageEnterTextArea = new PrimaryTextArea(space); |  | ||||||
|  |  | ||||||
| 		// Message enter field | 		// Message enter field | ||||||
| 		messageEnterTextArea.addKeyListener(new KeyAdapter() { | 		messageEnterTextArea.addKeyListener(new KeyAdapter() { | ||||||
|  |  | ||||||
| 			@Override | 			@Override | ||||||
| 			public void keyReleased(KeyEvent e) { | 			public void keyReleased(KeyEvent e) { | ||||||
| 				if (e.getKeyCode() == KeyEvent.VK_ENTER | 				if (e.getKeyCode() == KeyEvent.VK_ENTER | ||||||
| 						&& ((Settings.getInstance().isEnterToSend() && e.getModifiersEx() == 0) | 						&& ((Settings.getInstance().isEnterToSend() && e.getModifiersEx() == 0) || (e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK))) { | ||||||
| 								|| (e.getModifiersEx() == KeyEvent.CTRL_DOWN_MASK))) { |  | ||||||
| 					postMessage(messageList); | 					postMessage(messageList); | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
|  |  | ||||||
| 		GridBagConstraints gbc_messageEnterTextfield = new GridBagConstraints(); | 		GridBagConstraints gbc_messageEnterTextfield = new GridBagConstraints(); | ||||||
| 		gbc_messageEnterTextfield.fill	= GridBagConstraints.BOTH; | 		gbc_messageEnterTextfield.fill	= GridBagConstraints.BOTH; | ||||||
| 		gbc_messageEnterTextfield.gridx	= 1; | 		gbc_messageEnterTextfield.gridx	= 1; | ||||||
| @@ -151,7 +145,6 @@ public class ChatWindow extends JFrame { | |||||||
| 		contentPane.add(messageEnterTextArea, gbc_messageEnterTextfield); | 		contentPane.add(messageEnterTextArea, gbc_messageEnterTextfield); | ||||||
|  |  | ||||||
| 		// Post Button | 		// Post Button | ||||||
| 		postButton = new PrimaryButton("Post"); |  | ||||||
| 		GridBagConstraints gbc_moveSelectionPostButton = new GridBagConstraints(); | 		GridBagConstraints gbc_moveSelectionPostButton = new GridBagConstraints(); | ||||||
|  |  | ||||||
| 		gbc_moveSelectionPostButton.fill	= GridBagConstraints.BOTH; | 		gbc_moveSelectionPostButton.fill	= GridBagConstraints.BOTH; | ||||||
| @@ -164,8 +157,6 @@ public class ChatWindow extends JFrame { | |||||||
| 		contentPane.add(postButton, gbc_moveSelectionPostButton); | 		contentPane.add(postButton, gbc_moveSelectionPostButton); | ||||||
|  |  | ||||||
| 		// Settings Button | 		// Settings Button | ||||||
| 		settingsButton = new PrimaryButton("Settings"); |  | ||||||
|  |  | ||||||
| 		GridBagConstraints gbc_moveSelectionSettingsButton = new GridBagConstraints(); | 		GridBagConstraints gbc_moveSelectionSettingsButton = new GridBagConstraints(); | ||||||
|  |  | ||||||
| 		gbc_moveSelectionSettingsButton.fill	= GridBagConstraints.BOTH; | 		gbc_moveSelectionSettingsButton.fill	= GridBagConstraints.BOTH; | ||||||
| @@ -177,8 +168,8 @@ public class ChatWindow extends JFrame { | |||||||
| 		settingsButton.addActionListener((evt) -> { | 		settingsButton.addActionListener((evt) -> { | ||||||
| 			try { | 			try { | ||||||
| 				SettingsScreen.open(); | 				SettingsScreen.open(); | ||||||
| 				changeChatWindowColors(Settings.getInstance().getCurrentTheme());			 | 				changeChatWindowColors(Settings.getInstance().getCurrentTheme()); | ||||||
|                 } catch (Exception e) { | 			} catch (Exception e) { | ||||||
| 				SettingsScreen.open(); | 				SettingsScreen.open(); | ||||||
| 				logger.log(Level.WARNING, "An error occured while opening the settings screen", e); | 				logger.log(Level.WARNING, "An error occured while opening the settings screen", e); | ||||||
| 				e.printStackTrace(); | 				e.printStackTrace(); | ||||||
| @@ -231,16 +222,16 @@ public class ChatWindow extends JFrame { | |||||||
| 		gbc_userList.insets	= new Insets(space, space, space, space); | 		gbc_userList.insets	= new Insets(space, space, space, space); | ||||||
|  |  | ||||||
| 		changeChatWindowColors(Settings.getInstance().getCurrentTheme()); | 		changeChatWindowColors(Settings.getInstance().getCurrentTheme()); | ||||||
|          |  | ||||||
| 		contentPane.add(userList, gbc_userList); | 		contentPane.add(userList, gbc_userList); | ||||||
| 		contentPane.revalidate(); | 		contentPane.revalidate(); | ||||||
|  |  | ||||||
| 		loadUsersAndChats(); | 		loadUsersAndChats(); | ||||||
| 		startSyncThread(Config.getInstance().getSyncTimeout()); |  | ||||||
|  | 		if (client.isOnline()) startSyncThread(Config.getInstance().getSyncTimeout()); | ||||||
|  |  | ||||||
| 		contentPane.revalidate(); | 		contentPane.revalidate(); | ||||||
| 	} | 	} | ||||||
| 	 |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Used to immediately reload the ChatWindow when settings were changed. | 	 * Used to immediately reload the ChatWindow when settings were changed. | ||||||
| @@ -283,18 +274,14 @@ public class ChatWindow extends JFrame { | |||||||
|  |  | ||||||
| 	private void postMessage(JList<Message> messageList) { | 	private void postMessage(JList<Message> messageList) { | ||||||
| 		if (!client.hasRecipient()) { | 		if (!client.hasRecipient()) { | ||||||
| 			JOptionPane.showMessageDialog(this, | 			JOptionPane.showMessageDialog(this, "Please select a recipient!", "Cannot send message", JOptionPane.INFORMATION_MESSAGE); | ||||||
| 					"Please select a recipient!", |  | ||||||
| 					"Cannot send message", |  | ||||||
| 					JOptionPane.INFORMATION_MESSAGE); |  | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (!messageEnterTextArea.getText().isEmpty()) try { | 		if (!messageEnterTextArea.getText().isEmpty()) try { | ||||||
|  |  | ||||||
| 			// Create and send message object | 			// Create and send message object | ||||||
| 			final Message message = localDB.createMessage(messageEnterTextArea.getText(), | 			final Message message = localDB.createMessage(messageEnterTextArea.getText(), currentChat.getRecipient().getID()); | ||||||
| 					currentChat.getRecipient().getID()); |  | ||||||
| 			currentChat.appendMessage(message); | 			currentChat.appendMessage(message); | ||||||
| 			messageList.setModel(currentChat.getModel()); | 			messageList.setModel(currentChat.getModel()); | ||||||
|  |  | ||||||
| @@ -318,9 +305,8 @@ public class ChatWindow extends JFrame { | |||||||
| 	 */ | 	 */ | ||||||
| 	private void loadUsersAndChats() { | 	private void loadUsersAndChats() { | ||||||
| 		new Thread(() -> { | 		new Thread(() -> { | ||||||
| 			Sync					users			= client.getUsersListXml(); | 			DefaultListModel<User> userListModel = new DefaultListModel<>(); | ||||||
| 			DefaultListModel<User>	userListModel	= new DefaultListModel<>(); | 			localDB.getUsers().values().forEach(user -> { | ||||||
| 			users.getUsers().forEach(user -> { |  | ||||||
| 				userListModel.addElement(user); | 				userListModel.addElement(user); | ||||||
|  |  | ||||||
| 				// Check if user exists in local DB | 				// Check if user exists in local DB | ||||||
| @@ -344,8 +330,11 @@ public class ChatWindow extends JFrame { | |||||||
| 			new Thread(() -> { | 			new Thread(() -> { | ||||||
|  |  | ||||||
| 				// Synchronize | 				// Synchronize | ||||||
| 				localDB.applySync( | 				try { | ||||||
| 						client.sendSync(client.getSender().getID(), localDB.fillSync(client.getSender().getID()))); | 					localDB.applySync(client.sendSync(client.getSender().getID(), localDB.fillSync(client.getSender().getID()))); | ||||||
|  | 				} catch (Exception e) { | ||||||
|  | 					logger.log(Level.SEVERE, "Could not perform sync", e); | ||||||
|  | 				} | ||||||
|  |  | ||||||
| 				// Process unread messages | 				// Process unread messages | ||||||
| 				localDB.addUnreadMessagesToLocalDB(); | 				localDB.addUnreadMessagesToLocalDB(); | ||||||
| @@ -355,8 +344,7 @@ public class ChatWindow extends JFrame { | |||||||
| 				readCurrentChat(); | 				readCurrentChat(); | ||||||
|  |  | ||||||
| 				// Update UI | 				// Update UI | ||||||
| 				SwingUtilities | 				SwingUtilities.invokeLater(() -> { updateUserStates(); contentPane.revalidate(); contentPane.repaint(); }); | ||||||
| 					.invokeLater(() -> { updateUserStates(); contentPane.revalidate(); contentPane.repaint(); }); |  | ||||||
| 			}).start(); | 			}).start(); | ||||||
| 		}).start(); | 		}).start(); | ||||||
| 	} | 	} | ||||||
| @@ -373,4 +361,3 @@ public class ChatWindow extends JFrame { | |||||||
| 	 */ | 	 */ | ||||||
| 	private void readCurrentChat() { if (currentChat != null) { localDB.setMessagesToRead(currentChat); } } | 	private void readCurrentChat() { if (currentChat != null) { localDB.setMessagesToRead(currentChat); } } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -42,22 +42,18 @@ public class MessageListRenderer extends JLabel implements ListCellRenderer<Mess | |||||||
| 		final String	text	= value.getContent().get(0).getText(); | 		final String	text	= value.getContent().get(0).getText(); | ||||||
| 		final String	state	= value.getMetadata().getState().toString(); | 		final String	state	= value.getMetadata().getState().toString(); | ||||||
| 		final String	date	= value.getMetadata().getDate() == null ? "" | 		final String	date	= value.getMetadata().getDate() == null ? "" | ||||||
| 				: new SimpleDateFormat("dd.MM.yyyy HH:mm ") | 				: new SimpleDateFormat("dd.MM.yyyy HH:mm ").format(value.getMetadata().getDate().toGregorianCalendar().getTime()); | ||||||
| 					.format(value.getMetadata().getDate().toGregorianCalendar().getTime()); |  | ||||||
|  |  | ||||||
| 		// Getting the MessageColor in the Chat of the current theme | 		// Getting the MessageColor in the Chat of the current theme | ||||||
| 		String textColor = null; | 		String textColor = null; | ||||||
|  |  | ||||||
| 		textColor = toHex( | 		textColor = toHex(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat()); | ||||||
| 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat()); |  | ||||||
|  |  | ||||||
| 		// Getting the DateColor in the Chat of the current theme | 		// Getting the DateColor in the Chat of the current theme | ||||||
| 		String dateColor = null; | 		String dateColor = null; | ||||||
| 		dateColor = toHex( | 		dateColor = toHex(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat()); | ||||||
| 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat()); |  | ||||||
|  |  | ||||||
| 		setText(String.format( | 		setText(String.format("<html><p style=\"color:%s\"><b><small>%s</b></small><br><p style=\"color:%s\">%s :%s</html>", | ||||||
| 				"<html><p style=\"color:%s\"><b><small>%s</b></small><br><p style=\"color:%s\">%s :%s</html>", |  | ||||||
| 				dateColor, | 				dateColor, | ||||||
| 				date, | 				date, | ||||||
| 				textColor, | 				textColor, | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ import javax.swing.JButton; | |||||||
|  *  |  *  | ||||||
|  * @author Kai S. K. Engelbart |  * @author Kai S. K. Engelbart | ||||||
|  * @author Maximilian Käfer |  * @author Maximilian Käfer | ||||||
|  |  * @since Envoy v0.2-alpha | ||||||
|  */ |  */ | ||||||
| public class PrimaryButton extends JButton { | public class PrimaryButton extends JButton { | ||||||
|  |  | ||||||
| @@ -35,8 +36,6 @@ public class PrimaryButton extends JButton { | |||||||
| 	 */ | 	 */ | ||||||
| 	public PrimaryButton(String title, int arcSize) { | 	public PrimaryButton(String title, int arcSize) { | ||||||
| 		super(title); | 		super(title); | ||||||
| 		// setForeground(new Color(255, 255, 255)); |  | ||||||
| 		// setBackground(new Color(102, 51, 153)); |  | ||||||
| 		setBorderPainted(false); | 		setBorderPainted(false); | ||||||
| 		setFocusPainted(false); | 		setFocusPainted(false); | ||||||
| 		setContentAreaFilled(false); | 		setContentAreaFilled(false); | ||||||
|   | |||||||
| @@ -12,15 +12,15 @@ import javax.swing.border.EmptyBorder; | |||||||
|  * Created: <strong>07.12.2019</strong><br> |  * Created: <strong>07.12.2019</strong><br> | ||||||
|  *  |  *  | ||||||
|  * @author Maximilian Käfer |  * @author Maximilian Käfer | ||||||
|  |  * @since Envoy v0.2-alpha | ||||||
|  */ |  */ | ||||||
| public class PrimaryTextArea extends JTextArea { | public class PrimaryTextArea extends JTextArea { | ||||||
|  |  | ||||||
| 	private static final long serialVersionUID = 1L; | 	private static final long	serialVersionUID	= -5829028696155434913L; | ||||||
|  | 	private int					arcSize; | ||||||
| 	private int arcSize; |  | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Creates TextArea | 	 * Creates the text area | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @param borderSpace | 	 * @param borderSpace | ||||||
| 	 * @since Envoy 0.2-alpha | 	 * @since Envoy 0.2-alpha | ||||||
| @@ -28,10 +28,10 @@ public class PrimaryTextArea extends JTextArea { | |||||||
| 	public PrimaryTextArea(int borderSpace) { this(6, borderSpace); } | 	public PrimaryTextArea(int borderSpace) { this(6, borderSpace); } | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Creates TextArea | 	 * Creates the text area | ||||||
| 	 *  | 	 *  | ||||||
| 	 * @param arcSize | 	 * @param arcSize     is the diameter of the arc at the four corners. | ||||||
| 	 * @param borderSpace | 	 * @param borderSpace is the insets of the border on all four sides. | ||||||
| 	 * @since Envoy 0.2-alpha | 	 * @since Envoy 0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public PrimaryTextArea(int arcSize, int borderSpace) { | 	public PrimaryTextArea(int arcSize, int borderSpace) { | ||||||
| @@ -54,7 +54,7 @@ public class PrimaryTextArea extends JTextArea { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * @return the arcSize | 	 * @return the arcSize - the diameter of the arc at the four corners. | ||||||
| 	 * @since Envoy 0.2-alpha | 	 * @since Envoy 0.2-alpha | ||||||
| 	 */ | 	 */ | ||||||
| 	public int getArcSize() { return arcSize; } | 	public int getArcSize() { return arcSize; } | ||||||
|   | |||||||
| @@ -101,8 +101,7 @@ public class SettingsScreen extends JDialog { | |||||||
|  |  | ||||||
| 			createNewThemeButton.setEnabled(false); | 			createNewThemeButton.setEnabled(false); | ||||||
|  |  | ||||||
| 			temporaryTheme = new Theme("temporaryTheme", | 			temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); | ||||||
| 					Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); |  | ||||||
|  |  | ||||||
| 			// Content pane | 			// Content pane | ||||||
| 			GridBagLayout gbl_contentPanel = new GridBagLayout(); | 			GridBagLayout gbl_contentPanel = new GridBagLayout(); | ||||||
| @@ -190,20 +189,8 @@ public class SettingsScreen extends JDialog { | |||||||
| 			colorsPanel.setLayout(new BoxLayout(colorsPanel, BoxLayout.Y_AXIS)); | 			colorsPanel.setLayout(new BoxLayout(colorsPanel, BoxLayout.Y_AXIS)); | ||||||
| 			colorsPanel.setAlignmentX(Component.LEFT_ALIGNMENT); | 			colorsPanel.setAlignmentX(Component.LEFT_ALIGNMENT); | ||||||
|  |  | ||||||
| 			buildCustomizeElement(new JPanel(), | 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getBackgroundColor(), "Background", 0); | ||||||
| 					new JButton(), | 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getCellColor(), "Cells", 1); | ||||||
| 					new JTextPane(), |  | ||||||
| 					theme, |  | ||||||
| 					theme.getBackgroundColor(), |  | ||||||
| 					"Background", |  | ||||||
| 					0); |  | ||||||
| 			buildCustomizeElement(new JPanel(), |  | ||||||
| 					new JButton(), |  | ||||||
| 					new JTextPane(), |  | ||||||
| 					theme, |  | ||||||
| 					theme.getCellColor(), |  | ||||||
| 					"Cells", |  | ||||||
| 					1); |  | ||||||
| 			buildCustomizeElement(new JPanel(), | 			buildCustomizeElement(new JPanel(), | ||||||
| 					new JButton(), | 					new JButton(), | ||||||
| 					new JTextPane(), | 					new JTextPane(), | ||||||
| @@ -218,41 +205,11 @@ public class SettingsScreen extends JDialog { | |||||||
| 					theme.getInteractableBackgroundColor(), | 					theme.getInteractableBackgroundColor(), | ||||||
| 					"Interactable Background", | 					"Interactable Background", | ||||||
| 					3); | 					3); | ||||||
| 			buildCustomizeElement(new JPanel(), | 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getMessageColorChat(), "Messages Chat", 4); | ||||||
| 					new JButton(), | 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getDateColorChat(), "Date Chat", 5); | ||||||
| 					new JTextPane(), | 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getSelectionColor(), "Selection", 6); | ||||||
| 					theme, | 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getTypingMessageColor(), "Typing Message", 7); | ||||||
| 					theme.getMessageColorChat(), | 			buildCustomizeElement(new JPanel(), new JButton(), new JTextPane(), theme, theme.getUserNameColor(), "User Names", 8); | ||||||
| 					"Messages Chat", |  | ||||||
| 					4); |  | ||||||
| 			buildCustomizeElement(new JPanel(), |  | ||||||
| 					new JButton(), |  | ||||||
| 					new JTextPane(), |  | ||||||
| 					theme, |  | ||||||
| 					theme.getDateColorChat(), |  | ||||||
| 					"Date Chat", |  | ||||||
| 					5); |  | ||||||
| 			buildCustomizeElement(new JPanel(), |  | ||||||
| 					new JButton(), |  | ||||||
| 					new JTextPane(), |  | ||||||
| 					theme, |  | ||||||
| 					theme.getSelectionColor(), |  | ||||||
| 					"Selection", |  | ||||||
| 					6); |  | ||||||
| 			buildCustomizeElement(new JPanel(), |  | ||||||
| 					new JButton(), |  | ||||||
| 					new JTextPane(), |  | ||||||
| 					theme, |  | ||||||
| 					theme.getTypingMessageColor(), |  | ||||||
| 					"Typing Message", |  | ||||||
| 					7); |  | ||||||
| 			buildCustomizeElement(new JPanel(), |  | ||||||
| 					new JButton(), |  | ||||||
| 					new JTextPane(), |  | ||||||
| 					theme, |  | ||||||
| 					theme.getUserNameColor(), |  | ||||||
| 					"User Names", |  | ||||||
| 					8); |  | ||||||
|  |  | ||||||
| 			GridBagConstraints gbc_colorsPanel = new GridBagConstraints(); | 			GridBagConstraints gbc_colorsPanel = new GridBagConstraints(); | ||||||
| 			gbc_colorsPanel.fill		= GridBagConstraints.HORIZONTAL; | 			gbc_colorsPanel.fill		= GridBagConstraints.HORIZONTAL; | ||||||
| @@ -273,16 +230,14 @@ public class SettingsScreen extends JDialog { | |||||||
| 					String s = JOptionPane.showInputDialog("Enter a name for the new theme"); | 					String s = JOptionPane.showInputDialog("Enter a name for the new theme"); | ||||||
| 					System.out.println(s); | 					System.out.println(s); | ||||||
| 					Settings.getInstance() | 					Settings.getInstance() | ||||||
| 						.addNewThemeToMap(new Theme(s, temporaryTheme.getBackgroundColor(), | 						.addNewThemeToMap(new Theme(s, temporaryTheme.getBackgroundColor(), temporaryTheme.getCellColor(), | ||||||
| 								temporaryTheme.getCellColor(), temporaryTheme.getInteractableForegroundColor(), | 								temporaryTheme.getInteractableForegroundColor(), temporaryTheme.getInteractableBackgroundColor(), | ||||||
| 								temporaryTheme.getInteractableBackgroundColor(), temporaryTheme.getMessageColorChat(), | 								temporaryTheme.getMessageColorChat(), temporaryTheme.getDateColorChat(), temporaryTheme.getSelectionColor(), | ||||||
| 								temporaryTheme.getDateColorChat(), temporaryTheme.getSelectionColor(), |  | ||||||
| 								temporaryTheme.getTypingMessageColor(), temporaryTheme.getUserNameColor())); | 								temporaryTheme.getTypingMessageColor(), temporaryTheme.getUserNameColor())); | ||||||
| 					themeArray							= Arrays.copyOf(themeArray, themeArray.length + 1); | 					themeArray							= Arrays.copyOf(themeArray, themeArray.length + 1); | ||||||
| 					themeArray[themeArray.length - 1]	= Settings.getInstance().getThemes().get(s).getThemeName(); | 					themeArray[themeArray.length - 1]	= Settings.getInstance().getThemes().get(s).getThemeName(); | ||||||
|  |  | ||||||
| 					temporaryTheme = new Theme("temporaryTheme", | 					temporaryTheme = new Theme("temporaryTheme", Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); | ||||||
| 							Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme())); |  | ||||||
|  |  | ||||||
| 					createNewThemeButton.setEnabled(false); | 					createNewThemeButton.setEnabled(false); | ||||||
| 					themes.addItem(themeArray[themeArray.length - 1]); | 					themes.addItem(themeArray[themeArray.length - 1]); | ||||||
| @@ -336,10 +291,6 @@ public class SettingsScreen extends JDialog { | |||||||
| 				getRootPane().setDefaultButton(okButton); | 				getRootPane().setDefaultButton(okButton); | ||||||
| 				okButton.addActionListener((evt) -> { | 				okButton.addActionListener((evt) -> { | ||||||
| 					try { | 					try { | ||||||
| 						Settings.getInstance().setUsername(Settings.getInstance().getUsername());// still temporary |  | ||||||
|  |  | ||||||
| 						Settings.getInstance().setEmail(Settings.getInstance().getEmail());// still temporary value |  | ||||||
|  |  | ||||||
| 						Settings.getInstance().setEnterToSend(Settings.getInstance().isEnterToSend());// still temporary | 						Settings.getInstance().setEnterToSend(Settings.getInstance().isEnterToSend());// still temporary | ||||||
|  |  | ||||||
| 						Settings.getInstance().setCurrentTheme(selectedTheme.getThemeName()); | 						Settings.getInstance().setCurrentTheme(selectedTheme.getThemeName()); | ||||||
| @@ -400,21 +351,12 @@ public class SettingsScreen extends JDialog { | |||||||
| 		temporaryTheme = new Theme("temporaryTheme", | 		temporaryTheme = new Theme("temporaryTheme", | ||||||
| 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getBackgroundColor(), | 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getBackgroundColor(), | ||||||
| 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor(), | 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getCellColor(), | ||||||
| 				Settings.getInstance() | 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getInteractableForegroundColor(), | ||||||
| 					.getThemes() | 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getInteractableBackgroundColor(), | ||||||
| 					.get(Settings.getInstance().getCurrentTheme()) |  | ||||||
| 					.getInteractableForegroundColor(), |  | ||||||
| 				Settings.getInstance() |  | ||||||
| 					.getThemes() |  | ||||||
| 					.get(Settings.getInstance().getCurrentTheme()) |  | ||||||
| 					.getInteractableBackgroundColor(), |  | ||||||
| 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat(), | 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getMessageColorChat(), | ||||||
| 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat(), | 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getDateColorChat(), | ||||||
| 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getSelectionColor(), | 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getSelectionColor(), | ||||||
| 				Settings.getInstance() | 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getTypingMessageColor(), | ||||||
| 					.getThemes() |  | ||||||
| 					.get(Settings.getInstance().getCurrentTheme()) |  | ||||||
| 					.getTypingMessageColor(), |  | ||||||
| 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor()); | 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor()); | ||||||
|  |  | ||||||
| 		colorsPanel.removeAll(); | 		colorsPanel.removeAll(); | ||||||
| @@ -501,8 +443,7 @@ public class SettingsScreen extends JDialog { | |||||||
|  |  | ||||||
| 	private void setContent(JPanel content, GridBagConstraints layout) { contentPanel.add(content, layout); } | 	private void setContent(JPanel content, GridBagConstraints layout) { contentPanel.add(content, layout); } | ||||||
|  |  | ||||||
| 	private void buildCustomizeElement(JPanel panel, JButton button, JTextPane textPane, Theme theme, Color color, | 	private void buildCustomizeElement(JPanel panel, JButton button, JTextPane textPane, Theme theme, Color color, String name, int yIndex) { | ||||||
| 			String name, int yIndex) { |  | ||||||
| 		textPane.setFont(new Font("Arial", Font.PLAIN, 14)); | 		textPane.setFont(new Font("Arial", Font.PLAIN, 14)); | ||||||
| 		textPane.setBackground(theme.getBackgroundColor()); | 		textPane.setBackground(theme.getBackgroundColor()); | ||||||
| 		textPane.setForeground(getInvertedColor(theme.getBackgroundColor())); | 		textPane.setForeground(getInvertedColor(theme.getBackgroundColor())); | ||||||
|   | |||||||
| @@ -2,7 +2,6 @@ package envoy.client.ui; | |||||||
|  |  | ||||||
| import java.awt.EventQueue; | import java.awt.EventQueue; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.util.Properties; |  | ||||||
| import java.util.logging.Level; | import java.util.logging.Level; | ||||||
| import java.util.logging.Logger; | import java.util.logging.Logger; | ||||||
|  |  | ||||||
| @@ -11,12 +10,12 @@ import javax.swing.JOptionPane; | |||||||
| import envoy.client.Client; | import envoy.client.Client; | ||||||
| import envoy.client.Config; | import envoy.client.Config; | ||||||
| import envoy.client.LocalDB; | import envoy.client.LocalDB; | ||||||
| import envoy.client.Settings; |  | ||||||
| import envoy.exception.EnvoyException; | import envoy.exception.EnvoyException; | ||||||
|  | import envoy.schema.User; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * Starts the Envoy client and prompts the user to enter their name. |  * Starts the Envoy client and prompts the user to enter their name. | ||||||
|  *  |  * <br> | ||||||
|  * Project: <strong>envoy-client</strong><br> |  * Project: <strong>envoy-client</strong><br> | ||||||
|  * File: <strong>Startup.java</strong><br> |  * File: <strong>Startup.java</strong><br> | ||||||
|  * Created: <strong>12 Oct 2019</strong><br> |  * Created: <strong>12 Oct 2019</strong><br> | ||||||
| @@ -35,34 +34,69 @@ public class Startup { | |||||||
|  |  | ||||||
| 		Config config = Config.getInstance(); | 		Config config = Config.getInstance(); | ||||||
|  |  | ||||||
| 		// Load the configuration from client.properties first |  | ||||||
| 		ClassLoader loader = Thread.currentThread().getContextClassLoader(); |  | ||||||
| 		try { | 		try { | ||||||
| 			Properties configProperties = new Properties(); | 			// Load the configuration from client.properties first | ||||||
| 			configProperties.load(loader.getResourceAsStream("client.properties")); | 			config.load(); | ||||||
| 			config.load(configProperties); |  | ||||||
| 		} catch (IOException e) { | 			// Override configuration values with command line arguments | ||||||
|  | 			if (args.length > 0) config.load(args); | ||||||
|  |  | ||||||
|  | 			// Check if all configuration values have been initialized | ||||||
|  | 			if (!config.isInitialized()) throw new EnvoyException("Server or port are not defined"); | ||||||
|  | 		} catch (Exception e) { | ||||||
|  | 			JOptionPane | ||||||
|  | 				.showMessageDialog(null, "Error loading configuration values: \n" + e.toString(), "Configuration error", JOptionPane.ERROR_MESSAGE); | ||||||
|  | 			System.exit(1); | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// Override configuration values with command line arguments | 		// Ask the user for their user name | ||||||
| 		if (args.length > 0) config.load(args); |  | ||||||
|  |  | ||||||
| 		if (!config.isInitialized()) { |  | ||||||
| 			logger.severe("Server or port are not defined. Exiting..."); |  | ||||||
| 			JOptionPane.showMessageDialog(null, "Error loading configuration values.", "Configuration error", JOptionPane.ERROR_MESSAGE); |  | ||||||
| 			System.exit(1); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		String userName = JOptionPane.showInputDialog("Please enter your username"); | 		String userName = JOptionPane.showInputDialog("Please enter your username"); | ||||||
| 		if (userName == null || userName.isEmpty()) { | 		if (userName == null || userName.isEmpty()) { | ||||||
| 			logger.severe("User name is not set or empty. Exiting..."); | 			logger.severe("User name is not set or empty. Exiting..."); | ||||||
| 			System.exit(1); | 			System.exit(1); | ||||||
| 		} | 		} | ||||||
| 		Client	client	= new Client(config, userName); | 		 | ||||||
| 		LocalDB	localDB	= new LocalDB(client.getSender()); | 		// Initialize the local database | ||||||
|  | 		LocalDB localDB; | ||||||
| 		try { | 		try { | ||||||
| 			localDB.initializeDBFile(config.getLocalDB()); | 			localDB = new LocalDB(config.getLocalDB()); | ||||||
|  | 		} catch (IOException e3) { | ||||||
|  | 			logger.log(Level.SEVERE, "Could not initialize local database", e3); | ||||||
|  | 			JOptionPane.showMessageDialog(null, "Could not initialize local database!\n" + e3.toString()); | ||||||
|  | 			System.exit(1); | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		// Acquire the client user (with ID) either from the server or from the local | ||||||
|  | 		// database, which triggers offline mode | ||||||
|  | 		Client client = new Client(config); | ||||||
|  | 		try { | ||||||
|  | 			// Try entering online mode first | ||||||
|  | 			client.onlineInit(userName); | ||||||
|  | 		} catch (Exception e1) { | ||||||
|  | 			logger.warning("Could not connect to server. Trying offline mode..."); | ||||||
|  | 			try { | ||||||
|  | 				// Try entering offline mode | ||||||
|  | 				localDB.loadUsers(); | ||||||
|  | 				User clientUser = localDB.getUsers().get(userName); | ||||||
|  | 				if(clientUser == null) | ||||||
|  | 					throw new EnvoyException("Could not enter offline mode: user name unknown"); | ||||||
|  | 				client.setSender(clientUser); | ||||||
|  | 			} catch(Exception e2) { | ||||||
|  | 				JOptionPane.showMessageDialog(null, e1.toString(), "Client error", JOptionPane.ERROR_MESSAGE); | ||||||
|  | 				System.exit(1); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		 | ||||||
|  | 		// Set client user in local database | ||||||
|  | 		localDB.setUser(client.getSender()); | ||||||
|  | 		 | ||||||
|  | 		// Initialize chats in local database | ||||||
|  | 		try { | ||||||
|  | 			localDB.initializeDBFile(); | ||||||
|  | 			localDB.loadChats(); | ||||||
| 		} catch (EnvoyException e) { | 		} catch (EnvoyException e) { | ||||||
| 			e.printStackTrace(); | 			e.printStackTrace(); | ||||||
| 			JOptionPane.showMessageDialog(null, | 			JOptionPane.showMessageDialog(null, | ||||||
| @@ -70,13 +104,23 @@ public class Startup { | |||||||
| 					"Local DB error", | 					"Local DB error", | ||||||
| 					JOptionPane.WARNING_MESSAGE); | 					JOptionPane.WARNING_MESSAGE); | ||||||
| 		} | 		} | ||||||
| 		Settings.getInstance().setUsername(userName); | 		 | ||||||
|  | 		logger.info("Client user ID: " + client.getSender().getID()); | ||||||
|  |  | ||||||
|  | 		// Save all users to the local database | ||||||
|  | 		if(client.isOnline()) | ||||||
|  | 			localDB.setUsers(client.getUsers()); | ||||||
| 		 | 		 | ||||||
| 		EventQueue.invokeLater(() -> { | 		EventQueue.invokeLater(() -> { | ||||||
| 			try { | 			try { | ||||||
| 				ChatWindow chatWindow = new ChatWindow(client, localDB); | 				ChatWindow chatWindow = new ChatWindow(client, localDB); | ||||||
| 				new StatusTrayIcon(chatWindow).show(); |  | ||||||
| 				chatWindow.setVisible(true); | 				chatWindow.setVisible(true); | ||||||
|  |  | ||||||
|  | 				try { | ||||||
|  | 					new StatusTrayIcon(chatWindow).show(); | ||||||
|  | 				} catch (EnvoyException e) { | ||||||
|  | 					logger.warning("The StatusTrayIcon is not supported on this platform!"); | ||||||
|  | 				} | ||||||
| 			} catch (Exception e) { | 			} catch (Exception e) { | ||||||
| 				e.printStackTrace(); | 				e.printStackTrace(); | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -26,9 +26,8 @@ public class Theme implements Serializable { | |||||||
| 	private Color	selectionColor; | 	private Color	selectionColor; | ||||||
| 	private Color	typingMessageColor; | 	private Color	typingMessageColor; | ||||||
|  |  | ||||||
| 	public Theme(String themeName, Color backgroundColor, Color cellColor, Color interactableForegroundColor, | 	public Theme(String themeName, Color backgroundColor, Color cellColor, Color interactableForegroundColor, Color interactableBackgroundColor, | ||||||
| 			Color interactableBackgroundColor, Color messageColorChat, Color dateColorChat, Color selectionColor, | 			Color messageColorChat, Color dateColorChat, Color selectionColor, Color typingMessageColor, Color userNameColor) { | ||||||
| 			Color typingMessageColor, Color userNameColor) { |  | ||||||
|  |  | ||||||
| 		this.themeName = themeName; | 		this.themeName = themeName; | ||||||
|  |  | ||||||
| @@ -42,7 +41,7 @@ public class Theme implements Serializable { | |||||||
| 		this.typingMessageColor				= typingMessageColor; | 		this.typingMessageColor				= typingMessageColor; | ||||||
| 		this.userNameColor					= userNameColor; | 		this.userNameColor					= userNameColor; | ||||||
| 	} | 	} | ||||||
| 	 |  | ||||||
| 	public Theme(String name, Theme other) { | 	public Theme(String name, Theme other) { | ||||||
| 		this(name, other.backgroundColor, other.cellColor, other.interactableForegroundColor, | 		this(name, other.backgroundColor, other.cellColor, other.interactableForegroundColor, | ||||||
| 				other.interactableBackgroundColor, other.messageColorChat, other.dateColorChat, other.selectionColor, | 				other.interactableBackgroundColor, other.messageColorChat, other.dateColorChat, other.selectionColor, | ||||||
|   | |||||||
| @@ -44,23 +44,16 @@ public class UserListRenderer extends JLabel implements ListCellRenderer<User> { | |||||||
| 		final UserStatus	status	= value.getStatus(); | 		final UserStatus	status	= value.getStatus(); | ||||||
|  |  | ||||||
| 		// Getting the UserNameColor of the current theme | 		// Getting the UserNameColor of the current theme | ||||||
| 		String				textColor	= null; | 		String textColor = null; | ||||||
| 		textColor = toHex( | 		textColor = toHex(Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor()); | ||||||
| 				Settings.getInstance().getThemes().get(Settings.getInstance().getCurrentTheme()).getUserNameColor()); |  | ||||||
| 		switch (status) { | 		switch (status) { | ||||||
| 			case ONLINE: | 			case ONLINE: | ||||||
| 				setText(String.format( | 				setText(String | ||||||
| 						"<html><p style=\"color:#03fc20\"><b><small>%s</b></small><br><p style=\"color:%s\">%s</html>", | 					.format("<html><p style=\"color:#03fc20\"><b><small>%s</b></small><br><p style=\"color:%s\">%s</html>", status, textColor, name)); | ||||||
| 						status, |  | ||||||
| 						textColor, |  | ||||||
| 						name)); |  | ||||||
| 				break; | 				break; | ||||||
| 			case OFFLINE: | 			case OFFLINE: | ||||||
| 				setText(String.format( | 				setText(String | ||||||
| 						"<html><p style=\"color:#fc0303\"><b><small>%s</b></small><br><p style=\"color:%s\">%s</html>", | 					.format("<html><p style=\"color:#fc0303\"><b><small>%s</b></small><br><p style=\"color:%s\">%s</html>", status, textColor, name)); | ||||||
| 						status, |  | ||||||
| 						textColor, |  | ||||||
| 						name)); |  | ||||||
| 				break; | 				break; | ||||||
| 		} | 		} | ||||||
| 		return this; | 		return this; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 DieGurke
					DieGurke