add gs
This commit is contained in:
+423
@@ -0,0 +1,423 @@
|
||||
local CoreGui = game:GetService("CoreGui")
|
||||
local GuiService = game:GetService("GuiService")
|
||||
local PlayerService = game:GetService("Players")
|
||||
|
||||
local Modules = CoreGui.RobloxGui.Modules
|
||||
|
||||
local LuaApp = Modules.LuaApp
|
||||
local LuaChat = Modules.LuaChat
|
||||
|
||||
local Create = require(LuaChat.Create)
|
||||
local Constants = require(LuaChat.Constants)
|
||||
local DialogInfo = require(LuaChat.DialogInfo)
|
||||
local ConversationActions = require(LuaChat.Actions.ConversationActions)
|
||||
local GetMultiplePlaceInfos = require(LuaChat.Actions.GetMultiplePlaceInfos)
|
||||
local HeaderLoader = require(LuaChat.Components.HeaderLoader)
|
||||
local PlaceInfoCard = require(LuaChat.Components.PlaceInfoCard)
|
||||
local GameShareCard = require(LuaChat.Components.GameShareCard)
|
||||
local ConversationList = require(LuaChat.Components.ConversationList)
|
||||
local getInputEvent = require(LuaChat.Utils.getInputEvent)
|
||||
local truncateAssetLink = require(LuaChat.Utils.truncateAssetLink)
|
||||
local FlagSettings = require(LuaApp.FlagSettings)
|
||||
|
||||
local HttpStatus = require(LuaChat.WebApi).Status
|
||||
|
||||
local ToastModel = require(LuaChat.Models.ToastModel)
|
||||
local ShowToast = require(LuaChat.Actions.ShowToast)
|
||||
|
||||
local NavigateBack = require(Modules.LuaApp.Thunks.NavigateBack)
|
||||
local RemoveRoute = require(LuaChat.Actions.RemoveRoute)
|
||||
local SetAppLoaded = require(LuaChat.Actions.SetAppLoaded)
|
||||
|
||||
local NotificationType = require(LuaApp.Enum.NotificationType)
|
||||
|
||||
local Intent = DialogInfo.Intent
|
||||
|
||||
local FFlagLuaChatToSplitRbxConnections = settings():GetFFlag("LuaChatToSplitRbxConnections")
|
||||
local FFlagShareGameToChatStatusAnalytics = settings():GetFFlag("ShareGameToChatStatusAnalytics")
|
||||
|
||||
local GameShareComponent = {}
|
||||
GameShareComponent.__index = GameShareComponent
|
||||
|
||||
local ICON_CELL_WIDTH = 60
|
||||
local SEARCH_BOX_HEIGHT = 48
|
||||
local CLEAR_TEXT_WIDTH = 44
|
||||
local PLACE_INFO_FRAME_HEIGHT = 84
|
||||
|
||||
local function requestOlderConversations(appState)
|
||||
-- Don't fetch older conversations if the oldest conversation has already been fetched.
|
||||
if appState.store:getState().ChatAppReducer.ConversationsAsync.oldestConversationIsFetched then
|
||||
return
|
||||
end
|
||||
|
||||
-- Ask for new conversations
|
||||
local convoCount = 0
|
||||
for _, _ in pairs(appState.store:getState().ChatAppReducer.Conversations) do
|
||||
convoCount = convoCount + 1
|
||||
end
|
||||
local pageSize = Constants.PageSize.GET_CONVERSATIONS
|
||||
local currentPage = math.floor(convoCount / pageSize)
|
||||
spawn(function()
|
||||
appState.store:dispatch(ConversationActions.GetLocalUserConversationsAsync(currentPage + 1, pageSize))
|
||||
end)
|
||||
end
|
||||
|
||||
function GameShareComponent.new(appState, placeId, innerFrame)
|
||||
local self = {}
|
||||
self._analytics = appState.analytics
|
||||
self.appState = appState
|
||||
self.placeId = placeId
|
||||
self.placeInfo = appState.store:getState().ChatAppReducer.PlaceInfos[placeId]
|
||||
setmetatable(self, GameShareComponent)
|
||||
|
||||
-- Header
|
||||
self.header = HeaderLoader.GetHeader(appState, Intent.GameShare)
|
||||
self.header:SetDefaultSubtitle()
|
||||
self.header:SetTitle(appState.localization:Format("Feature.Chat.Heading.ShareGameToChat"))
|
||||
self.header:SetBackButtonEnabled(true)
|
||||
|
||||
-- Place Info Card Frame
|
||||
self.placeInfoCardFrame = Create.new"Frame" {
|
||||
Name = "PlaceInfoCardFrame",
|
||||
BackgroundColor3 = Constants.Color.GRAY5,
|
||||
BorderSizePixel = 0,
|
||||
Size = UDim2.new(1, 0, 0, PLACE_INFO_FRAME_HEIGHT),
|
||||
LayoutOrder = 2,
|
||||
}
|
||||
|
||||
-- Search Container
|
||||
self.searchContainer = Create.new"Frame" {
|
||||
Name = "SearchContainer",
|
||||
BackgroundTransparency = 0,
|
||||
BackgroundColor3 = Constants.Color.WHITE,
|
||||
BorderSizePixel = 0,
|
||||
Size = UDim2.new(1, 0, 0, SEARCH_BOX_HEIGHT),
|
||||
Visible = false,
|
||||
LayoutOrder = 3,
|
||||
|
||||
Create.new"ImageLabel" {
|
||||
Name = "SearchIcon",
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.new(0, 24, 0, 24),
|
||||
Position = UDim2.new(0, ICON_CELL_WIDTH/2, 0.5, 0),
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
ImageColor3 = Constants.Color.GRAY3,
|
||||
Image = "rbxasset://textures/ui/LuaChat/icons/ic-search.png",
|
||||
},
|
||||
Create.new"TextBox" {
|
||||
Name = "Search",
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.new(1, -CLEAR_TEXT_WIDTH-ICON_CELL_WIDTH, 1, 0),
|
||||
Position = UDim2.new(0, ICON_CELL_WIDTH, 0, 0),
|
||||
TextSize = Constants.Font.FONT_SIZE_18,
|
||||
TextColor3 = Constants.Color.GRAY1,
|
||||
Font = Enum.Font.SourceSans,
|
||||
Text = "",
|
||||
PlaceholderText = appState.localization:Format("Feature.Chat.Label.SearchForFriendsAndChat"),
|
||||
PlaceholderColor3 = Constants.Color.GRAY3,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
OverlayNativeInput = true,
|
||||
ClearTextOnFocus = false,
|
||||
ClipsDescendants = true,
|
||||
},
|
||||
Create.new"ImageButton" {
|
||||
Name = "Clear",
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.new(0, 16, 0, 16),
|
||||
Position = UDim2.new(1, -(CLEAR_TEXT_WIDTH/2), 0.5, 0),
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
AutoButtonColor = false,
|
||||
Image = "rbxasset://textures/ui/LuaChat/icons/ic-clear-solid.png",
|
||||
ImageTransparency = 1,
|
||||
},
|
||||
}
|
||||
self.clearSearchButton = self.searchContainer.Clear
|
||||
self.searchBox = self.searchContainer.Search
|
||||
self.SearchFilterPredicate = function(other)
|
||||
if self.searchBox.Text == "" then
|
||||
return true
|
||||
end
|
||||
return string.find(string.lower(other), string.lower(self.searchBox.Text), 1, true) ~= nil
|
||||
end
|
||||
|
||||
local divider = Create.new"Frame" {
|
||||
Name = "Divider",
|
||||
BackgroundColor3 = Constants.Color.GRAY4,
|
||||
BorderSizePixel = 0,
|
||||
Size = UDim2.new(1, 0, 0, 1),
|
||||
LayoutOrder = 4,
|
||||
}
|
||||
|
||||
-- Conversation List Frame
|
||||
self.conversationListFrame = Create.new "Frame" {
|
||||
Name = "ConversationListFrame",
|
||||
BackgroundTransparency = 1,
|
||||
BorderSizePixel = 0,
|
||||
LayoutOrder = 5,
|
||||
Size = UDim2.new(1, 0, 1, - self.header.rbx.Size.Y.Offset - SEARCH_BOX_HEIGHT - PLACE_INFO_FRAME_HEIGHT),
|
||||
}
|
||||
|
||||
self.placeInfoCardFrame.Parent = innerFrame
|
||||
self.searchContainer.Parent = innerFrame
|
||||
divider.Parent = innerFrame
|
||||
self.conversationListFrame.Parent = innerFrame
|
||||
|
||||
self.rbx = Create.new"ImageButton" {
|
||||
Active = true,
|
||||
AutoButtonColor = false,
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundColor3 = Constants.Color.GRAY5,
|
||||
BorderSizePixel = 0,
|
||||
|
||||
Create.new("UIListLayout") {
|
||||
Name = "ListLayout",
|
||||
SortOrder = "LayoutOrder",
|
||||
HorizontalAlignment = "Center",
|
||||
},
|
||||
|
||||
self.header.rbx,
|
||||
innerFrame,
|
||||
}
|
||||
|
||||
if not appState.store:getState().ChatAppReducer.AppLoaded then
|
||||
spawn(function()
|
||||
appState.store:dispatch(
|
||||
ConversationActions.GetLocalUserConversationsAsync(1, Constants.PageSize.GET_CONVERSATIONS)
|
||||
):andThen(function()
|
||||
appState.store:dispatch(SetAppLoaded(true))
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function GameShareComponent:Start()
|
||||
local isLuaAppStarterScriptEnabled = FlagSettings:IsLuaAppStarterScriptEnabled()
|
||||
|
||||
self.connections = {}
|
||||
|
||||
-- back button
|
||||
local backButtonConnection
|
||||
if isLuaAppStarterScriptEnabled then
|
||||
backButtonConnection = self.header.BackButtonPressed:connect(function()
|
||||
self.appState.store:dispatch(NavigateBack())
|
||||
GuiService:BroadcastNotification("", NotificationType.CLOSE_MODAL)
|
||||
end)
|
||||
else
|
||||
backButtonConnection = self.header.BackButtonPressed:connect(function()
|
||||
self.appState.store:dispatch(RemoveRoute(DialogInfo.Intent.GameShare))
|
||||
GuiService:BroadcastNotification("", NotificationType.CLOSE_MODAL)
|
||||
end)
|
||||
end
|
||||
table.insert(self.connections, backButtonConnection)
|
||||
|
||||
-- update
|
||||
local appStateConnection = self.appState.store.changed:connect(function(state, oldState)
|
||||
self:Update(state, oldState)
|
||||
end)
|
||||
table.insert(self.connections, appStateConnection)
|
||||
|
||||
-- search clear button
|
||||
local clearButtonConnection = getInputEvent(self.clearSearchButton):Connect(function()
|
||||
self.searchBox.Text = ""
|
||||
end)
|
||||
if FFlagLuaChatToSplitRbxConnections then
|
||||
table.insert(self.rbx_connections, clearButtonConnection)
|
||||
else
|
||||
table.insert(self.connections, clearButtonConnection)
|
||||
end
|
||||
|
||||
local function updateClearButtonVisibility()
|
||||
-- If we were to set the visible property of the clear button on the textbox focus lost event
|
||||
-- it would disable the clear button, which in turn would stop the click event
|
||||
-- from being able to notify the button
|
||||
local visible = self.searchBox:IsFocused() and (self.searchBox.Text ~= "")
|
||||
self.clearSearchButton.ImageTransparency = visible and 0 or 1
|
||||
end
|
||||
|
||||
-- search box
|
||||
local searchChangedConnection = self.searchBox:GetPropertyChangedSignal("Text"):Connect(function()
|
||||
if self.list then
|
||||
updateClearButtonVisibility()
|
||||
self.list:SetFilterPredicate(self.SearchFilterPredicate)
|
||||
self:getOlderConversationsForSearchIfNecessary()
|
||||
end
|
||||
end)
|
||||
table.insert(self.connections, searchChangedConnection)
|
||||
|
||||
local focusedConnection = self.searchBox.Focused:Connect(updateClearButtonVisibility)
|
||||
if FFlagLuaChatToSplitRbxConnections then
|
||||
table.insert(self.rbx_connections, focusedConnection)
|
||||
else
|
||||
table.insert(self.connections, focusedConnection)
|
||||
end
|
||||
local focusLostConnection = self.searchBox.FocusLost:Connect(updateClearButtonVisibility)
|
||||
if FFlagLuaChatToSplitRbxConnections then
|
||||
table.insert(self.rbx_connections, focusLostConnection)
|
||||
else
|
||||
table.insert(self.connections, focusLostConnection)
|
||||
end
|
||||
|
||||
if not self.placeInfo then
|
||||
self.appState.store:dispatch(GetMultiplePlaceInfos({self.placeId}))
|
||||
end
|
||||
|
||||
if self.appState.store:getState().ChatAppReducer.AppLoaded and self.placeInfo then
|
||||
self:FillContent()
|
||||
end
|
||||
end
|
||||
|
||||
function GameShareComponent:Update(newState, oldState)
|
||||
if (not oldState.ChatAppReducer.AppLoaded) and newState.ChatAppReducer.AppLoaded and self.placeInfo then
|
||||
self:FillContent()
|
||||
end
|
||||
|
||||
if (not self.placeInfo) and (newState.ChatAppReducer.PlaceInfos[self.placeId]) then
|
||||
self.placeInfo = newState.ChatAppReducer.PlaceInfos[self.placeId]
|
||||
if newState.ChatAppReducer.AppLoaded then
|
||||
self:FillContent()
|
||||
end
|
||||
end
|
||||
|
||||
local newPageConversationsIsFetching = newState.ChatAppReducer.ConversationsAsync.pageConversationsIsFetching
|
||||
local oldPageConversationsIsFetching = oldState.ChatAppReducer.ConversationsAsync.pageConversationsIsFetching
|
||||
if newPageConversationsIsFetching ~= oldPageConversationsIsFetching and self.list then
|
||||
self.list:Update(newState, oldState)
|
||||
self:getOlderConversationsForSearchIfNecessary()
|
||||
end
|
||||
|
||||
if newState.ChatAppReducer.Conversations ~= oldState.ChatAppReducer.Conversations and self.list then
|
||||
self.list:Update(newState, oldState)
|
||||
end
|
||||
end
|
||||
|
||||
function GameShareComponent:FillContent()
|
||||
self.searchContainer.Visible = true
|
||||
self:FillPlaceInfo()
|
||||
self:FillConversations()
|
||||
end
|
||||
|
||||
function GameShareComponent:FillPlaceInfo()
|
||||
if self.placeInfoCard then
|
||||
return
|
||||
end
|
||||
|
||||
self.placeInfoCard = PlaceInfoCard.new(self.appState, self.placeInfo)
|
||||
self.placeInfoCard.rbx.Parent = self.placeInfoCardFrame
|
||||
end
|
||||
|
||||
function GameShareComponent:FillConversations()
|
||||
local conversations = self.appState.store:getState().ChatAppReducer.Conversations
|
||||
local list = ConversationList.new(self.appState, conversations, GameShareCard)
|
||||
list:SetSortWithConversationEntry(true)
|
||||
self.list = list
|
||||
list.rbx.Size = UDim2.new(1, 0, 1, 0)
|
||||
list.rbx.Parent = self.conversationListFrame
|
||||
|
||||
local tappedConnection = list.ConversationTapped:connect(function(convoId)
|
||||
local messageSentLocalTime = tick()
|
||||
|
||||
if FFlagShareGameToChatStatusAnalytics then
|
||||
self.appState.store:dispatch(
|
||||
ConversationActions.SendMessage(
|
||||
convoId,
|
||||
truncateAssetLink(self.placeInfo.url),
|
||||
messageSentLocalTime
|
||||
)):andThen(function(webStatus)
|
||||
self:ReportSendButtonTappedEvent(convoId, webStatus)
|
||||
|
||||
if webStatus == HttpStatus.MODERATED then
|
||||
local toastModel = ToastModel.new(Constants.ToastIDs.MESSAGE_WAS_MODERATED, "Feature.Chat.Message.GameLinkWasModerated")
|
||||
self.appState.store:dispatch(ShowToast(toastModel))
|
||||
end
|
||||
end)
|
||||
else
|
||||
self:ReportSendButtonTappedEvent(convoId)
|
||||
self.appState.store:dispatch(
|
||||
ConversationActions.SendMessage(
|
||||
convoId,
|
||||
truncateAssetLink(self.placeInfo.url),
|
||||
"Feature.Chat.Message.GameLinkWasModerated",
|
||||
messageSentLocalTime
|
||||
)
|
||||
)
|
||||
end
|
||||
end)
|
||||
table.insert(self.connections, tappedConnection)
|
||||
|
||||
local requestOlderConversationConnection = list.RequestOlderConversations:connect(function()
|
||||
requestOlderConversations(self.appState)
|
||||
end)
|
||||
table.insert(self.connections, requestOlderConversationConnection)
|
||||
end
|
||||
|
||||
function GameShareComponent:getOlderConversationsForSearchIfNecessary(appState)
|
||||
-- To Check:
|
||||
-- 1) Search is open
|
||||
-- 2) Not have loaded all conversations.
|
||||
-- 3) Not Ccrrently getting older conversations
|
||||
-- 4) Having enouth search items to show
|
||||
-- Note that we already try to load more conversations if we scroll down to the bottom of the list
|
||||
local state = self.appState.store:getState()
|
||||
local isSearchOpen = (self.searchBox.Text) ~= nil and (self.searchBox.Text ~= "")
|
||||
if (not isSearchOpen) or state.ChatAppReducer.ConversationsAsync.oldestConversationIsFetched
|
||||
or state.ChatAppReducer.ConversationsAsync.pageConversationsIsFetching then
|
||||
return
|
||||
end
|
||||
|
||||
if self.list.rbx.CanvasSize.Y.Offset > self.list.rbx.AbsoluteSize.Y then
|
||||
return
|
||||
end
|
||||
|
||||
requestOlderConversations(self.appState)
|
||||
end
|
||||
|
||||
function GameShareComponent:ReportSendButtonTappedEvent(convoId, httpStatus)
|
||||
local eventName = "clickSendBtnFromGameShareCard"
|
||||
local eventContext = "touch"
|
||||
|
||||
local player = PlayerService.LocalPlayer
|
||||
local userId = "UNKNOWN"
|
||||
if player then
|
||||
userId = tostring(player.UserId)
|
||||
end
|
||||
|
||||
local additionalArgs = {
|
||||
uid = userId,
|
||||
placeid = self.placeId,
|
||||
cid = convoId,
|
||||
httpStatus = httpStatus,
|
||||
}
|
||||
|
||||
self._analytics.EventStream:setRBXEvent(eventContext, eventName, additionalArgs)
|
||||
end
|
||||
|
||||
function GameShareComponent:Stop()
|
||||
for _, connection in ipairs(self.connections) do
|
||||
connection:disconnect()
|
||||
end
|
||||
self.connections = {}
|
||||
|
||||
if FFlagLuaChatToSplitRbxConnections then
|
||||
for _, connection in ipairs(self.rbx_connections) do
|
||||
connection:Disconnect()
|
||||
end
|
||||
self.rbx_connections = {}
|
||||
end
|
||||
end
|
||||
|
||||
function GameShareComponent:Destruct()
|
||||
if self.list then
|
||||
self.list:Destruct()
|
||||
end
|
||||
if self.header then
|
||||
self.header:Destroy()
|
||||
end
|
||||
if self.placeInfoCard then
|
||||
self.placeInfoCard:Destruct()
|
||||
end
|
||||
self.rbx:Destroy()
|
||||
end
|
||||
|
||||
return GameShareComponent
|
||||
Reference in New Issue
Block a user