|
|
@ -33,13 +33,20 @@ import com.sfxcode.sapphire.core.value.FXBeanAdapter |
|
|
|
import scalafx.collections.ObservableMap |
|
|
|
import com.sfxcode.sapphire.core.value.BeanConversions |
|
|
|
import javafx.util.converter.DateStringConverter |
|
|
|
import javafx.beans.binding.Bindings |
|
|
|
import wow.doge.chatto.service.ActiveUser |
|
|
|
import scala.collection.mutable |
|
|
|
import scala.collection.concurrent.TrieMap |
|
|
|
import wow.doge.chatto.messagebuble.BubbleSpec |
|
|
|
import javafx.scene.layout.Background |
|
|
|
import javafx.scene.layout.BackgroundFill |
|
|
|
import javafx.geometry.Pos |
|
|
|
|
|
|
|
class ChatController @Inject() ( |
|
|
|
userService: UserService, |
|
|
|
appDataHandler: AppDataHandler |
|
|
|
) extends AbstractViewController |
|
|
|
with LazyLogging |
|
|
|
with BeanConversions { |
|
|
|
with LazyLogging { |
|
|
|
|
|
|
|
// @FXML private var label: Label = _ |
|
|
|
@FXML private var flowPane: FlowPane = _ |
|
|
@ -49,16 +56,21 @@ class ChatController @Inject() ( |
|
|
|
@FXML private var chatInput: TextArea = _ |
|
|
|
@FXML private var usersVBox: VBox = _ |
|
|
|
@FXML var usersListView: JFXListView[UserBox2] = _ |
|
|
|
@FXML private var chatListView: JFXListView[HBox] = _ |
|
|
|
@FXML var chatListView: JFXListView[HBox] = _ |
|
|
|
@FXML private var curUsr: Label = _ |
|
|
|
@FXML private var dataContent: Label = _ |
|
|
|
// applicationController.show |
|
|
|
private val usersBuffer = ObservableBuffer[FXBean[User]]() |
|
|
|
private val chatDataBuffer = ObservableMap[String, FXBean[User]]() |
|
|
|
private val usersListProperty = new SimpleListProperty( |
|
|
|
ObservableBuffer[UserBox2]() |
|
|
|
) |
|
|
|
private val chatDataBuffer = ObservableBuffer[UserBox2]() |
|
|
|
private val chatDataStore: mutable.Map[String, ChatDataProperty] = |
|
|
|
TrieMap() |
|
|
|
|
|
|
|
private lazy val curUserKeys = KeyBindings("curUser") |
|
|
|
// 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 lazy val curUserAdapter = FXBeanAdapter[User](this) |
|
|
|
private lazy val chatDataAdapter = FXBeanAdapter[ChatData](this) |
|
|
|
|
|
|
|
override def didGainVisibilityFirstTime(): Unit = { |
|
|
|
super.didGainVisibilityFirstTime() |
|
|
@ -99,28 +111,53 @@ class ChatController @Inject() ( |
|
|
|
// .addListener((_, _, newValue) => { |
|
|
|
// curUsr.text() = newValue.usernameLabel.text() |
|
|
|
// }) |
|
|
|
curUserKeys.add("content", "${_self.data().content()}") |
|
|
|
// curUserKeys.add("content", "${_self.data().content()}") |
|
|
|
val chatDataAdapterKeys = KeyBindings() |
|
|
|
// chatDataAdapterKeys.add("currentUser", "${_self.userName()}") |
|
|
|
// chatDataAdapterKeys.add( |
|
|
|
// "lastActive", |
|
|
|
// "${_self.lastActiveString()}" |
|
|
|
// ) |
|
|
|
// chatDataAdapterKeys.add( |
|
|
|
// "online", |
|
|
|
// "${_self.onlineString()}" |
|
|
|
// ) |
|
|
|
// curUserAdapter.addDateConverter() |
|
|
|
curUserAdapter.addBindings(curUserKeys) |
|
|
|
|
|
|
|
// curUserAdapter.addBindings(curUserKeys) |
|
|
|
chatDataAdapter.addBindings(chatDataAdapterKeys) |
|
|
|
// curUsr.text <== chatDataAdapter.beanProperty |
|
|
|
// .getOrElse(FXBean(ChatData.empty)) |
|
|
|
// .getStringProperty("lastActiveString") |
|
|
|
usersListView |
|
|
|
.getSelectionModel() |
|
|
|
.selectedItemProperty() |
|
|
|
.addListener((_, _, newValue) => { |
|
|
|
if (newValue != null) { |
|
|
|
val dataBean = |
|
|
|
FXBean(User(newValue.usernameLabel.text(), Data("test data"))) |
|
|
|
curUserAdapter |
|
|
|
.set(dataBean) |
|
|
|
// 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 |
|
|
|
.map(_.bean) |
|
|
|
.getOrElse { |
|
|
|
logger.error("Error null") |
|
|
|
FXBean(ChatData.empty) |
|
|
|
} |
|
|
|
chatDataAdapter.set(x) |
|
|
|
y.map(z => chatListView.items <== z.prop) |
|
|
|
} |
|
|
|
}) |
|
|
|
|
|
|
|
// curUsr.text <== usersListView |
|
|
|
// .getSelectionModel() |
|
|
|
// .getSelectedItem() |
|
|
|
// .username |
|
|
|
// .usernameLabel |
|
|
|
// .text |
|
|
|
|
|
|
|
usersListView.items <== usersListProperty |
|
|
|
} |
|
|
|
|
|
|
|
override def didGainVisibility(): Unit = { |
|
|
@ -140,7 +177,7 @@ class ChatController @Inject() ( |
|
|
|
// maybeActiveUsers.foreach(println) |
|
|
|
logger.debug(s"$maybeActiveUsers") |
|
|
|
|
|
|
|
val maybeUsersBoxes = maybeUsers.map(users => { |
|
|
|
val maybeUserBoxes = maybeActiveUsers.map(users => { |
|
|
|
// usersBuffer ++= users |
|
|
|
users.map(user => { |
|
|
|
// usersBuffer += FXBean(User(user)) |
|
|
@ -152,7 +189,21 @@ class ChatController @Inject() ( |
|
|
|
// fill <== when(hover) choose (Color.Red) |
|
|
|
// } |
|
|
|
// val hb = new HBox |
|
|
|
new UserBox2(user) { |
|
|
|
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) |
|
|
@ -161,12 +212,22 @@ class ChatController @Inject() ( |
|
|
|
} |
|
|
|
}) |
|
|
|
}) |
|
|
|
// maybeUserBoxes.map(userBoxes => { |
|
|
|
// // chatDataBuffer ++= userBoxes |
|
|
|
// usersListProperty ++= userBoxes |
|
|
|
// }) |
|
|
|
val messageBox = ChatDataProperty.createMdMessageBox("*hello!*") |
|
|
|
onFX { |
|
|
|
maybeUsersBoxes.map(userBoxes => { |
|
|
|
usersListView.items() ++= userBoxes |
|
|
|
// val x = new SimpleListProperty(ObservableBuffer(userBoxes)) |
|
|
|
// usersListView.items <== x |
|
|
|
// maybeUserBoxes.map(userBoxes => { |
|
|
|
// chatDataBuffer ++= userBoxes |
|
|
|
// // usersListView.items() ++= userBoxes |
|
|
|
// // val x = new SimpleListProperty(ObservableBuffer(userBoxes)) |
|
|
|
// // usersListView.items <== x |
|
|
|
// }) |
|
|
|
maybeUserBoxes.map(userBoxes => { |
|
|
|
usersListProperty ++= userBoxes |
|
|
|
}) |
|
|
|
chatListView.items() += messageBox |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -177,17 +238,26 @@ class ChatController @Inject() ( |
|
|
|
x |
|
|
|
} |
|
|
|
|
|
|
|
def actionLogout = { |
|
|
|
def actionLogout = onFX { |
|
|
|
offFXAndWait { |
|
|
|
appDataHandler.clearCredentials() |
|
|
|
println(appDataHandler.appData) |
|
|
|
} |
|
|
|
curUserAdapter.set(User.empty) |
|
|
|
// curUserAdapter.set(User.empty) |
|
|
|
chatDataAdapter.set(FXBean(ChatData.empty)) |
|
|
|
usersListView.items().clear() |
|
|
|
chatListView.items().clear() |
|
|
|
chatDataBuffer.clear() |
|
|
|
chatDataStore.clear() |
|
|
|
usersListProperty.clear() |
|
|
|
applicationController.logout() |
|
|
|
println(appDataHandler.appData) |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
object ChatController { |
|
|
|
lazy val markdownStyleSheet = |
|
|
|
getClass().getResource("/styles/markdown.css").toExternalForm() |
|
|
|
} |
|
|
|
|
|
|
|
final case class Person(id: Int, age: Int, name: String) |
|
|
@ -195,5 +265,58 @@ 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, |
|
|
|
messages: ObservableBuffer[String] |
|
|
|
) { |
|
|
|
lazy val lastActiveString = |
|
|
|
activeUser.lastActive |
|
|
|
.map(_.toString()) |
|
|
|
.getOrElse("User has not logged in yet") |
|
|
|
lazy val onlineString = activeUser.online.toString() |
|
|
|
} |
|
|
|
object ChatData { |
|
|
|
def empty = { |
|
|
|
ChatData("empty", ActiveUser.empty, ObservableBuffer.empty[String]) |
|
|
|
} |
|
|
|
} |
|
|
|
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) |
|
|
|
} |
|
|
|
object ChatDataProperty { |
|
|
|
def createMdMessageBox(mdfxText: String) = { |
|
|
|
val mdfxNode = new BubbledMDFXNode(mdfxText); |
|
|
|
mdfxNode |
|
|
|
.getStylesheets() |
|
|
|
.add(ChatController.markdownStyleSheet); |
|
|
|
mdfxNode.setBubbleSpec(BubbleSpec.FACE_RIGHT_CENTER); |
|
|
|
mdfxNode.setBackground( |
|
|
|
new Background(new BackgroundFill(Color.LIGHTSTEELBLUE, null, null)) |
|
|
|
); |
|
|
|
val box = new HBox(); |
|
|
|
mdfxNode.setMinWidth(100.0); |
|
|
|
box.setAlignment(Pos.TOP_RIGHT); |
|
|
|
box.children += mdfxNode; |
|
|
|
box |
|
|
|
} |
|
|
|
} |
|
|
|
// final case class chatData() |