From 6122c1842792e2a5612eef2260fbf43bc2ade5a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sebastian=20K=C3=BCrten?= <sebastian@mobanisto.de>
Date: Thu, 9 Sep 2021 22:46:49 +0200
Subject: [PATCH] Add UI stubs from Paul's prototype

---
 build.gradle.kts                              |   1 +
 .../briar/desktop/BriarService.kt             |   8 +-
 .../briar/desktop/paul/data/Contacts.kt       | 229 +++++++++++++
 .../briar/desktop/paul/data/ContentType.kt    |  16 +
 .../briar/desktop/paul/data/OptionType.kt     |  14 +
 .../briar/desktop/paul/model/Contact.kt       |   9 +
 .../briar/desktop/paul/model/ContentType.kt   |   7 +
 .../briar/desktop/paul/model/Message.kt       |   9 +
 .../briar/desktop/paul/model/OptionType.kt    |   9 +
 .../briar/desktop/paul/theme/colors.kt        |  32 ++
 .../briar/desktop/paul/views/BriarSidebar.kt  | 103 ++++++
 .../desktop/paul/views/BriarUIStateManager.kt |  51 +++
 .../desktop/paul/views/PrivateMessageView.kt  | 319 ++++++++++++++++++
 .../resources/images/profile_images/p0.png    | Bin 0 -> 45426 bytes
 .../resources/images/profile_images/p1.png    | Bin 0 -> 2804 bytes
 .../resources/images/profile_images/p2.png    | Bin 0 -> 45426 bytes
 .../resources/images/profile_images/p3.png    | Bin 0 -> 45426 bytes
 .../resources/images/profile_images/p4.png    | Bin 0 -> 45426 bytes
 .../resources/images/profile_images/p5.png    | Bin 0 -> 45426 bytes
 19 files changed, 800 insertions(+), 7 deletions(-)
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/data/Contacts.kt
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/data/ContentType.kt
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/data/OptionType.kt
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/model/Contact.kt
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/model/ContentType.kt
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/model/Message.kt
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/model/OptionType.kt
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/theme/colors.kt
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarSidebar.kt
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarUIStateManager.kt
 create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/paul/views/PrivateMessageView.kt
 create mode 100644 src/main/resources/images/profile_images/p0.png
 create mode 100644 src/main/resources/images/profile_images/p1.png
 create mode 100644 src/main/resources/images/profile_images/p2.png
 create mode 100644 src/main/resources/images/profile_images/p3.png
 create mode 100644 src/main/resources/images/profile_images/p4.png
 create mode 100644 src/main/resources/images/profile_images/p5.png

diff --git a/build.gradle.kts b/build.gradle.kts
index 66f5b38406..af4aeb877c 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -24,6 +24,7 @@ dependencies {
 
     implementation("com.fasterxml.jackson.core:jackson-databind:2.10.0")
     implementation("com.github.ajalt:clikt:2.2.0")
+    implementation("org.jetbrains.compose.material:material-icons-extended:0.4.0")
 
     implementation(project(path = ":briar:briar-core", configuration = "default"))
     implementation(project(path = ":briar:bramble-java", configuration = "default"))
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/BriarService.kt b/src/main/kotlin/org/briarproject/briar/desktop/BriarService.kt
index ad43f0bb61..18a11ca523 100644
--- a/src/main/kotlin/org/briarproject/briar/desktop/BriarService.kt
+++ b/src/main/kotlin/org/briarproject/briar/desktop/BriarService.kt
@@ -66,13 +66,7 @@ constructor(
                     })
 
                 is Screen.Main ->
-                    Column(
-                        modifier = Modifier.padding(16.dp).fillMaxSize(),
-                        verticalArrangement = Arrangement.Center,
-                        horizontalAlignment = Alignment.CenterHorizontally
-                    ) {
-                        Text("Welcome to Briar")
-                    }
+                    briarUIStateManager()
             }
         }
     }
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/data/Contacts.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/Contacts.kt
new file mode 100644
index 0000000000..2b7b47c203
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/Contacts.kt
@@ -0,0 +1,229 @@
+package org.briarproject.briar.desktop.paul.data
+
+import org.briarproject.briar.desktop.paul.model.Contact
+import org.briarproject.briar.desktop.paul.model.Message
+
+object ContactList {
+    val msg1: List<Message> = listOf<Message>(
+        Message(from = "Alice", message = "hello!", time = "2 days ago", delivered = true),
+        Message(from = null, message = "yes I hear you", time = "1 day ago", delivered = true),
+        Message(
+            from = null,
+            message = "I am messaging you through this fake Briar Desktop app",
+            time = "18 hrs. ago",
+            delivered = true
+        ),
+        Message(from = "Alice", message = "Ah I see, very neat", time = "12 min. ago", delivered = true),
+        Message(from = null, message = "Loren Ipsum", time = "2 min. ago", delivered = false)
+    )
+    val msg2: List<Message> = listOf<Message>(
+        Message(
+            from = null,
+            message = "The air bites shrewdly; it is very cold.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(from = "Bob", message = "It is a nipping and an eager air.", time = "1 day ago", delivered = true),
+        Message(from = null, message = "What hour now?", time = "18 hrs. ago", delivered = true),
+        Message(from = "Bob", message = "I think it lacks of twelve.", time = "12 min. ago", delivered = true),
+        Message(from = null, message = "No, it is struck.", time = "2 min. ago", delivered = false),
+        Message(
+            from = "Bob",
+            message = "Indeed? I heard it not: then it draws near the season Wherein the spirit held his wont to walk. A flourish of trumpets, and ordnance shot off, within. What does this mean, my lord?",
+            time = "2 min. ago",
+            delivered = false
+        ),
+        Message(
+            from = null,
+            message = "The air bites shrewdly; it is very cold.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(from = "Bob", message = "It is a nipping and an eager air.", time = "1 day ago", delivered = true),
+        Message(from = null, message = "What hour now?", time = "18 hrs. ago", delivered = true),
+        Message(from = "Bob", message = "I think it lacks of twelve.", time = "12 min. ago", delivered = true),
+        Message(from = null, message = "No, it is struck.", time = "2 min. ago", delivered = false),
+        Message(
+            from = null,
+            message = "The air bites shrewdly; it is very cold.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(
+            from = null,
+            message = "The air bites shrewdly; it is very cold.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(from = "Bob", message = "It is a nipping and an eager air.", time = "1 day ago", delivered = true),
+        Message(from = null, message = "What hour now?", time = "18 hrs. ago", delivered = true),
+        Message(from = "Bob", message = "I think it lacks of twelve.", time = "12 min. ago", delivered = true),
+        Message(from = null, message = "No, it is struck.", time = "2 min. ago", delivered = false),
+        Message(from = "Bob", message = "It is a nipping and an eager air.", time = "1 day ago", delivered = true),
+        Message(from = null, message = "What hour now?", time = "18 hrs. ago", delivered = true),
+        Message(from = "Bob", message = "I think it lacks of twelve.", time = "12 min. ago", delivered = true),
+        Message(from = null, message = "No, it is struck.", time = "2 min. ago", delivered = false),
+        Message(
+            from = "Bob",
+            message = "Indeed? I heard it not: then it draws near the season Wherein the spirit held his wont to walk. A flourish of trumpets, and ordnance shot off, within. What does this mean, my lord?",
+            time = "2 min. ago",
+            delivered = false
+        )
+    )
+    val msg3: List<Message> = listOf<Message>(
+        Message(
+            from = null,
+            message = "Give him this money and these notes, Reynaldo.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(from = "Bob", message = "I will, my lord.", time = "1 day ago", delivered = true),
+        Message(
+            from = null,
+            message = "You shall do marvellous wisely, good Reynaldo,Before you visit him, to make inquireOf his behavior.",
+            time = "18 hrs. ago",
+            delivered = true
+        ),
+        Message(from = "Bob", message = "My lord, I did intend it.", time = "12 min. ago", delivered = true),
+        Message(
+            from = null,
+            message = "Marry, well said; very well said. Look you, sir,Inquire me first what Danskers are in Paris;And how, and who, what means, and where they keep,What company, at what expense; and findingBy this encompassment and drift of questionThat they do know my son, come you more nearerThan your particular demands will touch it:Take you, as ’twere, some distant knowledge of him;As thus, ‘I know his father and his friends,And in part him: ‘ do you mark this, Reynaldo?",
+            time = "2 min. ago",
+            delivered = false
+        ),
+    )
+    val msg4: List<Message> = listOf<Message>(
+        Message(
+            from = "Bob",
+            message = "So art thou to revenge, when thou shalt hear.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(from = null, message = "What?", time = "1 day ago", delivered = true),
+        Message(
+            from = "Bob",
+            message = "I am your father’s spirit, doomed for a certain time to walk the night, and for the day to burn in fires, till the foul crimes done during my lifetime have been burnt and purged away. But that I am forbidden to tell the secrets of my prison-house I could tell a tale whose lightest word would shrivel up your soul, freeze your young blood, make your eyes start from their sockets and your hair stand up on end like the quills of a frightened porcupine. But this eternal torture is not for ears of flesh and blood. Listen, oh listen! If you ever loved your dear father ….",
+            time = "18 hrs. ago",
+            delivered = true
+        ),
+        Message(from = null, message = "Oh God!", time = "12 min. ago", delivered = true),
+    )
+    val msg5: List<Message> = listOf<Message>(
+        Message(
+            from = null,
+            message = "Here's a knocking indeed! If a man were porter of hell-gate, he should have old turning the key.  Knocking within Knock, knock, knock! Who's there, i' the name of Beelzebub? Here's a farmer, that hanged himself on the expectation of plenty: come in time; have napkins enow about you; here you'll sweat for't.",
+            time = "2 days ago",
+            delivered = true
+        ),
+        Message(
+            from = null,
+            message = "Knock, knock! Who's there, in the other devil's name? Faith, here's an equivocator, that could swear in both the scales against either scale; who committed treason enough for God's sake, yet could not equivocate to heaven: O, come in, equivocator.",
+            time = "1 day ago",
+            delivered = true
+        ),
+    )
+    val contacts = listOf(
+        Contact(name = "Alice", online = true, profile_pic = "p1.png", last_heard = "now", privateMessages = msg2),
+        Contact(
+            name = "Bob",
+            online = false,
+            profile_pic = "p2.png",
+            last_heard = "22 min. ago",
+            privateMessages = msg1
+        ),
+        Contact(
+            name = "Carl",
+            online = true,
+            profile_pic = "p3.png",
+            last_heard = "2 hr. ago ",
+            privateMessages = msg3
+        ),
+        Contact(name = "Dan", online = false, profile_pic = "p4.png", last_heard = "1 day ago", privateMessages = msg4),
+        Contact(
+            name = "Eve",
+            online = false,
+            profile_pic = "p5.png",
+            last_heard = "3 days ago",
+            privateMessages = msg5
+        ),
+        Contact(
+            name = "Fred",
+            online = false,
+            profile_pic = "p2.png",
+            last_heard = "22 min. ago",
+            privateMessages = msg1
+        ),
+        Contact(
+            name = "Greg",
+            online = true,
+            profile_pic = "p3.png",
+            last_heard = "2 hr. ago ",
+            privateMessages = msg3
+        ),
+        Contact(
+            name = "Harold",
+            online = false,
+            profile_pic = "p4.png",
+            last_heard = "1 day ago",
+            privateMessages = msg4
+        ),
+        Contact(
+            name = "Irene",
+            online = false,
+            profile_pic = "p5.png",
+            last_heard = "3 days ago",
+            privateMessages = msg5
+        ),
+        Contact(
+            name = "Jeanne",
+            online = false,
+            profile_pic = "p2.png",
+            last_heard = "22 min. ago",
+            privateMessages = msg1
+        ),
+        Contact(
+            name = "Karl",
+            online = true,
+            profile_pic = "p3.png",
+            last_heard = "2 hr. ago ",
+            privateMessages = msg3
+        ),
+        Contact(
+            name = "Lorn",
+            online = false,
+            profile_pic = "p4.png",
+            last_heard = "1 day ago",
+            privateMessages = msg4
+        ),
+        Contact(
+            name = "Meg",
+            online = false,
+            profile_pic = "p5.png",
+            last_heard = "3 days ago",
+            privateMessages = msg5
+        ),
+        Contact(
+            name = "Nile",
+            online = false,
+            profile_pic = "p2.png",
+            last_heard = "22 min. ago",
+            privateMessages = msg1
+        ),
+        Contact(
+            name = "Oscar",
+            online = true,
+            profile_pic = "p3.png",
+            last_heard = "2 hr. ago ",
+            privateMessages = msg3
+        ),
+        Contact(
+            name = "Paul",
+            online = false,
+            profile_pic = "p4.png",
+            last_heard = "1 day ago",
+            privateMessages = msg4
+        ),
+        Contact(name = "Qi", online = false, profile_pic = "p5.png", last_heard = "3 days ago", privateMessages = msg5),
+    )
+}
+
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/data/ContentType.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/ContentType.kt
new file mode 100644
index 0000000000..e29adb5f0b
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/ContentType.kt
@@ -0,0 +1,16 @@
+package org.briarproject.briar.desktop.paul.data
+
+import org.briarproject.briar.desktop.paul.model.ContentType
+
+object ContentTypeList {
+    val types = listOf(
+        ContentType(id = -1, name = "Profile"),
+        ContentType(id = 0, name = "Contacts"),
+        ContentType(id = 1, name = "Private Groups"),
+        ContentType(id = 2, name = "Forums"),
+        ContentType(id = 3, name = "Blogs"),
+        ContentType(id = 4, name = "Transports"),
+        ContentType(id = 5, name = "Settings"),
+        ContentType(id = 6, name = "Sign Out")
+    )
+}
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/data/OptionType.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/OptionType.kt
new file mode 100644
index 0000000000..5dbb5d8e4c
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/data/OptionType.kt
@@ -0,0 +1,14 @@
+package org.briarproject.briar.desktop.paul.data
+
+import org.briarproject.briar.desktop.paul.model.OptionType
+
+object OptionTypeList {
+    val msgTypes = listOf(
+        OptionType(name = "Alice", unread = 2, online = true),
+        OptionType(name = "Bob", unread = 0, online = true),
+        OptionType(name = "Carl", unread = 0, online = false),
+        OptionType(name = "Dan", unread = 1, online = false),
+        OptionType(name = "Eve", unread = 0, online = false),
+    )
+}
+
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Contact.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Contact.kt
new file mode 100644
index 0000000000..22085dff5b
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Contact.kt
@@ -0,0 +1,9 @@
+package org.briarproject.briar.desktop.paul.model
+
+data class Contact(
+    val name: String,
+    val online: Boolean,
+    val profile_pic: String,
+    val last_heard: String,
+    val privateMessages: List<Message>
+)
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/model/ContentType.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/ContentType.kt
new file mode 100644
index 0000000000..0db88d3071
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/ContentType.kt
@@ -0,0 +1,7 @@
+package org.briarproject.briar.desktop.paul.model
+
+data class ContentType(
+    val id: Int,
+    val name: String,
+    //val icon: Icon,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Message.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Message.kt
new file mode 100644
index 0000000000..a7a79f553f
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/Message.kt
@@ -0,0 +1,9 @@
+package org.briarproject.briar.desktop.paul.model
+
+data class Message(
+    val from: String?,
+    val message: String,
+    val time: String,
+    val delivered: Boolean,
+    //val read: Boolean,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/model/OptionType.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/OptionType.kt
new file mode 100644
index 0000000000..8367e1eb87
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/model/OptionType.kt
@@ -0,0 +1,9 @@
+package org.briarproject.briar.desktop.paul.model
+
+data class OptionType(
+    val name: String,
+    val unread: Int,
+    val online: Boolean
+    //val icon: Icon,
+)
+
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/theme/colors.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/theme/colors.kt
new file mode 100644
index 0000000000..2d443639ee
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/theme/colors.kt
@@ -0,0 +1,32 @@
+package org.briarproject.briar.desktop.paul.theme
+
+import androidx.compose.material.darkColors
+import androidx.compose.ui.graphics.Color
+
+val graySurface = Color(0xFF2A2A2A)
+val lightGray = Color(0xFFD3D3D3)
+val briarGray = Color(0xff222222)
+val briarBlack = Color(0xff1E2228)
+val briarSelBlack = Color(0xff495261)
+val briarDarkGray = Color(0xFF3D4552)
+val darkGray = Color(0xFF151515)
+val divider = Color(0xff35383D)
+val briarBlue = Color(0xFF2D3E50)
+val briarLightBlue = Color(0xFFEBEFF2)
+val briarGreen = Color(0xFF97D323)
+val briarBlueMsg = Color(0xFF1b69b6)
+val briarBlueSpecialMsg = Color(0xFF134a80)
+val briarGrayMsg = Color(0xff3b4047)
+val briarGraySpecialMsg = Color(0xFF212d3b)
+
+val DarkColorPallet = darkColors(
+    primary = Color.White,
+    secondary = graySurface,
+    background = briarLightBlue,
+    surface = briarBlue,
+    onPrimary = Color.White,
+    onSecondary = lightGray,
+    onBackground = Color.White,
+    onSurface = Color.White,
+    error = Color.Red,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarSidebar.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarSidebar.kt
new file mode 100644
index 0000000000..85454f9c57
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarSidebar.kt
@@ -0,0 +1,103 @@
+package org.briarproject.briar.desktop.paul.views
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.background
+import androidx.compose.foundation.border
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material.Icon
+import androidx.compose.material.IconButton
+import androidx.compose.material.Surface
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.*
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.imageFromResource
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.unit.dp
+import org.briarproject.briar.desktop.paul.theme.briarBlack
+import org.briarproject.briar.desktop.paul.theme.briarBlue
+
+@Composable
+fun briarSidebar(UIMode: String, onModeChange: (String) -> Unit) {
+    Surface(modifier = Modifier.width(66.dp).fillMaxHeight(), color = briarBlue) {
+        Column(verticalArrangement = Arrangement.Top) {
+            IconButton(
+                modifier = Modifier.align(Alignment.CenterHorizontally)
+                    .padding(top = 9.dp, bottom = 10.dp), onClick = {}) {
+                Image(
+                    bitmap = imageFromResource("images/profile_images/p0.png"),
+                    "my_profile_image",
+                    modifier = Modifier.size(48.dp).align(Alignment.CenterHorizontally).clip(
+                        CircleShape
+                    ).border(2.dp, color = Color.White, CircleShape)
+                )
+            }
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Contacts",
+                Icons.Filled.Contacts
+            )
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Private Groups",
+                Icons.Filled.Group
+            )
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Forums",
+                Icons.Filled.Forum
+            )
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Blogs",
+                Icons.Filled.ChromeReaderMode
+            )
+        }
+        Column(verticalArrangement = Arrangement.Bottom) {
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Transports",
+                Icons.Filled.WifiTethering
+            )
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Settings",
+                Icons.Filled.Settings
+            )
+            briarSidebarButton(
+                UIMode = UIMode,
+                onModeChange = onModeChange,
+                "Sign Out",
+                Icons.Filled.Logout
+            )
+        }
+    }
+}
+
+@Composable
+fun briarSidebarButton(
+    UIMode: String,
+    onModeChange: (String) -> Unit,
+    thisMode: String,
+    icon: ImageVector
+) {
+    val bg = if (UIMode == thisMode) briarBlack else briarBlue;
+    Column() {
+        IconButton(
+            modifier = Modifier.align(Alignment.CenterHorizontally).background(color = bg)
+                .padding(vertical = 9.dp, horizontal = 12.dp),
+            onClick = { onModeChange(thisMode) }) {
+            Icon(icon, thisMode, tint = Color.White, modifier = Modifier.size(30.dp))
+        }
+    }
+}
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarUIStateManager.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarUIStateManager.kt
new file mode 100644
index 0000000000..a58fa8f036
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/BriarUIStateManager.kt
@@ -0,0 +1,51 @@
+package org.briarproject.briar.desktop.paul.views
+
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import org.briarproject.briar.desktop.paul.data.ContactList
+import org.briarproject.briar.desktop.paul.theme.briarBlack
+
+/*
+ * This is the root of the tree, all state is held here and passed down to stateless composables, which render the UI
+ * Desktop specific kotlin files are found in briarComposeDesktop (possibly briar-compose-desktop project in the future)
+ * Multiplatform, stateless, composable are found in briarCompose (possible briar-compose project in the future)
+ */
+@Composable
+fun briarUIStateManager() {
+    //current selected mode, changed using the sidebar buttons
+    val (UIMode, onModeChange) = remember { mutableStateOf("Contacts") }
+    //current selected contact
+    val (UIContact, onContactSelect) = remember { mutableStateOf(ContactList.contacts[0]) }
+    //current selected private message
+    val (UIPrivateMsg, onPMSelect) = remember { mutableStateOf(0) }
+    //current selected forum
+    val (UIForum, onForumSelect) = remember { mutableStateOf(0) }
+    //current blog state
+    val (UIBlog, onBlogSelect) = remember { mutableStateOf(0) }
+    //current transport state
+    val (UITransports, onTransportSelect) = remember { mutableStateOf(0) }
+    //current settings state
+    val (UISettings, onSettingSelect) = remember { mutableStateOf(0) }
+    //current profile
+    var Profile: String;
+    //Other global state that we need to track should go here also
+    Row() {
+        briarSidebar(UIMode, onModeChange)
+        when (UIMode) {
+            "Contacts" -> privateMessageView(UIContact, onContactSelect)
+            else -> Box(modifier = Modifier.fillMaxSize().background(briarBlack)) {
+                Text("TBD", modifier = Modifier.align(Alignment.Center), color = Color.White)
+            }
+        }
+    }
+
+}
diff --git a/src/main/kotlin/org/briarproject/briar/desktop/paul/views/PrivateMessageView.kt b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/PrivateMessageView.kt
new file mode 100644
index 0000000000..fc8544d5e9
--- /dev/null
+++ b/src/main/kotlin/org/briarproject/briar/desktop/paul/views/PrivateMessageView.kt
@@ -0,0 +1,319 @@
+package org.briarproject.briar.desktop.paul.views
+
+import androidx.compose.foundation.*
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.lazy.LazyColumn
+import androidx.compose.foundation.lazy.items
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material.*
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.*
+import androidx.compose.runtime.*
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.graphics.imageFromResource
+import androidx.compose.ui.text.TextStyle
+import androidx.compose.ui.text.input.TextFieldValue
+import androidx.compose.ui.unit.IntSize
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.sp
+import androidx.compose.ui.window.v1.DialogProperties
+import org.briarproject.briar.desktop.paul.data.ContactList
+import org.briarproject.briar.desktop.paul.model.Contact
+import org.briarproject.briar.desktop.paul.model.Message
+import org.briarproject.briar.desktop.paul.theme.*
+
+
+val HEADER_SIZE = 66.dp;
+
+@Composable
+fun privateMessageView(UIContact: Contact, onContactSelect: (Contact) -> Unit) {
+    //Local State for managing the Add Contact Popup
+    val (AddContactDialog, onCancelAdd) = remember { mutableStateOf(false) }
+    addContactDialog(AddContactDialog, onCancelAdd)
+    Column(modifier = Modifier.fillMaxHeight()) {
+        Row(modifier = Modifier.fillMaxWidth()) {
+            Divider(color = divider, modifier = Modifier.fillMaxHeight().width(1.dp))
+            Column(modifier = Modifier.fillMaxHeight().background(color = briarBlack).width(275.dp)) {
+                Row(
+                    modifier = Modifier.fillMaxWidth().height(HEADER_SIZE).padding(horizontal = 16.dp),
+                    horizontalArrangement = Arrangement.SpaceBetween,
+                ) {
+                    Text(
+                        "Contacts",
+                        fontSize = 24.sp,
+                        color = Color.White,
+                        modifier = Modifier.align(Alignment.CenterVertically)
+                    )
+                    IconButton(
+                        onClick = { onCancelAdd(true) },
+                        modifier = Modifier.align(Alignment.CenterVertically).background(color = briarDarkGray)
+                    ) {
+                        Icon(Icons.Filled.Add, "add contact", tint = Color.White, modifier = Modifier.size(24.dp))
+                    }
+                }
+                Divider(color = divider, thickness = 1.dp, modifier = Modifier.fillMaxWidth())
+                Column(modifier = Modifier.verticalScroll(rememberScrollState())) {
+                    for (c in ContactList.contacts) {
+                        contactCard(c, UIContact, onSel = onContactSelect)
+                    }
+                }
+
+            }
+            Divider(color = divider, modifier = Modifier.fillMaxHeight().width(1.dp))
+            Column(modifier = Modifier.weight(1f).fillMaxHeight().background(color = darkGray)) {
+                drawMessageRow(UIContact)
+            }
+        }
+    }
+}
+
+@Composable
+fun addContactDialog(isVisible: Boolean, onCancel: (Boolean) -> Unit) {
+    if (isVisible) {
+        AlertDialog(
+            onDismissRequest = {
+                onCancel(false)
+            },
+            text = {
+                Column(modifier = Modifier.fillMaxWidth()) {
+                    Row(Modifier.fillMaxWidth().padding(vertical = 16.dp)) {
+                        Text(
+                            text = "Add Contact at a Distance",
+                            fontSize = 24.sp,
+                            color = Color.White,
+                            modifier = Modifier.align(Alignment.CenterVertically)
+                        )
+                    }
+                    Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
+                        Text(
+                            "Contact's Link",
+                            Modifier.width(128.dp).align(Alignment.CenterVertically),
+                            color = lightGray
+                        )
+                        TextField("", onValueChange = {}, modifier = Modifier.fillMaxWidth())
+                    }
+                    Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
+                        Text(
+                            "Contact's Name",
+                            Modifier.width(128.dp).align(Alignment.CenterVertically),
+                            color = lightGray
+                        )
+                        TextField("", onValueChange = {}, modifier = Modifier.fillMaxWidth())
+                    }
+                    Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
+                        Text(
+                            "Your Link",
+                            modifier = Modifier.width(128.dp).align(Alignment.CenterVertically),
+                            color = lightGray
+                        )
+                        TextField(
+                            "briar://ksdjlfgakslhjgaklsjdhglkasjdlk3j12h4lk2j3tkj4",
+                            onValueChange = {},
+                            modifier = Modifier.fillMaxWidth()
+                        );
+                    }
+                }
+            },
+            confirmButton = {
+                TextButton(
+                    onClick = {
+                        onCancel(false)
+                    },
+                    modifier = Modifier.background(briarGreen)
+                ) {
+                    Text("Add")
+                }
+            },
+            dismissButton = {
+                TextButton(
+                    onClick = {
+                        onCancel(false)
+                    }, modifier = Modifier.background(briarBlack)
+                ) {
+                    Text("Cancel")
+                }
+            },
+
+            backgroundColor = briarBlue,
+            contentColor = Color.White,
+            modifier = Modifier.border(1.dp, color = divider),
+            properties = DialogProperties(resizable = false, undecorated = true, size = IntSize(600, 300))
+        )
+    }
+}
+
+@Composable
+fun contactCard(contact: Contact, selContact: Contact, onSel: (Contact) -> Unit) {
+    var bgColor = briarBlack
+    if (selContact.name == contact.name) {
+        bgColor = darkGray
+    }
+    Row(
+        modifier = Modifier.fillMaxWidth().height(HEADER_SIZE).background(bgColor)
+            .clickable(onClick = { onSel(contact) }), horizontalArrangement = Arrangement.SpaceBetween
+    ) {
+        Row(modifier = Modifier.align(Alignment.CenterVertically).padding(horizontal = 16.dp)) {
+            Image(
+                bitmap = imageFromResource("images/profile_images/" + contact.profile_pic),
+                "image",
+                modifier = Modifier.size(40.dp).align(Alignment.CenterVertically).clip(
+                    CircleShape
+                ).border(2.dp, color = Color.White, CircleShape)
+            )
+            Column(modifier = Modifier.align(Alignment.CenterVertically).padding(start = 12.dp)) {
+                Text(
+                    contact.name,
+                    fontSize = 14.sp,
+                    color = Color.White,
+                    modifier = Modifier.align(Alignment.Start).padding(bottom = 2.dp)
+                )
+                Text(
+                    contact.last_heard,
+                    fontSize = 10.sp,
+                    color = Color.LightGray,
+                    modifier = Modifier.align(Alignment.Start)
+                )
+            }
+        }
+        androidx.compose.foundation.Canvas(
+            modifier = Modifier.padding(horizontal = 29.dp).size(22.dp).align(Alignment.CenterVertically), onDraw = {
+                val size = 16.dp.toPx()
+                drawCircle(
+                    color = Color.White,
+                    radius = size / 2f
+                )
+                if (contact.online) {
+                    drawCircle(
+                        color = briarGreen,
+                        radius = 14.dp.toPx() / 2f
+                    )
+                } else {
+                    drawCircle(
+                        color = briarBlack,
+                        radius = 14.dp.toPx() / 2f
+                    )
+                }
+            })
+    }
+
+    Divider(color = divider, thickness = 1.dp, modifier = Modifier.fillMaxWidth())
+}
+
+@Composable
+fun textBubble(m: Message) {
+    Column(Modifier.fillMaxWidth()) {
+        if (m.from == null) {
+            Column(Modifier.fillMaxWidth(fraction = 0.9f).align(Alignment.End)) {
+                Column(Modifier.background(briarBlueMsg).padding(8.dp).align(Alignment.End)) {
+                    Text(m.message, fontSize = 14.sp, color = Color.White, modifier = Modifier.align(Alignment.Start))
+                    Row(modifier = Modifier.padding(top = 4.dp)) {
+                        Text(m.time, Modifier.padding(end = 4.dp), fontSize = 10.sp, color = Color.LightGray)
+                        if (m.delivered) {
+                            Icon(
+                                Icons.Filled.Check,
+                                "sent",
+                                tint = Color.LightGray,
+                                modifier = Modifier.size(10.dp).align(Alignment.CenterVertically)
+                            )
+                        } else {
+                            Icon(
+                                Icons.Filled.Send,
+                                "sending",
+                                tint = Color.LightGray,
+                                modifier = Modifier.size(10.dp).align(Alignment.CenterVertically)
+                            )
+                        }
+                    }
+                }
+            }
+        } else {
+            Column(Modifier.fillMaxWidth(fraction = 0.9f).align(Alignment.Start)) {
+                Column(Modifier.background(briarGrayMsg).padding(8.dp).align(Alignment.Start)) {
+                    Text(m.message, fontSize = 14.sp, color = Color.White, modifier = Modifier.align(Alignment.Start))
+                    Row(modifier = Modifier.padding(top = 4.dp)) {
+                        Text(m.time, Modifier.padding(end = 4.dp), fontSize = 10.sp, color = Color.LightGray)
+                        if (m.delivered) {
+                            Icon(
+                                Icons.Filled.Check,
+                                "sent",
+                                tint = Color.LightGray,
+                                modifier = Modifier.size(10.dp).align(Alignment.CenterVertically)
+                            )
+                        } else {
+                            Icon(
+                                Icons.Filled.Send,
+                                "sending",
+                                tint = Color.LightGray,
+                                modifier = Modifier.size(10.dp).align(Alignment.CenterVertically)
+                            )
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+@Composable
+fun drawTextBubbles(msgList: List<Message>) {
+    LazyColumn(
+        Modifier.fillMaxWidth().padding(horizontal = 8.dp),
+        verticalArrangement = Arrangement.spacedBy(8.dp),
+        reverseLayout = true,
+        contentPadding = PaddingValues(vertical = 8.dp)
+    ) {
+        items(msgList) { m ->
+            textBubble(m)
+        }
+    }
+}
+
+@Composable
+fun drawMessageRow(UIContact: Contact) {
+    Box(Modifier.fillMaxHeight()) {
+        Box(modifier = Modifier.fillMaxWidth().height(HEADER_SIZE + 1.dp)) {
+            Row(modifier = Modifier.align(Alignment.Center)) {
+                Image(
+                    bitmap = imageFromResource("images/profile_images/" + UIContact.profile_pic),
+                    "sel_contact_prof",
+                    modifier = Modifier.size(36.dp).align(
+                        Alignment.CenterVertically
+                    ).clip(
+                        CircleShape
+                    ).border(2.dp, color = Color.White, CircleShape)
+                )
+                Text(
+                    UIContact.name,
+                    color = Color.White,
+                    modifier = Modifier.align(Alignment.CenterVertically).padding(start = 12.dp),
+                    fontSize = 24.sp
+                )
+            }
+            IconButton(onClick = {}, modifier = Modifier.align(Alignment.CenterEnd).padding(end = 16.dp)) {
+                Icon(Icons.Filled.MoreVert, "contact info", tint = Color.White, modifier = Modifier.size(24.dp))
+            }
+            Divider(color = divider, thickness = 1.dp, modifier = Modifier.fillMaxWidth().align(Alignment.BottomCenter))
+        }
+        Box(Modifier.padding(top = HEADER_SIZE + 1.dp, bottom = HEADER_SIZE)) {
+            drawTextBubbles(UIContact.privateMessages)
+        }
+        var text by remember { mutableStateOf(TextFieldValue("")) }
+        Box(Modifier.align(Alignment.BottomCenter).background(darkGray)) {
+            OutlinedTextField(
+                value = text,
+                trailingIcon = { Icon(Icons.Filled.Send, "send message", tint = briarGreen) },
+                leadingIcon = { Icon(Icons.Filled.AddCircle, contentDescription = "add file") },
+                modifier = Modifier.padding(start = 8.dp, end = 8.dp, bottom = 8.dp).fillMaxWidth(),
+                label = { Text(text = "Message") },
+                textStyle = TextStyle(color = Color.White),
+                placeholder = { Text(text = "Your message to " + UIContact.name) },
+                onValueChange = {
+                    text = it
+                },
+            )
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/resources/images/profile_images/p0.png b/src/main/resources/images/profile_images/p0.png
new file mode 100644
index 0000000000000000000000000000000000000000..8c67a3c592c8267f56a4c810cb2d561c88d05e18
GIT binary patch
literal 45426
zcmeAS@N?(olHy`uVBq!ia0y~yV7LUr9Lx+13>@xx1q=+#3;{kNuK)l4zp=1~VHAvp
zz=#Zi$EIfr85kHDN`m}?|NkG6K>+u(R{Hg03=C@(JzX3_DsC}~t$hh9H{jBvjL{Gn
z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!3hDA;3r#fX4!u6jkhDgqenqrkhQ4vxtFi
zHqp(ZQ7_>NYJ5o>Du+ueY2r}B@KU6ih)XqID<G1%w2~$cF$+IQnu)kn<F^AWi%TnM
z;$Wi)5Tu!iOEm#YK+?Fhk|qu^i4Z2uL|m!~*}}j;zjBCvHsJ~l(!_}fyHPLU3Q{5h
z50_Tb#EGzIG?s7$DG`B(ODk#OL|8N$OSpoRh`__8l{9f8EE<g^TtP}i;Nj9rnm7>_
zjm8qLASEL3aA_q?oCu3XV+mJ~5)pW~w2~%HghivVgeypi2s~U`NfRf+qS08w6{JK2
z9xkn<i4$SbXe{9hQX&EmmsZlmiLhuimT(0r5rKzGD{10HSTq_-xPp|3z{91LG;ty<
z8jU4fK}tm6;nGT)I1v^N$5<l9+l18+5!8eY8C)txy)?Mu1G{TRV+nh>3@*{pSQ=dM
zf!#Huv4lNb2AAk)EDf&s!0wvSSi&AIgG+QYmIhaRV0X=EEMX6q!6iBxOM@#uu)Ah7
zmavD*;1V5;rNI>+*j+OkOW4C@aEXq_(%^~@?5-J&CG6ocxI{-|X>i2{cGrx?683Nz
zT%x0~MBDhFPWTQcQ;3;<CL&Bny@Vr>s1q=wv4kUd2UWlfD#wf_yrGa}Mq_C-mXOl`
zuFyadM^=u5jieeE6NgS@VO&~~#gWzHU?VHX!N#EzSr~^-WMO3GIM~R_aj|h|MHa@T
z6-gXfISw|GYFtblI+2BOX+;)CR*!>?tQ-d$hfZW+96FJOk(J|MBP++n#-SBi7?)Ng
zab)E<*hs2zF>&Zb7RIF&SsYnC4mPrK9Bdpqk%e*SL>5L?j)RS?92XmhR%BsZT9L$&
zmE&L|sm8^`p%YmcmsVtPWc4`M$jWiBap*)A#-S5g7+E<EHnMVDY#dsVg>h*`5=T~!
zgN>vb7ZZn0WMN!dk;ReK<6t8z$HB&-6ImFCPGn(Z<v7^L%5kxAXhjyrr4>mWSvd|i
zl4@K`96FJOacM;sM^=x6jjS988;4G0VH`S<g^`uxU?VHX#m1o(Ss0gABynWrIM_(4
zaWQe|L>9)S6<HivJq|XqavW?NI+2BO=tLGqR*r*>tQ;2`hgM`^Tw0ODk(J|MBdNy4
z#Gw;e7?)OLab)#4*vQIpuyN=_7RI3ySr}P44mPrKTx=X#k%e(-MG{9=j)RS)8W$6X
zPGn(RT9L(()#G3zE62gcp%YmchfZW+WaT*6$jWiCacD&r#-$ZW99cOIHj-*wOdL9q
zg>h*`7DrZ(gN>{l2OEb@WMLdSk%f_!<6t8z$Hm5>6<HXURwQv`<v7?#s&O%K=tLIA
zr4?BmSv?LmvT_`396FJOap*)AMpll4jjS9O8;4e8VO&~~#F3TbU?Zu<#l)c#Ss0gA
zWN~EmIM~R_aj<ddL>9)O6ImEpISw|ma$Ia2T9JiuX+;u8R*r*>q#73!hfZW+Tw0OE
zk=5g1BP++j#-S5g7>7<|VPxev*vQIpv2kcc7RIF&NgP=@4mOf%TudA~k%e(-MHWX^
zkAsb@90wbRPGn&mI+2BumE&L|E62sgp%qyemsTWkWaT*6NUCu$ap*)A#-$Zm99caM
zHnMUYY#cg~g>mRa7DiT%gN>{l7aNCGWMN!dk;IXe<6tAH#>K>;6ImFSR%CHx^*Gqb
z%5ku9=tLIAp%YmcSvd|ivT|H(99ofuacM;oM^=u5jieeE6NgS@VO&~~#gWzHU?VHX
z!N#EzSr~^-WMO3GIM~R_aj|h|MHa@T6-gXfISw|GYFtblI+2BOX+;)CR*!>?tQ-d$
zhfZW+96FJOk(J|MBP++n#-SBi7?)Ngab)E<*hs2zF>&Zb7RIF&SsYnC4mPrK9Bdpq
zk%e*SL>5L?j)RS?92XmhR%BsZT9L$&mE&L|sm8^`p%YmcmsVtPWc4`M$jWiBap*)A
z#-S5g7+E<EHnMVDY#dsVg>h*`5=T~!gN>vb7ZZn0WMN!dk;ReK<6t8z$HB&-6ImFC
zPGn(Z<v7^L%5kxAXhjyrr4>mWSvd|il4@K`96FJOacM;sM^=x6jjS988;4G0VH`S<
zg^`uxU?VHX#m1o(Ss0gABynWrIM_(4aWQe|L>9)S6<HivJq|XqavW?NI+2BO=tLGq
zR*r*>tQ;2`hgM`^Tw0ODk(J|MBdNy4#Gw;e7?)OLab)#4*vQIpuyN=_7RI3ySr}P4
z4mPrKTx=X#k%e(-MG{9=j)RS)8W$6XPGn(RT9L(()#G3zE62gcp%YmchfZW+WaT*6
z$jWiCacD&r#-$ZW99cOIHj-*wOdL9qg>h*`7DrZ(gN>{l2OEb@WMLdSk%f_!<6t8z
z$Hm5>6<HXURwQv`<v7?#s&O%K=tLIAr4?BmSv?LmvT_`396FJOap*)AMpll4jjS9O
z8;4e8VO&~~#F3TbU?Zu<#l)c#Ss0gAWN~EmIM~R_aj<ddL>9)O6ImEpISw|ma$Ia2
zT9JiuX+;u8R*r*>q#73!hfZW+Tw0OEk=5g1BP++j#-S5g7>7<|VPxev*vQIpv2kcc
z7RIF&NgP=@4mOf%TudA~k%e(-MHWX^kAsb@90wbRPGn&mI+2BumE&L|E2n^s!*uEk
zQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{YAtwNl^hI7}qb
zT@)zC;Q;CjQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{YAt
zwNl^hI7}qbT@)zC;Q;CjQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{YAtwNl^hI7}qbT@)zC
z;Q;CjQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{YAtwNl^h
zI7}qbT@)zC;Q;CjQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{YAtwNl^hI7}qbT@)zC;Q;Cj
zQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{YAtwNl^hI7}qb
zT@)zC;Q;CjQ{YAtwNl^hI7}qbT@)zC;Q;CjQ{cu?t)n3@8UmvsFd71*Aut*OqaiRF
q0;3@?8UmvsFd71*Aut*OgChh!YB~MiTQp-c$Tgm>elF{r5}E*)!DHkA

literal 0
HcmV?d00001

diff --git a/src/main/resources/images/profile_images/p1.png b/src/main/resources/images/profile_images/p1.png
new file mode 100644
index 0000000000000000000000000000000000000000..50155c8a1ebc3513e3b6e3cc2936881b594f92f4
GIT binary patch
literal 2804
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

literal 0
HcmV?d00001

diff --git a/src/main/resources/images/profile_images/p2.png b/src/main/resources/images/profile_images/p2.png
new file mode 100644
index 0000000000000000000000000000000000000000..8ff9a6e10f151d8e9913a968a535cf7b3e542c0f
GIT binary patch
literal 45426
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

literal 0
HcmV?d00001

diff --git a/src/main/resources/images/profile_images/p3.png b/src/main/resources/images/profile_images/p3.png
new file mode 100644
index 0000000000000000000000000000000000000000..4b8509e1e21afe1863ad0d35395ef11cdd9113b4
GIT binary patch
literal 45426
zcmeAS@N?(olHy`uVBq!ia0y~yV7LUr9Lx+13>@xx1q=+#3;{kNuK)l4@7Z>PVHAvp
zz=#Y1kqoIx3=E76B|(0{|NoE3Ab@*XEB*R028OkYo-U3d6}K40*1iOl8*u4S#%KtP
zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjD`T75MU$>@aTp~5jKPorW6lN9a9*nW6WSO
zWz<W!Qq5>A;RqS(1k7l{!x6lLDqsecV@4C+P)IVPu{0V>$Y}sqXdsCrE62e`QjLp=
zLnpE@F0IJo$m(&hk(J|M<IssLj6)}~FtTzSY-HuQ*f_Kz3**v?B#x{c2OCK>E+!70
z$ild^B8wxd$H7Kcj)RRuC$caOoyfw-%5kufmE&UL(26XKODmE%vT_`3B-OZ>ICLTl
z<I;*Oj;tOB8(BFHHV&Q0!Z>sy3nMGX!A4e&i;Y7ovM?^KNaD!Kaj=n8<6`2_i7bpu
zE3!DUdK_$I<v7?lbRrAm(1|RJtQ-d$Svf8?4z0+-xU?dPBP++jMpBK7i9;u{FfOgg
z;>hZ8u#uJHVB^q<EQ~`ZvM{o89BgFexY#(fA`9cviX@J#90waoH7+I&oyfwtv?7Zm
ztH;4cR*r*>LnpE@4xPxt$jWiBk(J|O<IsvMj7uw$II?maY$VmVm^gGI3**v?ERL)m
z2OC*A4mJ**$ig^uA`2rc$H7Kcj*E>$E3z;ytw`d?%5kufRO4de(1|RJODnQCvU(hB
zWaT*6ICLTl<IssLjI1078(BFnHV&=G!nm{|i6bk=!A4Szi-|)gvM?^K$l}QAaj=n<
z<6z^^i7bpmC$ccIavW@A<+#{5v?2@R(uyRGtQ-d$Ni{Ae4xPxtxU?dRBdf>3Mpll4
zjYB80Fb<u_!pO>Tu#uJHV&l+?ER0Jlk~p$*9Bd@jxR^L}A`9cviY$(-9tRs)ISw`s
zoyfvCbRr8QE62e`R*s8}Lo2c{F0Dx7$jWiBkyPVi;?RjKj7#gN_-F`>hQMeDjE2By
z2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1J
zhQMeD45<)6o(LTRY+}N82zUe8iKAXZ4voRe9*w2J8Z*f58jU67&={=j(O4R+F@x-`
z(O5zbjls$ujitdFGsx~5jV0vJ7_98kSQ@M`gY2%+SV9hs!O9+urNJ6A$nF}ACFIZ;
ztnATP8muvc?5@#RLJp0=${vlS!5TBj?i!6H<j@$b?9o^ntTBV^t`Qnb#CUsD&1eXW
zhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kin
zXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeD
zjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mkz-S1JhQMeDjE2By2#kinXb6mk
sz-S1JhQMeDjE2By2#kinXb23>5J*o`^DImB&H}m4)78&qol`;+071k=2mk;8

literal 0
HcmV?d00001

diff --git a/src/main/resources/images/profile_images/p4.png b/src/main/resources/images/profile_images/p4.png
new file mode 100644
index 0000000000000000000000000000000000000000..96ed7fbc717af1d66c71fd5b9376b6a32dfc6e5b
GIT binary patch
literal 45426
zcmeAS@N?(olHy`uVBq!ia0y~yV7LUr9Lx+13>@xx1q=+#3;{kNuK)l4@42ysVHAvp
zz=#Zimyu8685kHDN`m}?|NkG6K>+u(R{Hg03=C@(JzX3_DsC}~t$hh9H{jBvjL{Gn
z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!3iMhX5mCKyx=x*#g2oVx+Q-G&gS4OEeE+
zDp)WYOH>F%nj0}1OEeE+Dp)WYOH>F%nj0}1OEeE+Dp)WYOH>F%nj0}1OEeE+Dp)WY
zOH>F%nj0}1OEeE+Dp)WYOH>F%nj0}1OEeE+Dp)WYOH>F%nj0}1OEeE+Dp)WYOH>F%
znj0}1OEeE+Dp)WYOH>F%nj0~wVu=XH5TS&KFeAbgB9ste5d#s%5TS$!n}{%l2qi>V
zH0mW>;YdW_;nGT)I1v_&#uBa|B_i-}X(dgZ2#ZEz30II35qP+?k|s`sMWeBVD@ch5
zJX~5y6DPu=(OAM2q(lTBF0G`A6JgP4Ea3`LA_5PWR?@_YuxK=va0Mw5frm>gY2rj!
zG#X2|f|Q8B!=;rpaUv`ljU`+`N<`q{(n^{*5f+Wc60RU6BJgl&B~6?Ni$-G!SCA4B
zc(}BZCQgJ!qp^f5NQnqMTv|yJC&Hr9Si%*gL<Al#t)z()VbN$T;R;eB0uPr~(!`0d
zXf&2^1t}4Mhf6DI;zU?98cVo>l!(B?rIj>sA}kt?u|$NoNef2`R1@JADk-7Bk)&y*
zl6#3ThBS9kpqdD`P)P{|jwDShmE22&F{HVR0@Xygg-S{&a3pD3spMWFj3Lck6sRV`
zEmTrMfg?%NN+tIaVGL>RqChnfZlRJA3LHtARw}ud2xCZd7X_+`a0```P~b??v{K2v
zL>NPwyC_gigj=YjgaSvBrj<(WCBhie+(m(EBHThHB@{T4G_6!}FA>I&<}M0U6X6yr
zDWSlTq-mv+dx<cHG<Q*;nh3X0NeKmxBuy)o+)IQpq`8X%)kL_3N=hhjBxzcy<X$3-
zA<bPBs3yWKR8m5LBT3UrCHE3x3~BD7Ks6C=p^_2`97&p1D!G>kV@Pus1*(Z~3zd{m
z;7HQ6QpvqU7(<%7C{Rs=Td1Uj0!Najl}hd<!Wh!rMS*G}+(IQK6gZMJtyFR^5yp__
zE(%l=;T9?>p}>)(X{C~Ti7<vVcTu342)B$X84ZEa5Eu=C(GVC7fzc2c4S~@R7!85Z
z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!85Z5Eu=CkrDz#%)Sy4
z6x1<=2#bhOLLJ9Y#}s1RON1KgIEFf=5aC>6lu*Yp)G>t^_Y$FoI*y@^DMUDz7$wwk
z40TK)#=S(Sp^jsyV+s+@B}NH#977#bh;c6wYN+EF>X<@=bBR$x9mi0|6k^;<gc|BN
zhB~GY;ap;rP{%RUF@+fS5}}4Vj-iezL^ziiCDd^Ybxa|~y+o*?j$^1}3K7mFMhSHs
zLmg9yaW4^SsN)#wm_meeiBUow$56)<V%$rF8tOQPI;IfeTw;_^$1&6~g&6k|p@uq+
zp^hm;IF}eD)Nu@TOd-a-M5v*TW2j>a5zZw>33VJp9aD&LFA-{};~46gLWFaPQ9>QZ
zP{$Nv+)IQS>NtivrV!y=Vw6zFG1M`I821vPhB}U+jwwVqml!3~aSU}#A;!H#sG*Ky
zsACEd&Lu_(bsR$-Q;2ad5o)O880wfpgmZ~eLLJ9Y#}s1RON1KgIEFf=5aHZWC8HrQ
z8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*O0~i7YDf+kXYi>3GIl<G_&t;uc
GLK6UAC{OkP

literal 0
HcmV?d00001

diff --git a/src/main/resources/images/profile_images/p5.png b/src/main/resources/images/profile_images/p5.png
new file mode 100644
index 0000000000000000000000000000000000000000..72348d6d73b3a8cb15aa7f1269e5e980256c7388
GIT binary patch
literal 45426
zcmeAS@N?(olHy`uVBq!ia0y~yV7LUr9Lx+13>@xx1q=+#3;{kNuK)l4pWSnVVHAvp
zz=#Y1shz8;85kHDN`m}?|NkG6K>+u(R{Hg03=C@(JzX3_DsC}~t$hh9H{jBvjL{Gn
z4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R7!3hDA;3r#fX4!u6jkhDgqenqrkhQ4vxtFi
zHqp(ZQ7_>NYJ5o>Du+ueY2r}B@KU6ih)XqID<G1%w2~$cF$+IQnu)kn<F^AWi%TnM
z;$Wi)5Tu!iOEm#YK+?Fhk|qu^i4Z2uL|m!~*}}j;zjBCvHsJ~l(!_}fyHPLU3Q{5h
z50_Tb#EGzIG?s7$DG`B(ODk#OL|8N$OSpoRh`__8l{9f8EE<g^TtP}i;Nj9rnm7>_
zjm8qLASEL3aA_q?oCu3XV+mJ~5)pW~w2~%HghivVgeypi2s~U`NfRf+qS08w6{JK2
z9xkn<i4$SbXe{9hQX&EmmsZlmiLhuimT(0r5rKzGD{10HSTq_-xPp|3z{91LG;ty<
z8jU4fK}tm6;nGT)I1v^N$5<l5+eCyT-Ap0EB4U(`dI?7;Q72$<7*47%bsR$-Q%H3?
z4)xS=40TMw;Y3n}spA;xm_n-Caj2(`W2j>a4kwZ-OdZEi#}rcCjzc|l977#ba5#}v
zVd^-BI;N27b{y)d;~46gg2RcV3RA~1)G>urx8qPx9mi0|6dX<@RhT-Cp^hn}x*dml
z>Ntivrr>ZQslwE840TK))$KUcQ^zsXF$IScNfoA!W2j>ascy%io;r@9jwv{tNUAV(
z977#bNOe07_0(|;bxgtGL{f#R;~46gLaN(wsHcu&sACEaCz2{m9mi0|6jI%eLp^mI
zLmg9aIFVFg>NtivrjY7(9O|j#80wgU!-=E{Q^zsXF@;pO<4{i>$56)<98M%vm^zN3
zjwz(N9fx}AIEFf=;BX?T!qjmLbxa}E?Ksp^$1&6~1&0$!6{e13sACGLZpWdXI*y@^
zDL9;nB1}J<P^`tup^{suWDHg(k}60gw@}F#QeBT#J(b)-C1bEUkyJq{xrIu`km`D@
z>Z#-wDj9>-iKGfr$t_eehE&&MRZk_iP{|mqP9#;3N^YT&F{HX4t9mNAg-XU?bt0*P
zRB{WIj3L$aSk+U>EmSfFs}o5Tq>@{xWDKdU$Eu!6ZlRJfSe;0!AeG!gC1Xf+Jy!Kp
zatoD=!Rka(1*zl~Dj7qn>#?e*l3S=`3|1$SDo7=_P{|llU5`~gmE1xlW3W1rR6#1a
zg-XVd>Uyl|spJ+a8H3e{qzY2WEmSgwRM%rwPbIfd$r!9oBvp_~ZlRJfq`DrfdMdev
zO2%MyBB_E@atoD=A=UL*)l<nWR5Avu6G;`Ml3S=`45_Zis-8-2p^`CJok*%6mE1xl
zV@P#9R`pbJ3zdw)>O@inspJ+a8AGb;v8tz%Tc~6VRwt4wNF}#W$rw^yk5xUD+(Lvg
zL@2@PLR3K_Od&!Es+rh%L>NPa66|K9h!SB65lT>u#K9rL7$TJ5FdSK!2vdkqf@~r#
zHW9`Up#+!dNa948LWB||1938mFop;vIE_b05Mc@tN)YDZW)Wcw5lV2I50@dr6e5(s
zjl;tr!Wbfy;IRNEMT99tD1n)Vk0!zxB9!2>0V+p?DMToN8ito5!Wbfy;I#rGNrWjx
zD1n%TpCrN<B9!2_11w8~DMTm%8%2O1!Wbfy5U>O!O@t{#C;^#72oqrp5lRTzGI|Cw
z?m#3W?1tmnDYyfK6d57{j}+r@t0lss(OAM2d_)8uF0G`A6JgP4Ea3`LA_5PWR?@_Y
zuxK=va0Mw5frm>gY2rj!G#X2|f|Q8B!=;rpaUv`ljU`+`N<`q{(n^{*5f+Wc60RU6
zBJgl&B~6?Ni$-G!SCA4Bc(}BZCQgJ!qp^f5NQnqMTv|yJC&Hr9Si%*gL<Al#t)z()
zVbN$T;R;eB0uPr~(!`0dXf&2^1t}4Mhf6DI;zU?98cVo>l!(B?rIj>sA}kt>C0s#D
zMBw4lN}4zk7LCRdt{^2M@Nj7*O`HgeMq>$AkP;DixU`ZcPJ~6Hv4kr~i3mJgT1gWp
z!lKbw!WE=M1RgG}q=^$@(P%8;3Q{5h50_Tb#EGzIG?s7$DG`B(ODk#OL|8N$OSpoR
zh`__8l{9f8EE<g^TtP}i;Nj9rnm7>_jm8qLASEL3aA_q?oCu3XV+mJ~5)pW~w2~%H
zghivVgeypi2s~U`NfRf+qS08w6{JK29xkn<i4$SbXe{9hQX&EmmsZlmiLhuimT(0r
z5rKzGD{10HSTr1Ci5PE>su>M|(GVC7fzc2c4S~@R7!85Z5Eu=C(GVC7fzc2c4S~@R
apiKzKtNKjL$bQHIGTqbF&t;ucLK6VyA8Qr>

literal 0
HcmV?d00001

-- 
GitLab