Browse Source

updated UI

master
Rohan Sircar 4 years ago
parent
commit
640b2507eb
  1. 12
      build.sbt
  2. 61
      src/main/resources/fxml/Chat.fxml
  3. 13
      src/main/resources/fxml/Login.fxml
  4. 54
      src/main/resources/fxml/MainView.fxml
  5. 29
      src/main/resources/fxml/default.css
  6. 173
      src/main/resources/styles/chat.css
  7. 85
      src/main/resources/styles/default.css
  8. 5
      src/main/resources/styles/login.css
  9. 57
      src/main/scala/wow/doge/chatto/ApplicationController.scala
  10. 114
      src/main/scala/wow/doge/chatto/control/JFXSmoothScroll.java
  11. 10
      src/main/scala/wow/doge/chatto/control/MessageBox.scala
  12. 5
      src/main/scala/wow/doge/chatto/control/UserBox2.scala
  13. 388
      src/main/scala/wow/doge/chatto/controller/ChatController.scala
  14. 15
      src/main/scala/wow/doge/chatto/controller/LoginController.scala
  15. 19
      src/main/scala/wow/doge/chatto/controller/MainViewController.scala
  16. 4
      src/main/scala/wow/doge/chatto/controller/NavigationController.scala
  17. 2
      src/main/scala/wow/doge/chatto/controller/WorkspaceController.scala
  18. 69
      src/main/scala/wow/doge/chatto/service/CustomSerializer.scala
  19. 14
      src/main/scala/wow/doge/chatto/service/UserService.scala

12
build.sbt

@ -45,13 +45,14 @@ libraryDependencies ++= Seq(
"org.json4s" %% "json4s-jackson" % "3.6.8",
"org.scala-lang.modules" %% "scala-async" % "0.10.0",
"org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided,
// "org.kordamp.ikonli" %% "ikonli-javafx" % "11.4.0",
// "org.kordamp.ikonli" %% "ikonli-fontawesome-pack" % "11.4.0",
// "org.kordamp.ikonli" %% "ikonli-fontawesome5-pack" % "11.4.0",
"org.kordamp.ikonli" % "ikonli-javafx" % "11.4.0",
"org.kordamp.ikonli" % "ikonli-fontawesome-pack" % "11.4.0",
"org.kordamp.ikonli" % "ikonli-fontawesome5-pack" % "11.4.0",
"org.jsoup" % "jsoup" % "1.13.1",
"com.sandec" % "mdfx" % "0.1.6",
"com.softwaremill.sttp.client" %% "async-http-client-backend-future" % "2.1.1",
"com.softwaremill.quicklens" %% "quicklens" % "1.5.0"
"com.softwaremill.quicklens" %% "quicklens" % "1.5.0",
"net.synedra" % "validatorfx" % "0.1.11"
)
libraryDependencies += "org.asynchttpclient" % "async-http-client" % "2.12.1"
libraryDependencies += "com.softwaremill.macwire" %% "macros" % "2.3.3"
@ -66,6 +67,9 @@ libraryDependencies += "org.kordamp.bootstrapfx" % "bootstrapfx-core" % "0.2.4"
// https://mvnrepository.com/artifact/org.json4s/json4s-ext
libraryDependencies += "org.json4s" %% "json4s-ext" % "3.6.8"
// https://mvnrepository.com/artifact/org.jsoup/jsoup
libraryDependencies += "org.jsoup" % "jsoup" % "1.13.1"
enablePlugins(BuildInfoPlugin)
buildInfoPackage := "wow.doge.chatto"

61
src/main/resources/fxml/Chat.fxml

@ -1,49 +1,54 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8"?>
<?import com.jfoenix.controls.JFXListView ?>
<?import javafx.geometry.Insets ?>
<?import javafx.scene.control.Button ?>
<?import javafx.scene.control.Label ?>
<?import javafx.scene.control.TextArea ?>
<?import javafx.scene.layout.BorderPane ?>
<?import javafx.scene.layout.FlowPane ?>
<?import javafx.scene.layout.HBox ?>
<?import javafx.scene.layout.VBox ?>
<?import com.jfoenix.controls.JFXListView?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import org.kordamp.ikonli.javafx.FontIcon?>
<!-- <?import com.example.javafx.control.UserBox?> -->
<!-- fx:controller="com.example.javafx.controller.SimpleUiController" -->
<BorderPane minHeight="533.0" minWidth="800.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.ChatController">
<BorderPane fx:id="chatMainPane" minWidth="800.0" prefHeight="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.ChatController">
<left>
<VBox fx:id="usersVBox" alignment="TOP_CENTER" prefHeight="200.0" prefWidth="175.0" BorderPane.alignment="CENTER">
<VBox fx:id="usersVBox" alignment="CENTER" prefHeight="200.0" prefWidth="175.0" BorderPane.alignment="CENTER">
<children>
<JFXListView fx:id="usersListView" prefHeight="554.0" prefWidth="175.0" styleClass="my-list-view" />
<JFXListView fx:id="usersListView" prefHeight="561.0" prefWidth="175.0" styleClass="my-list-view" VBox.vgrow="ALWAYS" />
</children>
</VBox>
</left>
<center>
<VBox prefHeight="200.0" prefWidth="100.0" spacing="5.0" BorderPane.alignment="CENTER">
<VBox alignment="CENTER" prefHeight="200.0" prefWidth="100.0" spacing="5.0" BorderPane.alignment="CENTER">
<children>
<BorderPane prefHeight="41.0" prefWidth="620.0">
<center>
<HBox alignment="CENTER" spacing="5.0">
<HBox fx:id="selectedUserBox" alignment="CENTER" spacing="5.0" styleClass="chat-background">
<children>
<Label id="currentUser" fx:id="curUsr" text="User1" />
<Label id="lastActive" fx:id="dataContent" text="User2" />
<Label id="online" text="User2" />
<Label id="currentUser" fx:id="curUsr" styleClass="text-white" text="User1" />
<Label id="lastActive" fx:id="lastActiveLabel" styleClass="text-white" text="User2" />
<Label id="online" fx:id="isOnlineLabel" styleClass="text-white" text="User2" />
</children>
</HBox>
</center>
</BorderPane>
<JFXListView fx:id="chatListView" prefHeight="463.0" prefWidth="610.0" />
<HBox prefHeight="50.0" prefWidth="790.0" spacing="2.0">
<JFXListView fx:id="chatListView" minWidth="100.0" prefHeight="477.0" prefWidth="608.0" styleClass="my-list-view" VBox.vgrow="ALWAYS" />
<HBox prefHeight="50.0" prefWidth="790.0" spacing="2.0" styleClass="chat-background">
<children>
<TextArea fx:id="chatInput" prefHeight="15.0" prefWidth="250.0" HBox.hgrow="ALWAYS" />
<FlowPane alignment="CENTER" hgap="2.0" prefHeight="47.0" prefWidth="221.0">
<FlowPane alignment="CENTER" hgap="2.0" prefHeight="50.0" prefWidth="181.0">
<children>
<Button fx:id="logoutButton" styleClass="btn, btn-primary" text="Logout" onAction="#actionLogout" />
<Button fx:id="submitButton" styleClass="btn, btn-primary" text="Submit" />
<Button fx:id="logoutButton" onAction="#actionLogout" styleClass="btn, btn-primary" text="Logout" />
<Button fx:id="submitButton" style="-fx-background-color: transparent;">
<graphic>
<FontIcon accessibleText="Submit" fill="#2f91c9" iconLiteral="fa-chevron-circle-right" iconSize="40" />
</graphic>
</Button>
</children>
</FlowPane>
@ -55,8 +60,8 @@
</BorderPane.margin>
</VBox>
</center>
<stylesheets>
<!-- <URL value="@../styles/ui.css" />
<URL value="@../styles/bootstrapfx.css" /> -->
</stylesheets>
</BorderPane>
<!-- <stylesheets>
<URL value="@../styles/chat.css" />
<URL value="@../styles/bootstrapfx.css" />
</stylesheets> -->
</BorderPane>

