add gs
This commit is contained in:
@@ -0,0 +1,308 @@
|
||||
--[[
|
||||
// FriendsData.lua
|
||||
|
||||
// Caches the current friends pagination to used by anyone in the app
|
||||
|
||||
// TODO:
|
||||
Need polling to update friends. How are we going to handle all the cases
|
||||
like the person you're selecting going offline, etc..
|
||||
]]
|
||||
local CoreGui = game:GetService("CoreGui")
|
||||
local PlatformService = nil
|
||||
pcall(function() PlatformService = game:GetService('PlatformService') end)
|
||||
local FriendService = nil
|
||||
pcall(function() FriendService = game:GetService('FriendService') end)
|
||||
local ThirdPartyUserService = nil
|
||||
pcall(function() ThirdPartyUserService = game:GetService('ThirdPartyUserService') end)
|
||||
local isNotConsole = UserSettings().GameSettings:InStudioMode() or game:GetService('UserInputService'):GetPlatform() == Enum.Platform.Windows
|
||||
|
||||
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
|
||||
local Modules = GuiRoot:FindFirstChild("Modules")
|
||||
local ShellModules = Modules:FindFirstChild("Shell")
|
||||
|
||||
local Http = require(ShellModules:FindFirstChild('Http'))
|
||||
local Utility = require(ShellModules:FindFirstChild('Utility'))
|
||||
local EventHub = require(ShellModules:FindFirstChild('EventHub'))
|
||||
local TableUtilities = require(Modules.LuaApp.TableUtilities)
|
||||
local ReloaderManager = require(ShellModules:FindFirstChild('ReloaderManager'))
|
||||
local MakeSafeAsync = require(ShellModules:FindFirstChild('SafeAsync'))
|
||||
local AppState = require(ShellModules.AppState)
|
||||
local ResetUserThumbnails = require(ShellModules.Actions.ResetUserThumbnails)
|
||||
local SetFriendsData = require(ShellModules.Actions.SetFriendsData)
|
||||
local SetRenderedFriendsData = require(ShellModules.Actions.SetRenderedFriendsData)
|
||||
|
||||
|
||||
-- NOTE: This is just required for fixing Usernames in auto-generatd games
|
||||
local GameData = require(ShellModules:FindFirstChild('GameData'))
|
||||
local ConvertMyPlaceNameInXboxAppFlag = settings():GetFFlag("ConvertMyPlaceNameInXboxApp")
|
||||
|
||||
local FriendsData = {}
|
||||
|
||||
local function OnUserAccountChanged()
|
||||
FriendsData.Setup()
|
||||
end
|
||||
EventHub:addEventListener(EventHub.Notifications["AuthenticationSuccess"], "FriendsData", OnUserAccountChanged)
|
||||
if ThirdPartyUserService then
|
||||
ThirdPartyUserService.ActiveUserSignedOut:connect(function()
|
||||
FriendsData.Reset()
|
||||
end)
|
||||
end
|
||||
|
||||
local isOnlineFriendsPolling = false
|
||||
local isFriendEventsConnected = false
|
||||
local renderedFriendsUpdateSuspended = false
|
||||
local cachedFriendsData = nil
|
||||
local cachedFriendsDataMap = {}
|
||||
local friendsDataConns = {}
|
||||
|
||||
local function filterFriends(friendsData)
|
||||
for i = 1, #friendsData do
|
||||
local data = friendsData[i]
|
||||
|
||||
if data.gamertag == "" then
|
||||
data.gamertag = nil
|
||||
end
|
||||
|
||||
if data.robloxuid <= 0 then
|
||||
data.robloxuid = nil
|
||||
end
|
||||
|
||||
if data.xuid == "" then
|
||||
data.xuid = nil
|
||||
end
|
||||
|
||||
if data.placeId == 0 then
|
||||
data.placeId = nil
|
||||
end
|
||||
|
||||
if data.lastLocation == "" then
|
||||
data.lastLocation = nil
|
||||
end
|
||||
|
||||
if data.robloxName == "" then
|
||||
data.robloxName = nil
|
||||
end
|
||||
|
||||
local placeId = data.placeId
|
||||
local lastLocation = data.lastLocation
|
||||
|
||||
-- If the lastLocation for a user is some user place with a GeneratedUsername in it
|
||||
-- then replace it with the actual creator name!
|
||||
if ConvertMyPlaceNameInXboxAppFlag and placeId and lastLocation and GameData:ExtractGeneratedUsername(lastLocation) then
|
||||
local gameCreator = GameData:GetGameCreatorAsync(placeId)
|
||||
if gameCreator then
|
||||
lastLocation = GameData:GetFilteredGameName(lastLocation, gameCreator)
|
||||
end
|
||||
end
|
||||
|
||||
data.placeId = placeId
|
||||
data.lastLocation = lastLocation
|
||||
end
|
||||
|
||||
return friendsData
|
||||
end
|
||||
|
||||
--[[ Public API ]]--
|
||||
FriendsData.OnFriendsDataUpdated = Utility.Signal()
|
||||
|
||||
function FriendsData.GetOnlineFriendsAsync()
|
||||
if not cachedFriendsData then
|
||||
--Wait until we get cachedFriendsData from FriendService/FriendEvents disconnect(user sign out)
|
||||
while isFriendEventsConnected and not cachedFriendsData do
|
||||
wait()
|
||||
end
|
||||
end
|
||||
|
||||
return cachedFriendsData or {}
|
||||
end
|
||||
|
||||
-- we make connections through this function so we can clean them all up upon
|
||||
-- clearing the friends data
|
||||
function FriendsData.ConnectUpdateEvent(cbFunc)
|
||||
local cn = FriendsData.OnFriendsDataUpdated:connect(cbFunc)
|
||||
table.insert(friendsDataConns, cn)
|
||||
end
|
||||
|
||||
function FriendsData.Reset()
|
||||
isOnlineFriendsPolling = false
|
||||
|
||||
for index, cn in pairs(friendsDataConns) do
|
||||
Utility.DisconnectEvent(cn)
|
||||
friendsDataConns[index] = nil
|
||||
end
|
||||
isFriendEventsConnected = false
|
||||
|
||||
cachedFriendsData = nil
|
||||
cachedFriendsDataMap = {}
|
||||
|
||||
AppState.store:dispatch(ResetUserThumbnails())
|
||||
AppState.store:dispatch(SetFriendsData())
|
||||
AppState.store:dispatch(SetRenderedFriendsData())
|
||||
renderedFriendsUpdateSuspended = false
|
||||
|
||||
if isNotConsole then
|
||||
ReloaderManager:removeReloader("FriendsData")
|
||||
FriendsData.ReloaderFuncId = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function CheckEntryUpdate(newFriendsData)
|
||||
local validEntries = {}
|
||||
for i = 1, #newFriendsData do
|
||||
local data = newFriendsData[i]
|
||||
local xuid = data.xuid or ""
|
||||
local robloxuid = data.robloxuid or ""
|
||||
local idStr = tostring(xuid.."#"..robloxuid)
|
||||
validEntries[idStr] = true
|
||||
if cachedFriendsDataMap[idStr] then --check whether entry changed
|
||||
local differentAttributes = TableUtilities.TableDifference(cachedFriendsDataMap[idStr], data)
|
||||
if next(differentAttributes) ~= nil then
|
||||
data.isUpdated = true
|
||||
end
|
||||
end
|
||||
cachedFriendsDataMap[idStr] = data
|
||||
end
|
||||
|
||||
for idStr in pairs(cachedFriendsDataMap) do
|
||||
if not validEntries[idStr] then
|
||||
cachedFriendsDataMap[idStr] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local UpdateRenderedFriendsData = function(newFriendsData)
|
||||
AppState.store:dispatch(SetRenderedFriendsData(newFriendsData))
|
||||
--data for HomePane friend scroller, also from store, but need the CheckEntryUpdate
|
||||
CheckEntryUpdate(newFriendsData)
|
||||
cachedFriendsData = newFriendsData
|
||||
FriendsData.OnFriendsDataUpdated:fire(newFriendsData)
|
||||
end
|
||||
function FriendsData:SuspendUpdate()
|
||||
renderedFriendsUpdateSuspended = true
|
||||
end
|
||||
|
||||
function FriendsData:ResumeUpdate()
|
||||
--Get latest data from store when ResumeUpdate(), don't dispatch if the friends data hasn't been fetched yet
|
||||
if AppState.store:getState().Friends.initialized then
|
||||
UpdateRenderedFriendsData(AppState.store:getState().Friends.data)
|
||||
end
|
||||
renderedFriendsUpdateSuspended = false
|
||||
end
|
||||
|
||||
function FriendsData.Setup()
|
||||
FriendsData.Reset()
|
||||
--We make the conns once user logged in, and once we get the cachedFriendsData from FriendService
|
||||
--this func becomes sync call
|
||||
if PlatformService and FriendService then
|
||||
--Connect FriendsUpdated event to get newFriendsData at intervals
|
||||
table.insert(friendsDataConns, FriendService.FriendsUpdated:connect(function(newFriendsData)
|
||||
newFriendsData = filterFriends(newFriendsData)
|
||||
AppState.store:dispatch(SetFriendsData(newFriendsData))
|
||||
if not AppState.store:getState().RenderedFriends.initialized or not renderedFriendsUpdateSuspended then
|
||||
UpdateRenderedFriendsData(newFriendsData)
|
||||
end
|
||||
end))
|
||||
|
||||
isFriendEventsConnected = true
|
||||
|
||||
--Try to get the cachedFriendsData, check if the friends data has been fetched on Friend Service
|
||||
local success, result = pcall(function()
|
||||
return FriendService:GetPlatformFriends()
|
||||
end)
|
||||
if success then
|
||||
result = filterFriends(result)
|
||||
AppState.store:dispatch(SetFriendsData(result))
|
||||
if not AppState.store:getState().RenderedFriends.initialized or not renderedFriendsUpdateSuspended then
|
||||
UpdateRenderedFriendsData(result)
|
||||
end
|
||||
end
|
||||
else
|
||||
if isNotConsole then
|
||||
local POLL_DELAY = 30
|
||||
local GetRecommendPeopleInStudio = MakeSafeAsync({
|
||||
asyncFunc = function()
|
||||
local finalRecommendedUsers = {}
|
||||
local result = Http.GetRecommendedUsersndsAsync()
|
||||
if result and result["recommendedUsers"] then
|
||||
local recommendedUsersMap = {}
|
||||
local recommendedUsers = result["recommendedUsers"]
|
||||
local userIds = {}
|
||||
for i = 1, #recommendedUsers do
|
||||
local data = recommendedUsers[i]
|
||||
local robloxuid = data.userId
|
||||
if robloxuid then
|
||||
table.insert(userIds, robloxuid)
|
||||
recommendedUsersMap[robloxuid] =
|
||||
{
|
||||
robloxuid = robloxuid,
|
||||
robloxName = data.userName
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local presenceInfo = Http.GetUsersPresenceAsync(userIds)
|
||||
if presenceInfo and presenceInfo["userPresences"] then
|
||||
for _, presence in ipairs(presenceInfo["userPresences"]) do
|
||||
local robloxuid = presence.userId
|
||||
if robloxuid and recommendedUsersMap[robloxuid] then
|
||||
recommendedUsersMap[robloxuid].placeId = presence.rootPlaceId
|
||||
recommendedUsersMap[robloxuid].lastLocation = presence.lastLocation
|
||||
recommendedUsersMap[robloxuid].friendsSource = "Roblox"
|
||||
local robloxStatus = "Offline"
|
||||
local rank = 4
|
||||
if presence.userPresenceType == 1 then
|
||||
robloxStatus = "Online"
|
||||
rank = 3
|
||||
elseif presence.userPresenceType == 2 then
|
||||
if presence.rootPlaceId and presence.rootPlaceId > 0 then
|
||||
robloxStatus = "InGame"
|
||||
rank = 1
|
||||
else
|
||||
robloxStatus = "Online"
|
||||
rank = 3
|
||||
end
|
||||
elseif presence.userPresenceType == 3 then
|
||||
robloxStatus = "InStudio"
|
||||
rank = 2
|
||||
end
|
||||
recommendedUsersMap[robloxuid].robloxStatus = robloxStatus
|
||||
recommendedUsersMap[robloxuid].rank = rank
|
||||
table.insert(finalRecommendedUsers, recommendedUsersMap[robloxuid])
|
||||
end
|
||||
end
|
||||
end
|
||||
local function sortFunc(a, b)
|
||||
if a.rank == b.rank then
|
||||
return a.robloxName:lower() < b.robloxName:lower()
|
||||
end
|
||||
return a.rank < b.rank
|
||||
end
|
||||
|
||||
table.sort(finalRecommendedUsers, sortFunc)
|
||||
end
|
||||
return finalRecommendedUsers
|
||||
end,
|
||||
callback = function(finalRecommendedUsers)
|
||||
finalRecommendedUsers = filterFriends(finalRecommendedUsers)
|
||||
AppState.store:dispatch(SetFriendsData(finalRecommendedUsers))
|
||||
if not AppState.store:getState().RenderedFriends.initialized or not renderedFriendsUpdateSuspended then
|
||||
UpdateRenderedFriendsData(finalRecommendedUsers)
|
||||
end
|
||||
end,
|
||||
userRelated = true
|
||||
})
|
||||
|
||||
if not isOnlineFriendsPolling then
|
||||
isOnlineFriendsPolling = true
|
||||
isFriendEventsConnected = true
|
||||
spawn(function()
|
||||
ReloaderManager:removeReloader("FriendsData")
|
||||
FriendsData.ReloaderFuncId = ReloaderManager:addReloaderFunc("FriendsData", function() GetRecommendPeopleInStudio() end, POLL_DELAY, true)
|
||||
ReloaderManager:callReloaderFunc("FriendsData", FriendsData.ReloaderFuncId)
|
||||
end)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return FriendsData
|
||||
Reference in New Issue
Block a user