Commit 32687f79 authored by Ignamarte's avatar Ignamarte

Refactor popovers and add context menu for followed users

parent 434a1e05
Pipeline #104802898 passed with stage
in 2 minutes and 56 seconds
......@@ -6,6 +6,7 @@ import gui.MainWindow
import gui.panels.MainPanel
import gui.widgets.alert.ErrorAlert
import gui.widgets.jfx2sfx.{FAGlyphIcon, Overlay}
import gui.widgets.popover.StreamPopover
import gui.widgets.transitions.FadeIn
import javafx.scene.input.MouseButton
import org.controlsfx.control.PopOver
......
......@@ -2,7 +2,9 @@ package gui.widgets
import api.types.User
import gui.panels.MainPanel
import gui.widgets.popover.UserPopover
import gui.widgets.transitions.FadeIn
import javafx.scene.input.MouseButton
import scalafx.geometry.Pos.Center
import scalafx.scene.Node
import scalafx.scene.control.{Label, ProgressIndicator}
......@@ -37,12 +39,23 @@ class UserCard(user: User) extends VBox {
private val transition = new FadeIn(600, this)
transition.play()
// Context menu
private val contextMenu = new UserPopover(user, true, image)
image.progress.onChange(
(progress,_,_) => if(progress() == 1.0){children.remove(imgProgress)}
)
onMousePressed = e => {
val url = f"https://www.twitch.tv/${user.login}"
Browser.openURL(url)
e.getButton match {
case MouseButton.PRIMARY => {
val url = f"https://www.twitch.tv/${user.login}"
Browser.openURL(url)
}
case MouseButton.SECONDARY => {
contextMenu.show(this)
}
case _ =>
}
}
}
package gui.widgets.popover
import api.types.{Stream, User}
import gui.MainWindow
import gui.panels.MainPanel
import org.controlsfx.control.PopOver
import scalafx.geometry.Insets
import scalafx.geometry.Pos.Center
import scalafx.scene.Node
import scalafx.scene.control.Button
import scalafx.scene.image.{Image, ImageView}
import scalafx.scene.layout.Priority.Always
import scalafx.scene.layout.VBox
import util.Browser
/** Abstract class for building context menu popping up when right clicking
* on a gui element related to a channel (a stream or a user for instance)
*
* This class provides elements common to any channel popover menu but it's up
* to the implementation to choose what to display by constructing the
* childrenList
*
* @constructor Created a context menu for a stream GUI element
* @param followed whether the user is currently following the streamer or not
* @param image a thumbnail used when displaying a notification
* */
abstract class ChannelPopover(followed: Boolean, image: Image) extends PopOver {
// Values required for the menu items provided
val userLogin: String
val userID: String
val userName: String
val childrenList: List[Node]
def display(): Unit
// Container for the menu's content
protected val content: VBox = new VBox(){
minWidth = 150
margin = Insets(10)
spacing = 7
vgrow = Always
alignment = Center
}
// Configuration of the popover
setArrowLocation(PopOver.ArrowLocation.TOP_CENTER)
setContentNode(content)
setDetachable(false)
// Open the channel's page in a browser
protected val channelBtn: Button = new Button {
text = "Channel Page"
prefWidth <== content.width
onAction = _ => {
val url = f"https://www.twitch.tv/${userLogin}"
Browser.openURL(url)
}
}
// Follow or unfollow the streamer
protected val followBtn: Button = new Button{
text = if (followed) "Unfollow" else "Follow"
prefWidth <== content.width
onAction = _ => {
val msg: String = if (followed) {
User.authenticatedUser.unfollow(userID)
MainPanel.displayFollowedPanel()
f"You are not following ${userName} anymore."
}
else {
User.authenticatedUser.follow(userID)
f"You are now following ${userName}."
}
MainWindow.displayNotification(
msg,
new ImageView(image){
fitWidth = 50
preserveRatio = true
}
)
hide() // Hide this menu
}
}
// When displayed, call the implementation of display()
setOnShowing(_ => {
content.children = childrenList
display()
})
}
package gui.widgets
package gui.widgets.popover
import api.types.{Stream, User}
import gui.MainWindow
import gui.panels.MainPanel
import org.controlsfx.control.PopOver
import api.types.Stream
import scalafx.application.Platform
import scalafx.geometry.Insets
import scalafx.geometry.Pos.Center
import scalafx.scene.control.{Button, Label, ProgressIndicator}
import scalafx.scene.image.{Image, ImageView}
import scalafx.scene.layout.Priority.Always
import scalafx.scene.layout.VBox
import scalafx.scene.image.Image
import util.Browser
class StreamPopover(stream: Stream, followed: Boolean, image: Image)
extends PopOver {
/** The context menu popping up when right clicking on a specific stream
*
* The game name is loaded with an async task because twitch's API only returns
* the ID of the game.
*
* @constructor Created a context menu for a stream GUI element
* @param stream the stream object to witch the menu is attached to
* @param followed whether the user is currently following the streamer or not
* @param image the thumbnail of the stream used when displaying a notification
* */
private val content: VBox = new VBox(){
minWidth = 150
margin = Insets(10)
spacing = 7
vgrow = Always
alignment = Center
}
class StreamPopover(stream: Stream, followed: Boolean, image: Image)
extends ChannelPopover(followed, image) {
setArrowLocation(PopOver.ArrowLocation.TOP_CENTER)
setContentNode(content)
setDetachable(false)
val userLogin: String = stream.user_login.get
val userID: String = stream.user_id
val userName: String = stream.user_name
// A loading icon displayed while retrieving the game's name
private val gameNameSpinner = new ProgressIndicator() {
prefWidth <== content.width / 10d
prefHeight <== prefWidth
}
private val channelBtn = new Button {
text = "Channel Page"
prefWidth <== content.width
onAction = _ => {
val url = f"https://www.twitch.tv/${stream.user_login.get}"
Browser.openURL(url)
}
}
// Open the popout chat in a browser
private val chatBtn = new Button {
text = "Chat"
prefWidth <== content.width
......@@ -52,40 +41,18 @@ class StreamPopover(stream: Stream, followed: Boolean, image: Image)
}
}
private val followBtn = new Button{
text = if (followed) "Unfollow" else "Follow"
prefWidth <== content.width
// Set the content of the menu
override val childrenList = List(
new Label(stream.user_name){prefWidth <== content.width},
gameNameSpinner,
channelBtn,
chatBtn,
followBtn
)
onAction = _ => {
if (followed) {
User.authenticatedUser.unfollow(stream.user_id)
MainPanel.displayFollowsPanel()
}
else {
User.authenticatedUser.follow(stream.user_id)
MainWindow.displayNotification(
f"You are now following ${stream.user_name}",
new ImageView(image){
fitWidth = 50
preserveRatio = true
}
)
}
hide()
}
}
setOnShowing(_ => {
content.children = List(
new Label(stream.user_name){prefWidth <== content.width},
gameNameSpinner,
channelBtn,
chatBtn,
followBtn
)
// Get game name
// When displayed, start the async task retrieving the game name and
// add content
override def display(): Unit = {
new Thread() {
override def run(): Unit = {
val gameName = stream.getGameName
......@@ -95,6 +62,6 @@ class StreamPopover(stream: Stream, followed: Boolean, image: Image)
})
}
}.start()
})
}
}
package gui.widgets.popover
import api.types.{Stream, User}
import scalafx.scene.control.Label
import scalafx.scene.image.Image
class UserPopover (user: User, followed: Boolean, image: Image)
extends ChannelPopover(followed, image) {
val userLogin: String = user.login
val userID: String = user.id
val userName: String = user.display_name
override val childrenList = List(
new Label(user.display_name){prefWidth <== content.width},
channelBtn,
followBtn
)
override def display(): Unit = {}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment