463 lines
17 KiB
Lua
463 lines
17 KiB
Lua
local GuiService = game:GetService("GuiService")
|
|
local Modules = game:GetService("CoreGui").RobloxGui.Modules
|
|
local UserInputService = game:GetService("UserInputService")
|
|
|
|
local Constants = require(Modules.LuaChat.Constants)
|
|
local ConversationActions = require(Modules.LuaChat.Actions.ConversationActions)
|
|
local formatInteger = require(Modules.LuaChat.Utils.formatInteger)
|
|
local LocalizedTextLabel = require(Modules.LuaApp.Components.LocalizedTextLabel)
|
|
local Roact = require(Modules.Common.Roact)
|
|
local RoactAnalyticsSharedGameItem = require(Modules.LuaChat.Services.RoactAnalyticsSharedGameItem)
|
|
local RoactRodux = require(Modules.Common.RoactRodux)
|
|
local RoactServices = require(Modules.LuaApp.RoactServices)
|
|
local Text = require(Modules.Common.Text)
|
|
|
|
local DEFAULT_BACKGROUND_COLOR = Constants.Color.WHITE
|
|
local DEFAULT_GAME_ADDITIONAL_INFO_LABEL_HEIGHT = 14
|
|
local DEFAULT_GAME_ADDITIONAL_INFO_LABEL_TEXT_SIZE = 14
|
|
local DEFAULT_GAME_CREATOR_LABEL_BOTTOM_PADDING = 3
|
|
local DEFAULT_GAME_CREATOR_LABEL_COLOR = Constants.Color.GRAY2
|
|
local DEFAULT_GAME_CREATOR_LABEL_HEIGHT = 14
|
|
local DEFAULT_GAME_CREATOR_LABEL_TEXT_SIZE = 15
|
|
local DEFAULT_GAME_CREATOR_LABEL_TOP_PADDING = 6
|
|
local DEFAULT_GAME_NAME_LABEL_COLOR = Constants.Color.GRAY1
|
|
local DEFAULT_GAME_NAME_LABEL_HEIGHT = 20
|
|
local DEFAULT_GAME_NAME_LABEL_TEXT_SIZE = 23
|
|
local DEFAULT_GAME_ICON_LEFT_PADDING = 15
|
|
local DEFAULT_GAME_ICON_RIGHT_PADDING = 12
|
|
local DEFAULT_GAME_ICON_SIZE = Constants.SharedGamesConfig.Thumbnail.SHOWN_SIZE
|
|
local DEFAULT_GAME_ICON_TOP_PADDING = 12
|
|
local DEFAULT_ITEM_HEIGHT = 84
|
|
local DEFAULT_ITEM_PRESSED_BACKGROUND_COLOR = Constants.Color.GRAY5
|
|
local DEFAULT_PRICE_COLOR = Constants.Color.GREEN_PRIMARY
|
|
local DEFAULT_ROBUX_ICON_SIZE = 12
|
|
local DEFAULT_SEND_BUTTON_ICON_SIZE = 24
|
|
local DEFAULT_SEND_BUTTON_LEFT_PADDING = 12
|
|
local DEFAULT_SEND_BUTTON_RIGHT_PADDING = 25
|
|
local DEFAULT_SEPARATOR_LINE_COLOR = Constants.Color.GRAY4
|
|
local DEFAULT_TEXT_FONT = Enum.Font.SourceSans
|
|
|
|
local GAME_LOADING_ICON = "rbxasset://textures/ui/LuaApp/icons/ic-game.png"
|
|
local GAME_BORDER_ICON = "rbxasset://textures/ui/LuaChat/graphic/gr-game-border-60x60.png"
|
|
local ROBUX_ICON = "rbxasset://textures/ui/LuaChat/icons/ic-robux.png"
|
|
local SEND_BUTTON_ICON = "rbxasset://textures/ui/LuaChat/icons/icon-share-game-24x24.png"
|
|
local SENT_BUTTON_ICON = "rbxasset://textures/ui/LuaChat/icons/icon-share-game-pressed-24x24.png"
|
|
|
|
local SharedGameItem = Roact.PureComponent:extend("SharedGameItem")
|
|
|
|
SharedGameItem.defaultProps = {
|
|
backgroundColor = DEFAULT_BACKGROUND_COLOR,
|
|
gameAdditionalLabelHeight = DEFAULT_GAME_ADDITIONAL_INFO_LABEL_HEIGHT,
|
|
gameAdditionalLabelTextSize = DEFAULT_GAME_ADDITIONAL_INFO_LABEL_TEXT_SIZE,
|
|
gameCreatorLabelBottomPadding = DEFAULT_GAME_CREATOR_LABEL_BOTTOM_PADDING,
|
|
gameCreatorLabelColor = DEFAULT_GAME_CREATOR_LABEL_COLOR,
|
|
gameCreatorLabelHeight = DEFAULT_GAME_CREATOR_LABEL_HEIGHT,
|
|
gameCreatorLabelTopPadding = DEFAULT_GAME_CREATOR_LABEL_TOP_PADDING,
|
|
gameCreatorLabelTextSize = DEFAULT_GAME_CREATOR_LABEL_TEXT_SIZE,
|
|
gameIconSize = DEFAULT_GAME_ICON_SIZE,
|
|
gameIconLeftPadding = DEFAULT_GAME_ICON_LEFT_PADDING,
|
|
gameIconRightPadding = DEFAULT_GAME_ICON_RIGHT_PADDING,
|
|
gameIconTopPadding = DEFAULT_GAME_ICON_TOP_PADDING,
|
|
gameNameLabelColor = DEFAULT_GAME_NAME_LABEL_COLOR,
|
|
gameNameLabelHeight = DEFAULT_GAME_NAME_LABEL_HEIGHT,
|
|
gameNameLabelTextSize = DEFAULT_GAME_NAME_LABEL_TEXT_SIZE,
|
|
itemPressedBackgroundColor = DEFAULT_ITEM_PRESSED_BACKGROUND_COLOR,
|
|
itemHeight = DEFAULT_ITEM_HEIGHT,
|
|
priceColor = DEFAULT_PRICE_COLOR,
|
|
robuxIconSize = DEFAULT_ROBUX_ICON_SIZE,
|
|
sendButtonIconSize = DEFAULT_SEND_BUTTON_ICON_SIZE,
|
|
sendButtonLeftPadding = DEFAULT_SEND_BUTTON_LEFT_PADDING,
|
|
sendButtonRightPadding = DEFAULT_SEND_BUTTON_RIGHT_PADDING,
|
|
separatorLineColor = DEFAULT_SEPARATOR_LINE_COLOR,
|
|
textFont = DEFAULT_TEXT_FONT
|
|
}
|
|
|
|
function SharedGameItem:init()
|
|
self.state = {
|
|
gameItemDown = false,
|
|
gameItemActivated = false,
|
|
sendButtonDown = false,
|
|
sendButtonActivated = false,
|
|
}
|
|
|
|
self.creatorName = nil
|
|
self.gameNameTextLabel = nil
|
|
self.gameCreatorTextLabel = nil
|
|
|
|
self.onGameButtonActivated = function()
|
|
self:openGameDetails()
|
|
end
|
|
|
|
self.onSendButtonInputBegan = function(_, inputObject)
|
|
if (inputObject.UserInputType == Enum.UserInputType.Touch or
|
|
inputObject.UserInputType == Enum.UserInputType.MouseButton1) and
|
|
inputObject.UserInputState == Enum.UserInputState.Begin then
|
|
self:onSendButtonDown()
|
|
end
|
|
end
|
|
|
|
self.onSendButtonInputEnded = function(_, inputObject)
|
|
self:onSendButtonUp()
|
|
end
|
|
|
|
self.onGameItemInputBegan = function(_, inputObject)
|
|
if (inputObject.UserInputType == Enum.UserInputType.Touch or
|
|
inputObject.UserInputType == Enum.UserInputType.MouseButton1) and
|
|
inputObject.UserInputState == Enum.UserInputState.Begin then
|
|
self:onGameItemDown()
|
|
end
|
|
end
|
|
|
|
self.onGameItemInputEnded = function(_, inputObject)
|
|
self:onGameItemUp()
|
|
end
|
|
end
|
|
|
|
function SharedGameItem:onSendButtonDown()
|
|
if not self.state.sendButtonDown then
|
|
self:eventDisconnect()
|
|
|
|
self.userInputServiceCon = UserInputService.InputEnded:Connect(function()
|
|
self:onSendButtonUp()
|
|
end)
|
|
|
|
self:setState({
|
|
sendButtonDown = true,
|
|
sendButtonActivated = false,
|
|
})
|
|
end
|
|
end
|
|
|
|
function SharedGameItem:onSendButtonUp(buttonActivated)
|
|
if self.state.sendButtonDown or self.state.sendButtonActivated ~= buttonActivated then
|
|
self:setState({
|
|
sendButtonDown = false,
|
|
sendButtonActivated = buttonActivated,
|
|
})
|
|
end
|
|
|
|
self:eventDisconnect()
|
|
end
|
|
|
|
function SharedGameItem:onGameItemDown()
|
|
if not self.state.gameItemDown then
|
|
self:eventDisconnect()
|
|
|
|
self.userInputServiceCon = UserInputService.InputEnded:Connect(function()
|
|
self:onGameItemUp()
|
|
end)
|
|
|
|
self:setState({
|
|
gameItemDown = true,
|
|
gameItemActivated = false,
|
|
})
|
|
end
|
|
end
|
|
|
|
function SharedGameItem:onGameItemUp(buttonActivated)
|
|
if self.state.gameItemDown or self.state.gameItemActivated ~= buttonActivated then
|
|
self:setState({
|
|
gameItemDown = false,
|
|
gameItemActivated = buttonActivated,
|
|
})
|
|
end
|
|
|
|
self:eventDisconnect()
|
|
end
|
|
|
|
function SharedGameItem:openGameDetails()
|
|
local notificationType = GuiService:GetNotificationTypeList().VIEW_GAME_DETAILS_ANIMATED
|
|
GuiService:BroadcastNotification(string.format("%d", self.props.game.placeId), notificationType)
|
|
end
|
|
|
|
function SharedGameItem:render()
|
|
local activeConversationId = self.props.activeConversationId
|
|
local analytics = self.props.analytics
|
|
local backgroundColor = self.props.backgroundColor
|
|
local gameAdditionalLabelHeight = self.props.gameAdditionalLabelHeight
|
|
local gameAdditionalLabelTextSize = self.props.gameAdditionalLabelTextSize
|
|
local gameCreatorLabelBottomPadding = self.props.gameCreatorLabelBottomPadding
|
|
local gameCreatorLabelColor = self.props.gameCreatorLabelColor
|
|
local gameCreatorLabelHeight = self.props.gameCreatorLabelHeight
|
|
local gameCreatorLabelTextSize = self.props.gameCreatorLabelTextSize
|
|
local gameCreatorLabelTopPadding = self.props.gameCreatorLabelTopPadding
|
|
local gameIconLeftPadding = self.props.gameIconLeftPadding
|
|
local gameIconRightPadding = self.props.gameIconRightPadding
|
|
local gameIconSize = self.props.gameIconSize
|
|
local gameIconTopPadding = self.props.gameIconTopPadding
|
|
local gameIconWidth = gameIconSize + gameIconLeftPadding + gameIconRightPadding
|
|
local gameNameLabelHeight = self.props.gameNameLabelHeight
|
|
local gameNameLabelColor = self.props.gameNameLabelColor
|
|
local gameNameLabelTextSize = self.props.gameNameLabelTextSize
|
|
local gameThumbnails = self.props.gameThumbnails
|
|
local gameUrl = self.props.game.url
|
|
local itemHeight = self.props.itemHeight
|
|
local itemPressedBackgroundColor = self.props.itemPressedBackgroundColor
|
|
local isSharing = self.props.isSharing
|
|
local placeId = tostring(self.props.game.placeId)
|
|
local playable = self.props.game.isPlayable
|
|
local priceColor = self.props.priceColor
|
|
local robuxIconSize = self.props.robuxIconSize
|
|
local sendButtonIconSize = self.props.sendButtonIconSize
|
|
local sendButtonLeftPadding = self.props.sendButtonLeftPadding
|
|
local sendButtonRightPadding = self.props.sendButtonRightPadding
|
|
local sendButtonWidth = sendButtonIconSize + sendButtonLeftPadding + sendButtonRightPadding
|
|
local separatorLineColor = self.props.separatorLineColor
|
|
local textFont = self.props.textFont
|
|
|
|
local additionalInfoFrameHeight = gameAdditionalLabelHeight + gameCreatorLabelBottomPadding
|
|
local showPrice = self.props.game.price ~= nil and playable
|
|
local showAdditionalInfo = showPrice or (not playable)
|
|
local gameIcon = gameThumbnails[placeId] or GAME_LOADING_ICON
|
|
local gameInfoHeight = showAdditionalInfo and
|
|
(gameNameLabelHeight + gameCreatorLabelHeight + 2 * gameCreatorLabelBottomPadding + gameAdditionalLabelHeight) or
|
|
(gameNameLabelHeight + gameCreatorLabelHeight + gameCreatorLabelBottomPadding)
|
|
|
|
|
|
return Roact.createElement("Frame", {
|
|
BackgroundColor3 = self.state.gameItemDown and itemPressedBackgroundColor or backgroundColor,
|
|
BorderSizePixel = 0,
|
|
Size = UDim2.new(1, 0, 0, itemHeight),
|
|
},{
|
|
Separator = Roact.createElement("Frame", {
|
|
AnchorPoint = Vector2.new(0, 1),
|
|
BackgroundColor3 = separatorLineColor,
|
|
BorderSizePixel = 0,
|
|
Position = UDim2.new(0, gameIconWidth, 1, 0),
|
|
Size = UDim2.new(1, -gameIconWidth, 0, 1),
|
|
}),
|
|
|
|
Game = Roact.createElement("Frame", {
|
|
BackgroundTransparency = 1,
|
|
BorderSizePixel = 0,
|
|
Size = UDim2.new(1, 0, 0, itemHeight),
|
|
}, {
|
|
Layout = Roact.createElement("UIListLayout", {
|
|
FillDirection = Enum.FillDirection.Horizontal,
|
|
SortOrder = Enum.SortOrder.LayoutOrder,
|
|
VerticalAlignment = Enum.VerticalAlignment.Center,
|
|
}),
|
|
|
|
GameButtonContainer = Roact.createElement("TextButton", {
|
|
BackgroundTransparency = 1,
|
|
LayoutOrder = 1,
|
|
Size = UDim2.new(1, -sendButtonWidth, 1, 0),
|
|
Text = "",
|
|
|
|
[Roact.Event.Activated] = self.onGameButtonActivated,
|
|
[Roact.Event.InputBegan] = self.onGameItemInputBegan,
|
|
[Roact.Event.InputEnded] = self.onGameItemInputEnded,
|
|
},{
|
|
Icon = Roact.createElement("ImageLabel", {
|
|
BackgroundTransparency = 1,
|
|
BorderSizePixel = 0,
|
|
Image = gameIcon,
|
|
Position = UDim2.new(0, gameIconLeftPadding, 0, gameIconTopPadding),
|
|
Size = UDim2.new(0, gameIconSize, 0, gameIconSize),
|
|
}, {
|
|
RoundCornerOverlay = Roact.createElement("ImageLabel", {
|
|
BackgroundTransparency = 1,
|
|
BorderSizePixel = 0,
|
|
Image = GAME_BORDER_ICON,
|
|
Size = UDim2.new(0, gameIconSize, 0, gameIconSize),
|
|
}),
|
|
}),
|
|
|
|
GameInfo = Roact.createElement("Frame", {
|
|
AnchorPoint = Vector2.new(0, 0.5),
|
|
BackgroundTransparency = 1,
|
|
BorderSizePixel = 0,
|
|
Position = UDim2.new(0, gameIconWidth, 0.5, 0),
|
|
Size = UDim2.new(1, -gameIconWidth, 0, gameInfoHeight),
|
|
}, {
|
|
Layout = Roact.createElement("UIListLayout", {
|
|
FillDirection = Enum.FillDirection.Vertical,
|
|
SortOrder = Enum.SortOrder.LayoutOrder,
|
|
VerticalAlignment = Enum.VerticalAlignment.Center,
|
|
}),
|
|
|
|
Name = Roact.createElement("TextLabel", {
|
|
BackgroundTransparency = 1,
|
|
BorderSizePixel = 0,
|
|
Font = textFont,
|
|
LayoutOrder = 1,
|
|
Size = UDim2.new(1, 0, 0, gameNameLabelHeight),
|
|
Text = self.props.game.name,
|
|
TextColor3 = gameNameLabelColor,
|
|
TextSize = gameNameLabelTextSize,
|
|
TextXAlignment = Enum.TextXAlignment.Left,
|
|
TextYAlignment = Enum.TextYAlignment.Center,
|
|
[Roact.Ref] = function(rbx)
|
|
if rbx then
|
|
self.gameNameTextLabel = rbx
|
|
end
|
|
end,
|
|
}),
|
|
|
|
Creator = Roact.createElement(LocalizedTextLabel, {
|
|
BackgroundTransparency = 1,
|
|
BorderSizePixel = 0,
|
|
Font = textFont,
|
|
LayoutOrder = 2,
|
|
Size = UDim2.new(1, 0, 0, gameCreatorLabelHeight + gameCreatorLabelTopPadding),
|
|
Text = {"Feature.Chat.ShareGameToChat.By", creatorName = self.props.game.creatorName},
|
|
TextColor3 = gameCreatorLabelColor,
|
|
TextSize = gameCreatorLabelTextSize,
|
|
TextXAlignment = Enum.TextXAlignment.Left,
|
|
TextYAlignment = Enum.TextYAlignment.Bottom,
|
|
|
|
[Roact.Ref] = function(rbx)
|
|
if rbx then
|
|
self.gameCreatorTextLabel = rbx
|
|
self.creatorName = rbx.Text
|
|
end
|
|
end
|
|
}),
|
|
|
|
NotAvailableTip = not playable and Roact.createElement(LocalizedTextLabel, {
|
|
BackgroundTransparency = 1,
|
|
BorderSizePixel = 0,
|
|
Font = textFont,
|
|
LayoutOrder = 3,
|
|
Size = UDim2.new(1, 0, 0, additionalInfoFrameHeight),
|
|
Text = "Feature.Chat.ShareGameToChat.GameNotAvailable",
|
|
TextColor3 = gameCreatorLabelColor,
|
|
TextSize = gameAdditionalLabelTextSize,
|
|
TextXAlignment = Enum.TextXAlignment.Left,
|
|
TextYAlignment = Enum.TextYAlignment.Bottom,
|
|
}),
|
|
|
|
GamePrice = showPrice and Roact.createElement("Frame", {
|
|
BackgroundTransparency = 1,
|
|
BorderSizePixel = 0,
|
|
LayoutOrder = 3,
|
|
Size = UDim2.new(1, 0, 0, additionalInfoFrameHeight),
|
|
}, {
|
|
Layout = Roact.createElement("UIListLayout", {
|
|
FillDirection = Enum.FillDirection.Horizontal,
|
|
SortOrder = Enum.SortOrder.LayoutOrder,
|
|
VerticalAlignment = Enum.VerticalAlignment.Bottom,
|
|
Padding = UDim.new(0, 3),
|
|
}),
|
|
|
|
RobuxIcon = Roact.createElement("ImageLabel", {
|
|
BackgroundTransparency = 1,
|
|
BorderSizePixel = 0,
|
|
Image = ROBUX_ICON,
|
|
LayoutOrder = 1,
|
|
ScaleType = Enum.ScaleType.Fit,
|
|
Size = UDim2.new(0, robuxIconSize, 0, robuxIconSize),
|
|
}),
|
|
|
|
Price = Roact.createElement("TextLabel",{
|
|
BackgroundTransparency = 1,
|
|
Size = UDim2.new(1, -15, 1, 0),
|
|
Font = DEFAULT_TEXT_FONT,
|
|
LayoutOrder = 2,
|
|
Text = formatInteger(self.props.game.price),
|
|
TextColor3 = priceColor,
|
|
TextSize = gameAdditionalLabelTextSize,
|
|
TextXAlignment = Enum.TextXAlignment.Left,
|
|
TextYAlignment = Enum.TextYAlignment.Bottom,
|
|
}, {
|
|
padding = Roact.createElement("UIPadding", {
|
|
PaddingLeft = UDim.new(3, 0),
|
|
}),
|
|
}),
|
|
}),
|
|
})
|
|
}),
|
|
|
|
SendButtonContainer = Roact.createElement("TextButton", {
|
|
Active = not isSharing,
|
|
BackgroundTransparency = 1,
|
|
ClipsDescendants = true,
|
|
LayoutOrder = 2,
|
|
Position = UDim2.new(1, -sendButtonWidth, 0, 0),
|
|
Size = UDim2.new(0, sendButtonWidth, 1, 0),
|
|
Text = "",
|
|
|
|
[Roact.Event.InputBegan] = self.onSendButtonInputBegan,
|
|
[Roact.Event.InputEnded] = self.onSendButtonInputEnded,
|
|
[Roact.Event.Activated] = function()
|
|
if not isSharing then
|
|
self.props.shareGameToChat(activeConversationId, analytics, placeId, gameUrl)
|
|
end
|
|
end,
|
|
},{
|
|
SendButton = Roact.createElement("ImageLabel", {
|
|
AnchorPoint = Vector2.new(0, 0.5),
|
|
BackgroundTransparency = 1,
|
|
BorderSizePixel = 0,
|
|
ClipsDescendants = false,
|
|
Image = self.state.sendButtonDown and SENT_BUTTON_ICON or SEND_BUTTON_ICON,
|
|
Position = UDim2.new(0, sendButtonLeftPadding, 0.5, 0),
|
|
Size = UDim2.new(0, sendButtonIconSize, 0, sendButtonIconSize),
|
|
}),
|
|
}),
|
|
})
|
|
})
|
|
end
|
|
|
|
function SharedGameItem:didMount()
|
|
local function resizeGameName()
|
|
self.gameNameTextLabel.Text = Text.Truncate(self.props.game.name, self.props.textFont,
|
|
self.gameNameTextLabel.TextSize, self.gameNameTextLabel.AbsoluteSize.X, "...")
|
|
end
|
|
|
|
local function resizeGameCreator()
|
|
self.gameCreatorTextLabel.Text = Text.Truncate(self.creatorName, self.props.textFont,
|
|
self.gameCreatorTextLabel.TextSize, self.gameCreatorTextLabel.AbsoluteSize.X, "...")
|
|
end
|
|
|
|
resizeGameName()
|
|
resizeGameCreator()
|
|
|
|
self.connections = {}
|
|
table.insert(self.connections, self.gameNameTextLabel:GetPropertyChangedSignal("Text"):Connect(resizeGameName))
|
|
table.insert(self.connections, self.gameNameTextLabel:GetPropertyChangedSignal("AbsoluteSize"):Connect(resizeGameName))
|
|
table.insert(self.connections, self.gameCreatorTextLabel:GetPropertyChangedSignal("Text"):Connect(resizeGameCreator))
|
|
table.insert(
|
|
self.connections,
|
|
self.gameCreatorTextLabel:GetPropertyChangedSignal("AbsoluteSize"):Connect(resizeGameCreator)
|
|
)
|
|
end
|
|
|
|
function SharedGameItem:willUnmount()
|
|
for _, connection in pairs(self.connections) do
|
|
connection:Disconnect()
|
|
end
|
|
|
|
self:eventDisconnect()
|
|
end
|
|
|
|
function SharedGameItem:eventDisconnect()
|
|
if self.userInputServiceCon then
|
|
self.userInputServiceCon:Disconnect()
|
|
self.userInputServiceCon = nil
|
|
end
|
|
end
|
|
|
|
SharedGameItem = RoactRodux.UNSTABLE_connect2(
|
|
function(state, props)
|
|
return {
|
|
activeConversationId = state.ChatAppReducer.ActiveConversationId,
|
|
gameThumbnails = state.GameThumbnails,
|
|
isSharing = state.ChatAppReducer.ShareGameToChatAsync.sharingGame,
|
|
}
|
|
end,
|
|
function(dispatch)
|
|
return {
|
|
shareGameToChat = function(activeConversationId, analytics, placeId, url)
|
|
analytics.reportShareGameToChatFromChat(activeConversationId, tostring(placeId))
|
|
return dispatch(ConversationActions.ShareGame(activeConversationId, url))
|
|
end,
|
|
}
|
|
end
|
|
)(SharedGameItem)
|
|
|
|
SharedGameItem = RoactServices.connect({
|
|
analytics = RoactAnalyticsSharedGameItem,
|
|
})(SharedGameItem)
|
|
|
|
return SharedGameItem |