13
src/main/resources/fxml/Login.fxml

@ -15,8 +15,7 @@
<!-- minHeight="533.0" minWidth="800" maxHeight="533.0" maxWidth="800" -->
<!-- fx:controller="com.example.javafx.controller.LoginController" -->
<GridPane prefHeight="533.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.LoginController">
<GridPane id="rootPane" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.LoginController">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="257.0" minWidth="10.0" prefWidth="122.0" />
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="667.0" />
@ -43,14 +42,14 @@
<Font size="14.0" />
</font>
</Label>
<JFXTextField fx:id="usernameTextField" focusColor="#d30699" labelFloat="true" minWidth="196.0" prefHeight="31.0" prefWidth="215.0" id="username" promptText="Username" />
<JFXPasswordField fx:id="passwordTextField" focusColor="#fb06d2" labelFloat="true" minWidth="196.0" prefHeight="31.0" prefWidth="215.0" id="password" promptText="Password" />
<JFXTextField id="username" fx:id="usernameTextField" focusColor="#d30699" labelFloat="true" minWidth="196.0" prefHeight="31.0" prefWidth="215.0" promptText="Username" />
<JFXPasswordField id="password" fx:id="passwordTextField" focusColor="#fb06d2" labelFloat="true" minWidth="196.0" prefHeight="31.0" prefWidth="215.0" promptText="Password" />
<!-- <JFXButton fx:id="submitButton" buttonType="RAISED" prefHeight="37.0" prefWidth="110.0" ripplerFill="WHITE" style="-fx-background-color: #fb06d2; -fx-background-radius: 50px;" text="Get started" textFill="WHITE" /> -->
<JFXButton fx:id="submitButton" styleClass="btn, btn-primary" text="Submit" onAction="#actionLogin" />
<JFXButton fx:id="submitButton" onAction="#actionLogin" styleClass="btn, btn-primary" text="Submit" />
<!-- style="-fx-background-radius: 50px;-fx-background-color: #fb06d2" -->
<Label fx:id="errorLabel" alignment="CENTER" prefHeight="37.0" prefWidth="324.0" text="" textAlignment="CENTER" textFill="#727070" wrapText="true">
<Label fx:id="errorLabel" alignment="CENTER" prefHeight="37.0" prefWidth="324.0" style="-fx-text-fill: RED;" textAlignment="CENTER" wrapText="true">
<font>
<Font size="14.0" />
</font>
@ -70,7 +69,7 @@
</VBox>
</children>
<stylesheets>
<!-- <URL value="@../styles/style2.css" /> -->
<URL value="@../styles/login.css" />
<URL value="@../styles/bootstrapfx.css" />
</stylesheets>
</GridPane>

54
src/main/resources/fxml/MainView.fxml

@ -4,8 +4,27 @@
<?import javafx.scene.layout.* ?>
<?import javafx.scene.control.* ?>
<AnchorPane id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.MainViewController">
<children>
<BorderPane id="rootPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="400" minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="wow.doge.chatto.controller.MainViewController">
<!-- <children>
<BorderPane prefHeight="600.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<top>
<AnchorPane fx:id="navigationPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
prefHeight="40.0" styleClass="navigation"/>
</top>
<center>
<AnchorPane fx:id="workspacePane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
prefHeight="200.0"/>
</center>
<bottom>
<AnchorPane fx:id="statusPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
prefHeight="30.0" styleClass="status"/>
</bottom>
</BorderPane>
<AnchorPane fx:id="mainPane"></AnchorPane>
<AnchorPane fx:id="chatPane"></AnchorPane>
</children> -->
<top>
<MenuBar VBox.vgrow="NEVER" fx:id="menuBar">
<menus>
<Menu mnemonicParsing="false" text="File">
@ -45,28 +64,13 @@
</Menu>
</menus>
</MenuBar>
<!-- <BorderPane prefHeight="600.0" prefWidth="600.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"
AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<top>
<AnchorPane fx:id="navigationPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
prefHeight="40.0" styleClass="navigation"/>
</top>
<center>
<AnchorPane fx:id="workspacePane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
prefHeight="200.0"/>
</center>
<bottom>
<AnchorPane fx:id="statusPane" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308"
prefHeight="30.0" styleClass="status"/>
</bottom>
</BorderPane> -->
<AnchorPane fx:id="mainPane"></AnchorPane>
<!-- <AnchorPane fx:id="chatPane"></AnchorPane> -->
</children>
</top>
<center>
<HBox fx:id="mainPane"></HBox>
</center>
<stylesheets>
<!-- <URL value="@default.css" />
<URL value="@../styles/ui.css" />
<URL value="@../styles/style2.css" /> -->
<URL value="@../styles/default.css" />
<URL value="@../styles/bootstrapfx.css" />
<URL value="@../styles/chat.css" />
</stylesheets>
</AnchorPane>
</BorderPane>

29
src/main/resources/fxml/default.css

@ -1,29 +0,0 @@
.navigation {
-fx-background-color: derive(cadetblue, 60%);
-fx-font-size: 14px;
}
.status {
-fx-background-color: derive(lightgray, 30%);
-fx-font-size: 12px;
}
.workspace2 {
-fx-background-color: azure;
-fx-font-size: 16px;
}
.workspace {
-fx-background-color: beige;
-fx-font-size: 13px;
}
.personPane {
-fx-font-size: 11px;
}

173
src/main/resources/styles/chat.css

@ -0,0 +1,173 @@
/* .ikonli-font-icon {
-fx-icon-size: 100px;
-fx-icon-color: blue;
} */
.ikonli-font-icon:hover {
-fx-icon-color: #1976a8;
}
#chatMainPane {
-fx-padding: 5px;
}
.my-list-view .scroll-bar:horizontal .track,
.my-list-view .scroll-bar:vertical .track {
-fx-background-color: transparent;
-fx-border-color: transparent;
-fx-background-radius: 0em;
-fx-border-radius: 2em;
}
.my-list-view .scroll-bar:horizontal .increment-button,
.my-list-view .scroll-bar:horizontal .decrement-button {
-fx-background-color: transparent;
-fx-background-radius: 0em;
-fx-padding: 0 0 10 0;
}
.my-list-view .scroll-bar:vertical .increment-button,
.my-list-view .scroll-bar:vertical .decrement-button {
-fx-background-color: transparent;
-fx-background-radius: 0em;
-fx-padding: 0 10 0 0;
}
.my-list-view .scroll-bar .increment-arrow,
.my-list-view .scroll-bar .decrement-arrow {
-fx-shape: " ";
-fx-padding: 0;
}
.my-list-view .scroll-bar:horizontal .thumb,
.my-list-view .scroll-bar:vertical .thumb {
-fx-background-color: derive(black, 90%);
-fx-background-insets: 2, 0, 0;
-fx-background-radius: 2em;
}
.scroll-pane .scroll-bar:horizontal .track,
.scroll-pane .scroll-bar:vertical .track {
-fx-background-color: transparent;
-fx-border-color: transparent;
-fx-background-radius: 0em;
-fx-border-radius: 2em;
}
.scroll-pane .scroll-bar:horizontal .increment-button,
.scroll-pane .scroll-bar:horizontal .decrement-button {
-fx-background-color: transparent;
-fx-background-radius: 0em;
-fx-padding: 0 0 10 0;
}
.scroll-pane .scroll-bar:vertical .increment-button,
.scroll-pane .scroll-bar:vertical .decrement-button {
-fx-background-color: transparent;
-fx-background-radius: 0em;
-fx-padding: 0 10 0 0;
}
.scroll-pane .scroll-bar .increment-arrow,
.scroll-pane .scroll-bar .decrement-arrow {
-fx-shape: " ";
-fx-padding: 0;
}
.scroll-pane .scroll-bar:horizontal .thumb,
.scroll-pane .scroll-bar:vertical .thumb {
-fx-background-color: derive(black, 90%);
-fx-background-insets: 2, 0, 0;
-fx-background-radius: 2em;
}
.scroll-pane {
-fx-background-color: transparent;
}
.scroll-pane > .viewport {
-fx-background-color: transparent;
}
.chat-message-box {
-fx-text-fill: white;
/* -fx-background-color: LIGHTGREEN; */
-fx-background-color: #82ccdd;
-fx-background-radius: 30px;
-fx-padding: 20px;
}
.chat-background {
-fx-background-color: rgba(0, 0, 0, 0.4);
/* -fx-selection-bar: rgba(0, 0, 0, 0.5); */
-fx-text-fill: white;
-fx-background-radius: 20px;
-fx-padding: 5px 10px;
}
.my-list-view {
-fx-background-color: rgba(0, 0, 0, 0.4);
/* -fx-selection-bar: rgba(0, 0, 0, 0.5); */
-fx-text-fill: white;
-fx-background-radius: 20px;
-fx-padding: 5px 10px;
}
.list-cell {
-fx-background-color: transparent;
-fx-text-fill: white;
}
.list-cell:selected {
-fx-background-color: rgba(0, 0, 0, 0.2);
-fx-text-fill: white;
-fx-background-radius: 20px;
}
.list-cell:hover {
-fx-background-color: rgba(0, 0, 0, 0.1);
-fx-text-fill: white;
-fx-background-radius: 20px;
}
.list-cell:selected:hover {
-fx-background-color: rgba(0, 0, 0, 0.3);
-fx-text-fill: white;
-fx-background-radius: 20px;
}
.list-view:focused .list-cell:selected {
-fx-background-color: rgba(0, 0, 0, 0.3);
-fx-text-fill: white;
-fx-background-radius: 20px;
}
.text-area {
-fx-text-fill: white;
-fx-border-radius: 20px;
}
.text-area .content {
-fx-background-color: rgb(116, 116, 116);
-fx-background-radius: 20px;
}
.text-area {
-fx-background-color: rgba(53, 89, 119, 0.4);
}
.text-area .scroll-pane {
-fx-background-color: transparent;
}
.text-area .scroll-pane .viewport {
-fx-background-color: transparent;
}
.text-area .scroll-pane .content {
-fx-background-color: transparent;
}
#chatInput {
-fx-text-fill: white;
-fx-background-radius: 20px;
-fx-padding: 5px 10px;
}

85
src/main/resources/styles/default.css

@ -0,0 +1,85 @@
.navigation {
-fx-background-color: derive(cadetblue, 60%);
-fx-font-size: 14px;
}
.status {
-fx-background-color: derive(lightgray, 30%);
-fx-font-size: 12px;
}
.workspace2 {
-fx-background-color: azure;
-fx-font-size: 16px;
}
.workspace {
-fx-background-color: beige;
-fx-font-size: 13px;
}
.personPane {
-fx-font-size: 11px;
}
.root {
-fx-padding: 5 5 5 5;
}
.scroll-bar:horizontal .track,
.scroll-bar:vertical .track {
-fx-background-color: transparent;
-fx-border-color: transparent;
-fx-background-radius: 0em;
-fx-border-radius: 2em;
}
.scroll-bar:horizontal .increment-button,
.scroll-bar:horizontal .decrement-button {
-fx-background-color: transparent;
-fx-background-radius: 0em;
-fx-padding: 0 0 10 0;
}
.scroll-bar:vertical .increment-button,
.scroll-bar:vertical .decrement-button {
-fx-background-color: transparent;
-fx-background-radius: 0em;
-fx-padding: 0 10 0 0;
}
.scroll-bar .increment-arrow,
.scroll-bar .decrement-arrow {
-fx-shape: " ";
-fx-padding: 0.15em 0;
}
.scroll-bar:vertical .increment-arrow,
.scroll-bar:vertical .decrement-arrow {
-fx-shape: " ";
-fx-padding: 0 0.15em;
}
.scroll-bar:horizontal .thumb,
.scroll-bar:vertical .thumb {
-fx-background-color: derive(black, 90%);
-fx-background-insets: 2, 0, 0;
-fx-background-radius: 2em;
}
.scroll-bar:horizontal .thumb:hover,
.scroll-bar:vertical .thumb:hover {
-fx-background-color: derive(#4d4c4f, 10%);
-fx-background-insets: 2, 0, 0;
-fx-background-radius: 2em;
}
.root {
-fx-background-color: linear-gradient(to right, #91eae4, #86a8e7, #7f7fd5);
}
/* linear-gradient(to right, #91EAE4, #86A8E7, #7F7FD5); */
/* linear-gradient(from 25% 25% to 100% 100%, #dc143c, #661a33)"); */
.text-white {
-fx-text-fill: white;
}

5
src/main/resources/styles/login.css

@ -0,0 +1,5 @@
#rootPane {
-fx-background-image: url("../images/backgroung.jpg");
-fx-background-size: 1920 1080;
-fx-background-position: center center;
}

57
src/main/scala/wow/doge/chatto/ApplicationController.scala

@ -38,19 +38,20 @@ class ApplicationController extends DefaultWindowController {
// override def width: Int = 400
@Inject
private var appDataHandler: AppDataHandler = _
// @Inject
// private var appDataHandler: AppDataHandler = _
def applicationDidLaunch() = {
logger.info("start " + this)
applicationEnvironment.loadResourceBundle("bundles/application")
replaceSceneContent(mainViewController)
replaceSceneContent(mainViewController.loginController)
}
@Produces
def applicationName: ApplicationName = {
ApplicationName(configStringValue("application.name"))
}
@Produces
def httpBackend = backend
@ -65,15 +66,15 @@ class ApplicationController extends DefaultWindowController {
replaceSceneContent(newMainViewController)
}
def testListener(@Observes event: SceneControllerWillChangeEvent) = {
logger.info("test success 1")
// logger.info(s"${event.newController}")
}
// def testListener(@Observes event: SceneControllerWillChangeEvent) = {
// logger.info("test success 1")
// // logger.info(s"${event.newController}")
// }
def testListener2(@Observes event: SceneControllerDidChangeEvent) = {
logger.info("test success 2")
// logger.info(s"${event.newController}")
}
// def testListener2(@Observes event: SceneControllerDidChangeEvent) = {
// logger.info("test success 2")
// // logger.info(s"${event.newController}")
// }
override def applicationWillStop(): Unit = async {
super.applicationWillStop()
@ -84,42 +85,17 @@ class ApplicationController extends DefaultWindowController {
}
def showLoginPane() = onFX {
offFX { appDataHandler.clearCredentials() }
// replaceSceneContent(mainViewController.loginController)
// mainViewController.mainManager.updatePaneContent(
// mainViewController.loginController
// )
// offFX { appDataHandler.clearCredentials() }
replaceSceneContent(mainViewController.loginController)
}
def logout() = {
def logout() = onFX {
val newMainViewController = getController[MainViewController]()
replaceSceneContent(newMainViewController)
replaceSceneContent(mainViewController.loginController)
}
def showChatPane(): Unit = onFX {
// import org.scalafx.extras._
replaceSceneContent(mainViewController.chatController, true)
// mainViewController.mainManager.updatePaneContent(
// mainViewController.chatController
// )
// httpBackend.send(basicRequest.get(uri""))
// val willBeResponse = basicRequest
// .get(uri"https://httpbin.org/get")
// .response(asJson[HttpBinResponse])
// .send()
// async {
// val r = await { willBeResponse }
// r.body.map(println)
// }
// willBeResponse onComplete {
// case Success(x) => { x.body }
// case Failure(x) => {}
// }
// val body = for {
// r <- willBeResponse
// } yield (r.body)
replaceSceneContent(mainViewController, true)
}
}
@ -142,7 +118,6 @@ class AppDataHandler {
def appData = _appData
def updateCredentials(credentials: UserCredentials): Unit = offFX {
println(credentials)
appData = appData.copy(credentials = credentials)
}

114
src/main/scala/wow/doge/chatto/control/JFXSmoothScroll.java

@ -0,0 +1,114 @@
package wow.doge.chatto.control;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.DefaultProperty;
import javafx.beans.property.DoubleProperty;
import javafx.event.EventHandler;
import javafx.geometry.Bounds;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.ListView;
import javafx.geometry.Orientation;
import javafx.scene.control.ScrollBar;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.ScrollEvent;
import javafx.scene.layout.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.transform.Scale;
import javafx.scene.transform.Transform;
import javafx.util.Duration;
import java.util.function.Function;
public class JFXSmoothScroll {
private static ScrollBar getScrollbarComponent(ListView<?> control, Orientation orientation) {
Node n = control.lookup(".scroll-bar");
if (n instanceof ScrollBar) {
final ScrollBar bar = (ScrollBar) n;
if (bar.getOrientation().equals(orientation)) {
return bar;
}
}
return null;
}
public static void smoothScrollingListView(ListView<?> listView, double speed) {
smoothScrollingListView(listView, speed, Orientation.VERTICAL, bounds -> bounds.getHeight());
}
public static void smoothHScrollingListView(ListView<?> listView, double speed) {
smoothScrollingListView(listView, speed, Orientation.HORIZONTAL, bounds -> bounds.getHeight());
}
private static void smoothScrollingListView(ListView<?> listView, double speed, Orientation orientation,
Function<Bounds, Double> sizeFunc) {
ScrollBar scrollBar = getScrollbarComponent(listView, orientation);
if (scrollBar == null) {
return;
}
scrollBar.setUnitIncrement(5);
final double[] frictions = { 0.99, 0.1, 0.05, 0.04, 0.03, 0.02, 0.01, 0.04, 0.01, 0.008, 0.008, 0.008, 0.008,
0.0006, 0.0005, 0.00003, 0.00001 };
final double[] pushes = { speed };
final double[] derivatives = new double[frictions.length];
final double[] lastVPos = { 0 };
Timeline timeline = new Timeline();
final EventHandler<MouseEvent> dragHandler = event -> timeline.stop();
final EventHandler<ScrollEvent> scrollHandler = event -> {
scrollBar.valueProperty().set(lastVPos[0]);
if (event.getEventType() == ScrollEvent.SCROLL) {
double direction = event.getDeltaY() > 0 ? -1 : 1;
for (int i = 0; i < pushes.length; i++) {
derivatives[i] += direction * pushes[i];
}
if (timeline.getStatus() == Animation.Status.STOPPED) {
timeline.play();
}
}
event.consume();
};
if (scrollBar.getParent() != null) {
scrollBar.getParent().addEventHandler(MouseEvent.DRAG_DETECTED, dragHandler);
scrollBar.getParent().addEventHandler(ScrollEvent.ANY, scrollHandler);
}
scrollBar.parentProperty().addListener((o, oldVal, newVal) -> {
if (oldVal != null) {
oldVal.removeEventHandler(MouseEvent.DRAG_DETECTED, dragHandler);
oldVal.removeEventHandler(ScrollEvent.ANY, scrollHandler);
}
if (newVal != null) {
newVal.addEventHandler(MouseEvent.DRAG_DETECTED, dragHandler);
newVal.addEventHandler(ScrollEvent.ANY, scrollHandler);
}
});
timeline.getKeyFrames().add(new KeyFrame(Duration.millis(3), (event) -> {
for (int i = 0; i < derivatives.length; i++) {
derivatives[i] *= frictions[i];
}
for (int i = 1; i < derivatives.length; i++) {
derivatives[i] += derivatives[i - 1];
}
double dy = derivatives[derivatives.length - 1];
double size = sizeFunc.apply(scrollBar.getLayoutBounds());
scrollBar.valueProperty().set(Math.min(Math.max(scrollBar.getValue() + dy / size, 0), 1));
lastVPos[0] = scrollBar.getValue();
if (Math.abs(dy) < 1) {
if (Math.abs(dy) < 0.001) {
timeline.stop();
}
}
}));
timeline.setCycleCount(Animation.INDEFINITE);
}
}

10
src/main/scala/wow/doge/chatto/control/MessageBox.scala

@ -0,0 +1,10 @@
package wow.doge.chatto.control
import javafx.scene.layout.HBox
import javafx.scene.control.Label
import scalafx.Includes._
import wow.doge.chatto.controller.ChatData
import com.sfxcode.sapphire.core.value.FXBean
class MessageBox(val sender: String, val receiver: String, val message: String)
extends HBox() {}

5
src/main/scala/wow/doge/chatto/control/UserBox2.scala

@ -7,7 +7,10 @@ import wow.doge.chatto.controller.ChatData
import com.sfxcode.sapphire.core.value.FXBean
class UserBox2(val username: String, val chatData: ChatData) extends HBox() {
val usernameLabel = new Label(username)
val usernameLabel = new Label(username) {
// this.style = "-fx-text-fill: white"
this.styleClass ++= Seq("text-white")
}
// lazy val chatDataBean = FXBean[ChatData](chatData)
this.children ++= Seq {
usernameLabel

388
src/main/scala/wow/doge/chatto/controller/ChatController.scala

@ -18,7 +18,6 @@ import wow.doge.chatto.service.UserService
import scala.concurrent.ExecutionContext
import scala.concurrent.ExecutionContext.Implicits.global
import com.typesafe.scalalogging.LazyLogging
// import wow.doge.chatto.controller.LoginController.Person
import com.sfxcode.sapphire.core.value.FXBean
import wow.doge.chatto.AppDataHandler
import com.jfoenix.controls.JFXListView
@ -41,6 +40,27 @@ import wow.doge.chatto.messagebuble.BubbleSpec
import javafx.scene.layout.Background
import javafx.scene.layout.BackgroundFill
import javafx.geometry.Pos
import scalafx.beans.property.ReadOnlyBufferProperty
import scalafx.beans.property.ReadOnlyBufferWrapper
import javafx.beans.property.ReadOnlyListProperty
import scalafx.beans.property.BufferProperty
import javafx.collections.FXCollections
import com.sandec.mdfx.MDFXNode
import javafx.scene.layout.BorderPane
import javafx.scene.layout.Priority
import net.synedra.validatorfx.Validator
import wow.doge.chatto.control.JFXSmoothScroll
import javafx.scene.control.ContextMenu
import javafx.scene.control.MenuItem
import javafx.scene.input.Clipboard
import javafx.scene.input.ClipboardContent
import scalafx.scene.input.KeyCodeCombination
import scalafx.scene.input.KeyCode
import scalafx.scene.input.KeyCombination
import javafx.scene.input.DataFormat
import wow.doge.chatto.control.MessageBox
import javafx.scene.control.SelectionMode
import scalafx.beans.property.BooleanProperty
class ChatController @Inject() (
userService: UserService,
@ -49,71 +69,54 @@ class ChatController @Inject() (
with LazyLogging {
// @FXML private var label: Label = _
@FXML private var flowPane: FlowPane = _
@FXML var chatMainPane: BorderPane = _
// @FXML private var flowPane: FlowPane = _
@FXML private var submitButton: Button = _
@FXML private var logoutButton: Button = _
// @FXML private var chatTextArea: TextArea = _
@FXML private var chatInput: TextArea = _
@FXML private var usersVBox: VBox = _
@FXML var usersListView: JFXListView[UserBox2] = _
@FXML var chatListView: JFXListView[HBox] = _
@FXML var chatListView: JFXListView[MessageBox] = _
@FXML private var curUsr: Label = _
@FXML private var dataContent: Label = _
// applicationController.show
private val usersListProperty = new SimpleListProperty(
ObservableBuffer[UserBox2]()
@FXML private var lastActiveLabel: Label = _
@FXML private var isOnlineLabel: Label = _
@FXML private var selectedUserBox: HBox = _
private val usersBuffer = ObservableBuffer.empty[UserBox2]
private val usersListProperty = BufferProperty(usersBuffer)
/**
* Readonly property wrapping an unmodifiable list.
* Synchronized with the internal users list property.
* Attemping to modify the internal list will throw an exception
*/
val usersListROProp: ReadOnlyListProperty[UserBox2] = BufferProperty(
FXCollections.unmodifiableObservableList(usersListProperty())
)
private val chatDataBuffer = ObservableBuffer[UserBox2]()
private val chatDataStore: mutable.Map[String, ChatDataProperty] =
TrieMap()
// private lazy val curUserKeys = KeyBindings("curUser")
// bindings.add("person", "Person ${_self.name()} with age of ${_self.age()} is active: ${_self.isActive()}")
// private lazy val curUserAdapter = FXBeanAdapter[User](this)
private val chatDataStore = TrieMap.empty[String, ChatDataProperty]
private lazy val chatDataAdapter = FXBeanAdapter[ChatData](this)
override def didGainVisibilityFirstTime(): Unit = {
super.didGainVisibilityFirstTime()
// val ub = new UserBox()
this.stage.resizable = true
// ub.messageLabel.text = "Hi there"
// ub.messageLabel.id =
// ub.userRadioButton.text = "User 1"
// usersVBox.children.clear()
// usersVBox.children += ub
// println("test")
// println(s"Result = ${func()}")
// offFX(println("hello from new thread"))
// chatTextArea.visible <== !chatInput.text.isEmpty
// chatTextArea.text <== chatInput.text
// for (r <- userService.func2()) yield (logger.info(s"${r.body}"))
// val person = Person(0, 10, "Billy")
// val bean = FXBean[Person](person)
// ub.messageLabel.text <== bean.getStringProperty("name")
// bean.getStringProperty("name") <== chatInput.text
// bean.getStringProperty("name")() = "Lester"
// println(bean.getValue("name"))
// println(bean.getStringProperty("name")())
// bean.
// bean.updateValue("name", "Lester")
// println(bean.bean)
// val curUserBean = FXBean[User](User("None"))
// logoutButton.onAction = (e) =>
// usersListView
// .getSelectionModel()
// .selectedItemProperty()
// .addListener((_, _, newValue) => {
// curUsr.text() = newValue.usernameLabel.text()
// })
chatMainPane.hgrow = Priority.ALWAYS
chatListView.selectionModel().selectionMode = SelectionMode.MULTIPLE
chatDataAdapter.set(FXBean(ChatData.empty))
Array(submitButton, chatInput).foreach(n => {
n.disableProperty() <== usersListView
.selectionModel()
.selectedItemProperty()
.isNull()
})
// curUserKeys.add("content", "${_self.data().content()}")
val chatDataAdapterKeys = KeyBindings()
// chatDataAdapterKeys.add("currentUser", "${_self.userName()}")
chatDataAdapterKeys.add("currentUser", "${_self.userName()}")
// chatDataAdapterKeys.add(
// "lastActive",
// "${_self.lastActiveString()}"
@ -125,39 +128,97 @@ class ChatController @Inject() (
// curUserAdapter.addDateConverter()
// curUserAdapter.addBindings(curUserKeys)
chatDataAdapter.addBindings(chatDataAdapterKeys)
// curUsr.text <== chatDataAdapter.beanProperty
// .getOrElse(FXBean(ChatData.empty))
// .getStringProperty("lastActiveString")
usersListView
.getSelectionModel()
.selectionModel()
.selectedItemProperty()
.addListener((_, _, newValue) => {
if (newValue != null) {
// val dataBean =
// FXBean(User(newValue.usernameLabel.text(), Data("test data")))
// curUserAdapter
// .set(dataBean)
// chatDataAdapter.set(newValue.chatDataBean)
val y = chatDataStore
.get(newValue.username)
val x = y
Option(newValue).foreach(nv => {
val maybeCDP = chatDataStore
.get(nv.username)
val chatDataBean = maybeCDP
.map(_.bean)
.getOrElse {
logger.error("Error null")
FXBean(ChatData.empty)
}
chatDataAdapter.set(x)
y.map(z => chatListView.items <== z.prop)
}
chatDataAdapter.set(chatDataBean)
maybeCDP.foreach(cdp => {
// lastActiveLabel.text <== cdp.lastActive
isOnlineLabel.text <== cdp.isActive.asString()
chatListView.items <== cdp.messageBubbles
})
})
})
val copyMessageMenuItem = new MenuItem("Copy Message")
copyMessageMenuItem.accelerator =
new KeyCodeCombination(KeyCode.C, KeyCombination.ControlDown)
copyMessageMenuItem.onAction = _ => {
val content = new ClipboardContent()
val x = chatListView.getSelectionModel().getSelectedItems().map(_.message)
// chatListView.selectionModel().selectedItem().message
Option(x).foreach(message => {
content.putString(message.mkString("\n"))
Clipboard.getSystemClipboard().setContent(content)
})
// val message = cdp.messageList(selectedIndex)
// val maybeCDP = chatDataStore.get(chatDataAdapter.get.bean.userName)
// maybeCDP.foreach(cdp => {
// // val message = Option(cdp.messageList().get(selectedIndex)).toRight {
// // "Unexpected error - message not found"
// // }
// // message.map(msg => {
// // // content.putString(msg)
// // // clipboard.setContent(content)
// // // val content = clipboard.content
// // // content.putString(msg)
// // // clipboard.content = content
// // clipboard.putString(msg)
// // })
// // message.left.map(err => logger.error(err))
// })
}
val chatListMenu = new ContextMenu()
// curUsr.text <== usersListView
// .getSelectionModel()
// .getSelectedItem()
// .usernameLabel
// .text
chatListMenu.items += copyMessageMenuItem
chatListView.contextMenu = chatListMenu
usersListView.items <== usersListProperty
val validator = new Validator()
submitButton.disable <== validator.containsErrorsProperty()
submitButton.onAction = (e) => {
// val msgBox = ChatDataProperty.createMdMessageBox2(chatInput.text())
// chatListView.items() += msgBox
if (!chatInput.text().equals("") &&
!chatInput.text().equals(" ") &&
!chatInput.text().equals("\n")) {
val maybeCDP = chatDataStore.get(chatDataAdapter.get.bean.userName)
maybeCDP.foreach(cdp => {
cdp.messageBubbles += ChatDataProperty.createMdMessageBox3(
appDataHandler.appData.credentials.username,
cdp.username(),
chatInput.text()
)
})
}
}
validator
.createCheck()
.withMethod(c => {
val userName = chatInput.text()
if (!userName.toLowerCase().equals(userName)) {
c.error("Please use only lowercase letters.")
}
})
.dependsOn("chatInput", chatInput.text)
.decorates(chatInput)
.immediate()
}
override def didGainVisibility(): Unit = {
@ -165,70 +226,60 @@ class ChatController @Inject() (
chatInput.requestFocus()
async {
val willBeUsers = userService
.getUsers(appDataHandler.appData.credentials)
.map(_.body)
val willBeActiveUsers = userService
.getActiveUsers(appDataHandler.appData.credentials)
.map(_.body)
val maybeUsers = await(willBeUsers)
val maybeActiveUsers = await(willBeActiveUsers)
// maybeActiveUsers.foreach(println)
logger.debug(s"$maybeActiveUsers")
logger.debug(s"Received Users: $maybeActiveUsers")
val maybeUserBoxes = maybeActiveUsers.map(users => {
// usersBuffer ++= users
users.map(user => {
// usersBuffer += FXBean(User(user))
// val ub = new UserBox()
// ub.messageLabel.text = "Hi there"
// ub.userRadioButton.text = user
// ub
// new Rectangle {
// fill <== when(hover) choose (Color.Red)
// }
// val hb = new HBox
val chatData =
ChatData(user.userName, user, ObservableBuffer.empty[String])
// chatDataStore.updateWith(user.userName)(maybeCD =>
// maybeCD.map(cd => {
// cd.messagesStringProperty +=
// })
// )
chatDataStore.put(user.userName, new ChatDataProperty(chatData))
chatDataStore
.get(user.userName)
.map(cdp => {
cdp.prop ++= Seq("hi", "hello", "bye")
.map(s => ChatDataProperty.createMdMessageBox(s))
})
new UserBox2(user.userName, chatData) {
// this.children += new Label {
// textProperty() = user
// // textFillProperty <== when(this.hover) choose (Color.RED) otherwise (Color.BLUE)
// }
// fill <== when(this.hover) choose (Color.RED) otherwise (Color.BLUE)
this.styleClass ++= Seq("text-white")
}
})
})
// maybeUserBoxes.map(userBoxes => {
// // chatDataBuffer ++= userBoxes
// usersListProperty ++= userBoxes
// })
val messageBox = ChatDataProperty.createMdMessageBox("*hello!*")
val messageBox = ChatDataProperty.createMdMessageBox2(
"""**Hello world qefwew yeeehay bwergqwevqcqe**
|**Hello world qefwew yeeehay bwergqwevqcqe**
|
| Hello World
""".stripMargin
)
onFX {
// maybeUserBoxes.map(userBoxes => {
// chatDataBuffer ++= userBoxes
// // usersListView.items() ++= userBoxes
// // val x = new SimpleListProperty(ObservableBuffer(userBoxes))
// // usersListView.items <== x
// })
maybeUserBoxes.map(userBoxes => {
usersListProperty ++= userBoxes
maybeUserBoxes.foreach(userBoxes => {
usersBuffer ++= userBoxes
})
chatListView.items() += messageBox
chatListView.items() ++= Seq(
messageBox,
ChatDataProperty.createMdMessageBox2("hello"),
ChatDataProperty.createMdMessageBox2(
""" 1. Hello world qefwew yeeehay bwergqwevqcqe
|1. Hello world qefwew yeeehay bwergqwevqcqe
|1. Hello world qefwew yeeehay bwergqwevqcqe
|1. Hello world qefwew yeeehay bwergqwevqcqe""".stripMargin
)
)
// .map(node => {
// node.prefWidthProperty <== (chatListView.prefWidthProperty - 200)
// node
// })
// JFXSmoothScroll.smoothScrollingListView(chatListView, 0.1)
}
chatDataStore
.map { case (key, value) => value }
.foreach(cdp => {
cdp.messageBubbles ++= Seq(
ChatDataProperty.createMdMessageBox2("hi"),
ChatDataProperty.createMdMessageBox2("hello"),
ChatDataProperty.createMdMessageBox2("bye")
)
// .map(ChatDataProperty.createMdMessageBox)
})
}
}
def func() = {
@ -241,40 +292,29 @@ class ChatController @Inject() (
def actionLogout = onFX {
offFXAndWait {
appDataHandler.clearCredentials()
println(appDataHandler.appData)
}
// curUserAdapter.set(User.empty)
logger.debug(s"Logout - clearing credentials - ${appDataHandler.appData}")
chatDataAdapter.set(FXBean(ChatData.empty))
usersListView.items().clear()
chatListView.items().clear()
chatDataBuffer.clear()
chatDataStore.clear()
usersListProperty.clear()
usersBuffer.clear()
chatInput.clear()
this.stage.maximized = false
applicationController.logout()
println(appDataHandler.appData)
}
}
object ChatController {
lazy val markdownStyleSheet =
getClass().getResource("/styles/markdown.css").toExternalForm()
implicit class MyClipboardExtension(clipboard: Clipboard) {
def putString(string: String) = {
// val content = Option(clipboard.getContent(DataFormat.PLAIN_TEXT))
// .getOrElse(new ClipboardContent())
// content.putString(string)
// clipboard.setContent(content)
}
}
}
final case class Person(id: Int, age: Int, name: String)
final case class Data(content: String)
final case class User(curUser: String, data: Data)
object User {
def empty = User("", Data(""))
// Bindings.createObjectBinding()
}
// final case class ActiveUser(
// userName: String,
// online: Boolean,
// lastActive: String
// )
// object ActiveUser {
// def empty = ActiveUser("empty", false, "empty")
// }
final case class ChatData(
userName: String,
activeUser: ActiveUser,
@ -294,21 +334,26 @@ object ChatData {
class ChatDataProperty(chatData: ChatData) {
import ChatDataProperty._
val bean = FXBean(chatData)
val usernameProperty = bean.getStringProperty("userName")
val isActiveProperty = bean.getBooleanProperty("activeUser.online")
val lastActiveProperty = bean.getStringProperty("lastActiveString")
val messagesStringProperty = new SimpleListProperty(chatData.messages)
val prop = new SimpleListProperty(ObservableBuffer.empty[HBox])
// val x = messagesStringProperty.map(message => createMdMessageBox(message))
// prop <== messagesStringProperty.map(message => createMdMessageBox(message))
// prop <== new SimpleListProperty(x)
val username = bean.getStringProperty("userName")
val isActive = bean.getBooleanProperty("activeUser.online")
val lastActive = bean.getStringProperty("lastActiveString")
lazy val messageBubbles = BufferProperty(
chatData.messages.map(ChatDataProperty.createMdMessageBox2)
)
def messageList = messageBubbles().map(_.message)
// lazy val messages = messagesBubbleProperty
// .get()
// .map(_.messageText)
}
object ChatDataProperty {
lazy val markdownStyleSheet =
getClass().getResource("/styles/markdown.css").toExternalForm()
def createMdMessageBox(mdfxText: String) = {
val mdfxNode = new BubbledMDFXNode(mdfxText);
mdfxNode
.getStylesheets()
.add(ChatController.markdownStyleSheet);
.add(markdownStyleSheet);
mdfxNode.setBubbleSpec(BubbleSpec.FACE_RIGHT_CENTER);
mdfxNode.setBackground(
new Background(new BackgroundFill(Color.LIGHTSTEELBLUE, null, null))
@ -319,4 +364,49 @@ object ChatDataProperty {
box.children += mdfxNode;
box
}
def createMdMessageBox2(mdfxText: String) = {
val mdfxNode = new MDFXNode(mdfxText);
mdfxNode
.getStylesheets()
.add(markdownStyleSheet)
mdfxNode.setMaxWidth(500)
mdfxNode.vgrow = Priority.ALWAYS
mdfxNode.setAlignment(Pos.CENTER)
mdfxNode.styleClass = Seq("chat-message-box")
val box = new MessageBox("", "", mdfxText)
box.setAlignment(Pos.CENTER_RIGHT)
// box.maxWidth(500)
box.hgrow = Priority.ALWAYS
box.vgrow = Priority.ALWAYS
box.children ++= Seq(mdfxNode)
box.fillHeight = true
box
}
def createMdMessageBox3(
sender: String,
receiver: String,
mdfxText: String
) = {
val mdfxNode = new MDFXNode(mdfxText);
mdfxNode
.getStylesheets()
.add(markdownStyleSheet)
mdfxNode.setMaxWidth(500)
mdfxNode.vgrow = Priority.ALWAYS
mdfxNode.setAlignment(Pos.CENTER)
mdfxNode.styleClass = Seq("chat-message-box")
val box = new MessageBox(sender, receiver, mdfxText)
box.setAlignment(Pos.CENTER_RIGHT)
// box.maxWidth(500)
box.hgrow = Priority.ALWAYS
box.vgrow = Priority.ALWAYS
box.children ++= Seq(mdfxNode)
box.fillHeight = true
box
}
}

15
src/main/scala/wow/doge/chatto/controller/LoginController.scala

@ -31,6 +31,8 @@ import wow.doge.chatto.types.AppTypes
import org.scalafx.extras._
import wow.doge.chatto.AppDataHandler
import com.sfxcode.sapphire.core.value.BeanConversions
import javafx.scene.layout.StackPane
import com.jfoenix.controls.JFXSpinner
class LoginController @Inject() (
userService: UserService,
@ -87,33 +89,31 @@ class LoginController @Inject() (
val inputUserName = usernameTextField.text()
val inputPassword = passwordTextField.text()
submitButton.disable = true
login(inputUserName, inputPassword) onComplete {
case Success(maybeToken) => {
maybeToken.foreach(println)
maybeToken match {
case Some(token) =>
async {
val credentials =
UserCredentials(inputUserName, inputPassword, token)
appDataHandler.updateCredentials(credentials)
// await {
// userService.getUsers(credentials).map(_.body.foreach(println))
// }
updateErrorLabel("")
applicationController.showChatPane()
onFX { submitButton.disable = false }
}
case None => {
updateErrorLabel("Error logging in - please check your password")
logger.warn("Login unsuccessful wrong password")
onFX { submitButton.disable = false }
}
}
// applicationController.showChatPane()
}
case Failure(exception) => {
logger.error(s"${exception.getMessage()}")
logger.warn("Login unsuccessful network problem")
updateErrorLabel("Error logging in - Please check your network")
// applicationController.showChatPane()
onFX { submitButton.disable = false }
}
}
}
@ -141,5 +141,4 @@ class LoginController @Inject() (
username: String,
password: String
)
}

19
src/main/scala/wow/doge/chatto/controller/MainViewController.scala

@ -11,11 +11,13 @@ import com.typesafe.scalalogging.LazyLogging
import wow.doge.chatto.messagebuble.BubbledMDFXNode
import scalafx.scene.layout.GridPane
import scalafx.Includes._
// import wow.doge.chatto.
import javafx.scene.layout.HBox
import javafx.scene.layout.Priority
import wow.doge.chatto.control.UserBox
class MainViewController extends ViewController with LazyLogging {
@FXML var menuBar: MenuBar = _
@FXML private var menuBar: MenuBar = _
// @FXML
// var workspacePane: Pane = _
// @FXML
@ -23,9 +25,7 @@ class MainViewController extends ViewController with LazyLogging {
// @FXML
// var navigationPane: Pane = _
@FXML var mainPane: Pane = _
// @FXML var chatPane: Pane = _
@FXML private var mainPane: HBox = _
lazy val workspaceController = getController[WorkspaceController]()
lazy val navigationController = getController[NavigationController]()
@ -33,22 +33,21 @@ class MainViewController extends ViewController with LazyLogging {
lazy val loginController = getController[LoginController]()
lazy val chatController = getController[ChatController]()
// val bubbleNode = new BubbledMDFXNode("Wow")
var workspaceManager: ContentManager = _
var navigationManager: ContentManager = _
var statusBarManager: ContentManager = _
var mainManager: ContentManager = _
override def didGainVisibilityFirstTime() {
// menuBar.setUseSystemMenuBar(true)
override def didGainVisibilityFirstTime() = {
menuBar.setUseSystemMenuBar(true)
// menuBar.setVisible(false)
// navigationManager =
// ContentManager(navigationPane, this, navigationController)
// statusBarManager = ContentManager(statusPane, this, statusBarController)
// workspaceManager = ContentManager(workspacePane, this, workspaceController)
mainManager = ContentManager(mainPane, this, loginController)
mainManager = ContentManager(mainPane, this, chatController)
chatController.chatMainPane.hgrow = Priority.ALWAYS
}
}

4
src/main/scala/wow/doge/chatto/controller/NavigationController.scala

@ -5,12 +5,12 @@ import javafx.scene.control.Button
class NavigationController extends AbstractViewController {
def actionClickButton(event: ActionEvent) {
def actionClickButton(event: ActionEvent) = {
logger.debug(event.toString)
statusBarController.updateLabel(event.getSource.asInstanceOf[Button])
}
def actionHotReload(event: ActionEvent) {
def actionHotReload(event: ActionEvent) = {
applicationController.replacePrimarySceneContent()
logger.debug("Hot Reload Succeeded")
statusBarController.updateLabel(event.getSource.asInstanceOf[Button])

2
src/main/scala/wow/doge/chatto/controller/WorkspaceController.scala

@ -15,7 +15,7 @@ class WorkspaceController @Inject() (applicationName: ApplicationName)
@FXML
var infoLabel: Label = _
override def didGainVisibilityFirstTime() {
override def didGainVisibilityFirstTime() = {
infoLabel.setText(applicationName.name)
}
}

69
src/main/scala/wow/doge/chatto/service/CustomSerializer.scala

@ -1,69 +0,0 @@
package wow.doge.chatto.service
import org.json4s.CustomSerializer
import org.json4s._
import java.time.Instant
// import org.json4s.JsonAST._
import org.json4s.JsonDSL._
// class ParentSerializer extends Serializer[Parent] {
// private val ParentClass = classOf[Parent]
// implicit val formats = DefaultFormats
// def deserialize(implicit format: Formats): PartialFunction[(TypeInfo, JValue), Parent] = {
// case (TypeInfo(ParentClass, _), json) => json match {
// case JObject(JField("kind", JString(kind)) :: _) => kind match {
// case "first_type" => json.extract[ChildClassOne]
// case "second_type" => json.extract[ChildClassTwo]
// }
// case _ => throw new MappingException("Invalid kind")
// }
// }
// def serialize(implicit format: Formats): PartialFunction[Any, JValue] = Map()
// }
// class MyJInstantSerializer extends Serializer[Instant] {
// implicit val formats = DefaultFormats
// def deserialize(
// implicit format: Formats
// ): PartialFunction[(TypeInfo, JValue), Instant] = {
// case (_, JString(d)) => Instant.parse(d)
// case (_, JNull) => null
// }
// def serialize(implicit format: Formats): PartialFunction[Any, JValue] = {
// case d: Instant => JString(d.toString())
// }
// }
// class MyJInstantSerializer
// extends CustomSerializer[Instant](implicit format =>
// (
// {
// // case JInt(d) => Instant.ofEpochMilli(d.toLong)
// case JString(d) => Instant.parse(d)
// case JNull => null
// }, {
// // case d: Instant => JInt(d.toEpochMilli)
// case d: Instant => JString(d.toString())
// }
// )
// )
// import java.time.ZonedDateTime
// import java.time.format.DateTimeFormatter
// a custom serializer has two partial functions, one
// for serializing and one for deserializing
// case object ZDTSerializer
// extends CustomSerializer[ZonedDateTime](format =>
// ({
// case JString(s) => ZonedDateTime.parse(s)
// }, {
// case zdt: ZonedDateTime =>
// JString(
// zdt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX"))
// )
// })
// )

14
src/main/scala/wow/doge/chatto/service/UserService.scala

@ -52,12 +52,12 @@ class UserService @Inject() (appDataHandler: AppDataHandler)(
private def endpoint(uri: String) = uri"$baseUrl/$uri"
def getUsers(credentials: UserCredentials) = async {
logger.debug(s"${appDataHandler.appData}")
println(
write[ActiveUser](
ActiveUser("hmm what is it", true, Some(ZonedDateTime.now()))
)
)
// logger.debug(s"${appDataHandler.appData}")
// println(
// write[ActiveUser](
// ActiveUser("hmm what is it", true, Some(ZonedDateTime.now()))
// )
// )
await {
authBasicRequest(credentials)
.get(uri"http://localhost:8080/api/chat/get/users")
@ -67,7 +67,7 @@ class UserService @Inject() (appDataHandler: AppDataHandler)(
}
def getMessages(credentials: UserCredentials) = async {
logger.debug(s"${appDataHandler.appData}")
// logger.debug(s"${appDataHandler.appData}")
await {
authBasicRequest(credentials)
.get(uri"http://localhost:8080/api/chat/get/users")

Loading…
Cancel
Save