This commit is contained in:
lx
2026-07-06 14:01:11 -04:00
commit c4f97d729d
16468 changed files with 935321 additions and 0 deletions
@@ -0,0 +1,5 @@
{
"lint": {
"LocalShadow": "fatal"
}
}
@@ -0,0 +1,8 @@
{
"language": {
"mode": "nonstrict"
},
"lint": {
"ImplicitReturn": "fatal"
}
}
@@ -0,0 +1,9 @@
local Modules = game:GetService("CorePackages").AppTempCommon
local Common = Modules.Common
local Action = require(Common.Action)
return Action(script.Name, function(convo)
return {
conversation = convo,
}
end)
@@ -0,0 +1,10 @@
local Modules = game:GetService("CorePackages").AppTempCommon
local Common = Modules.Common
local Action = require(Common.Action)
return Action(script.Name, function(placeInfos)
return {
placeInfos = placeInfos,
}
end)
@@ -0,0 +1,30 @@
local Modules = game:GetService("CorePackages").AppTempCommon
local Action = require(Modules.Common.Action)
local LuaDateTime = require(Modules.LuaChat.DateTime)
return Action(script.Name, function(userId,
presence, lastLocation,
placeId, rootPlaceId,
gameInstanceId, lastOnlineISO, universeId, previousUniverseId)
local lastOnline = 0
if lastOnlineISO ~= nil then
local lastDateTime = LuaDateTime.fromIsoDate(lastOnlineISO)
if lastDateTime ~= nil then
lastOnline = lastDateTime:GetUnixTimestamp()
end
end
return {
userId = userId,
presence = presence,
lastLocation = lastLocation,
placeId = placeId,
rootPlaceId = rootPlaceId,
gameInstanceId = gameInstanceId,
lastOnline = lastOnline,
universeId = universeId,
previousUniverseId = previousUniverseId,
}
end)
@@ -0,0 +1,621 @@
local LocalizationService = game:GetService("LocalizationService")
local CorePackages = game:GetService("CorePackages")
local GetFFlagUseDateTimeType = require(CorePackages.AppTempCommon.LuaApp.Flags.GetFFlagUseDateTimeType)
local FFlagChinaLicensingApp = settings():GetFFlag("ChinaLicensingApp")
--[[
This is a Lua implementation of the DateTime API proposal. It'll eventually
be implemented in C++ and merged into the rest of the codebase if this model
of working with dates ends up being useful.
]]
local TimeZone = require(script.Parent.TimeZone)
local TimeUnit = require(script.Parent.TimeUnit)
local LuaDateTime = {}
local monthShortNames = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
}
local monthLongNames = {
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"
}
local dayShortNames = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
}
local dayLongNames = {
"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"
}
--[[
We structure tokens like this to preserve order, since Lua associative
arrays have no inherent order.
]]
local tokens = {
{"YYYY", function(values)
return tostring(values.Year)
end},
{"MMMM", function(values)
return monthLongNames[values.Month]
end},
{"MMM", function(values)
return monthShortNames[values.Month]
end},
{"MM", function(values)
return ("%02d"):format(values.Month)
end},
{"M", function(values)
return tostring(values.Month)
end},
{"DDDD", function(values)
return dayLongNames[values.WeekDay]
end},
{"DDD", function(values)
return dayShortNames[values.WeekDay]
end},
{"DD", function(values)
return ("%02d"):format(values.Day)
end},
{"D", function(values)
return tostring(values.Day)
end},
{"HH", function(values)
local hour = values.Hour
return ("%02d"):format(hour)
end},
{"H", function(values)
local hour = values.Hour
return tostring(hour)
end},
{"hh", function(values)
local hour = values.Hour % 12
if hour == 0 then
hour = 12
end
return ("%02d"):format(hour)
end},
{"h", function(values)
local hour = values.Hour % 12
if hour == 0 then
hour = 12
end
return tostring(hour)
end},
{"mm", function(values)
return ("%02d"):format(values.Minute)
end},
{"m", function(values)
return tostring(values.Minute)
end},
{"ss", function(values)
return ("%02d"):format(values.Seconds)
end},
{"s", function(values)
return tostring(values.Seconds)
end},
{"A", function(values)
if FFlagChinaLicensingApp then
return values.Hour >= 12 and "下午" or "上午"
else
return values.Hour >= 12 and "PM" or "AM"
end
end},
{"a", function(values)
if FFlagChinaLicensingApp then
return values.Hour >= 12 and "下午" or "上午"
else
return values.Hour >= 12 and "pm" or "am"
end
end}
}
local tokenKeys = {}
for _, pair in ipairs(tokens) do
table.insert(tokenKeys, pair[1])
end
local tokenMap = {}
for _, pair in ipairs(tokens) do
tokenMap[pair[1]] = pair[2]
end
--[[
What's the next token in this source?
]]
local function getToken(source, i)
local char = source:sub(i, i)
for _, token in ipairs(tokenKeys) do
-- Only keep checking if the first character matches the token
if token:sub(1, 1) == char then
local match = source:sub(i, i + token:len() - 1)
if match == token then
return token
end
end
end
end
--[[
An estimate of the current time zone's offset from UTC in seconds.
This might fail for weird timezones (UTC +/- 14), but we can fix that by
picking a reference time that's further away from the Unix epoch.
]]
local function getTimeZoneOffset()
local actualEpoch = 86400 + 43200
local epoch = os.time({year = 1970, month = 1, day = 2, isdst = -1})
if epoch then
return actualEpoch - epoch
else
return 0
end
end
-- Remove all above functions and tables when clean up GetFFlagUseDateTimeType()
--[[
Create a DateTime with the given values in UTC.
All values are optional!
]]
function LuaDateTime.new(year, month, day, hour, minute, seconds, milliseconds)
if GetFFlagUseDateTimeType() then
local self = {}
self.dateTime = DateTime.fromUniversalTime(
year or 1970,
month or 1,
day or 1,
hour or 0,
minute or 0,
seconds or 0,
milliseconds or 0)
setmetatable(self, LuaDateTime)
return self
end
local tzOffset = getTimeZoneOffset()
local timestamp = os.time({
year = year or 1970,
month = month or 1,
day = day or 1,
hour = hour or 0,
min = minute or 0,
sec = seconds or 0,
isdst = -1
})
if timestamp == nil then
timestamp = 0
end
if seconds then
local subseconds = seconds - math.floor(seconds)
timestamp = timestamp + subseconds
end
return LuaDateTime.fromUnixTimestamp(timestamp + tzOffset)
end
--[[
Create a DateTime representing now.
]]
function LuaDateTime.now()
if GetFFlagUseDateTimeType() then
local self = {}
self.dateTime = DateTime.now()
setmetatable(self, LuaDateTime)
return self
end
return LuaDateTime.fromUnixTimestamp(os.time())
end
--[[
Create a Datetime from the given Unix timestamp.
Limited to the range [0, 2^32) when GetFFlagUseDateTimeType() is off, which lets us represent
dates out to about 2038.
When GetFFlagUseDateTimeType() is on, year range is 1400-9999, and timestamp range is between
first second of year 1400 to the last second of year 9999.
]]
function LuaDateTime.fromUnixTimestamp(timestamp)
assert(type(timestamp) == "number", "Invalid argument #1 to fromUnixTimestamp, expected number.")
if GetFFlagUseDateTimeType() then
local self = {}
self.dateTime = DateTime.fromUnixTimestampMillis(timestamp*1000)
setmetatable(self, LuaDateTime)
return self
end
local self = {}
self.value = timestamp
setmetatable(self, LuaDateTime)
return self
end
--[[
Attempt to create a DateTime from an ISO 8601 date-time string.
Will return nil on failure and output a warning to a console denoting what
went wrong. This can probably turned into a second return value if we need
to handle that data programmatically.
]]
function LuaDateTime.fromIsoDate(isoDate)
assert(type(isoDate) == "string", "Invalid argument #1 to DateTime.fromIsoDate, expected string.")
if GetFFlagUseDateTimeType() then
local self = {}
self.dateTime = DateTime.fromIsoDate(isoDate)
setmetatable(self, LuaDateTime)
return self
end
local datePattern = "^(%d+)%-(%d+)%-(%d+)" -- 0000-00-00
local timePattern = "T(%d+):(%d+):(%d+%.?%d*)" -- T00:00:00
local utcPattern = "Z$"
local timeZonePattern = "([+-]%d+):(%d+)$" -- either Z or +/- followed by "00:00"
local timezone = 0
local values = {1970, 1, 1, 0, 0, 0}
local year, month, day = isoDate:match(datePattern)
if not year then
warn(("Invalid ISO 8601 date: %q"):format(isoDate))
return nil
end
values[1] = tonumber(year)
values[2] = tonumber(month)
values[3] = tonumber(day)
local hour, minute, seconds = isoDate:match(timePattern)
if hour then
values[4] = tonumber(hour)
values[5] = tonumber(minute)
values[6] = tonumber(seconds)
local isUtc = isoDate:match(utcPattern)
if not isUtc then
local offsetHours, offsetMinutes = isoDate:match(timeZonePattern)
if not offsetHours then
local offsetTotal = getTimeZoneOffset()
offsetHours = offsetTotal / 3600
offsetMinutes = 0
warn(("Invalid time zone in ISO 8601 date: %q -- falling back to local time"):format(isoDate))
end
timezone = 3600 * tonumber(offsetHours) + 60 * tonumber(offsetMinutes)
end
end
local date = LuaDateTime.new(unpack(values))
date.value = date.value - timezone
return date
end
--[[
Format our current date using a formatting string. Look at the DateTime
proposal to see information about the different formatting tokens.
Generally, they try to resemble LDML and/or Moment.js-style formatting.
The time zone parameter is optional and defaults to the current time zone,
TimeZone.Current.
]]
function LuaDateTime:Format(formatString, tz, localeId)
assert(type(formatString) == "string", "Invalid argument #1 to Format, expected string.")
if GetFFlagUseDateTimeType() then
tz = tz or TimeZone.Current
localeId = localeId or LocalizationService.RobloxLocaleId
if tz == TimeZone.UTC then
return self.dateTime:FormatUniversalTime(formatString, localeId)
elseif tz == TimeZone.Current then
return self.dateTime:FormatLocalTime(formatString, localeId)
else
error(("Invalid TimeZone \"%s\""):format(tostring(tz)), 2)
end
end
tz = tz or TimeZone.Current
local values = self:GetValues(tz)
local buffer = {}
local i = 1
while i <= formatString:len() do
local char = formatString:sub(i, i)
local token = getToken(formatString, i)
if token then
table.insert(buffer, tokenMap[token](values))
i = i + token:len()
elseif char == "[" then
-- Crawl forward until the next ] and interpret that text literally
local j = i
while j <= formatString:len() do
j = j + 1
if formatString:sub(j, j) == "]" then
break
end
end
table.insert(buffer, formatString:sub(i + 1, j - 1))
i = j + 1
else
table.insert(buffer, char)
i = i + 1
end
end
local result = table.concat(buffer)
return result
end
--[[
Get a table of values representing the date-time in the given timezone.
The time zone parameter is optional and defaults to the current zime zone,
TimeZone.Current.
When GetFFlagUseDateTimeType() is true, table would include
{Year, Month, Day, Hour, Minute, Second, Millisecond}
]]
function LuaDateTime:GetValues(tz)
if GetFFlagUseDateTimeType() then
tz = tz or TimeZone.Current
if tz == TimeZone.UTC then
return self.dateTime:ToUniversalTime()
elseif tz == TimeZone.Current then
return self.dateTime:ToLocalTime()
else
error(("Invalid TimeZone \"%s\""):format(tostring(tz)), 2)
end
end
tz = tz or TimeZone.Current
local reference
if tz == TimeZone.Current then
reference = os.date("*t", self.value)
elseif tz == TimeZone.UTC then
reference = os.date("!*t", self.value)
end
if not reference then
error(("Invalid TimeZone \"%s\""):format(tostring(tz)), 2)
end
return {
Year = reference.year,
Month = reference.month,
Day = reference.day,
Hour = reference.hour,
Minute = reference.min,
Seconds = reference.sec,
WeekDay = reference.wday
}
end
--[[
Recover a Unix timestamp representing the DateTime's value.
]]
function LuaDateTime:GetUnixTimestamp()
if GetFFlagUseDateTimeType() then
if self.dateTime:ToUniversalTime().Millisecond > 0 then
return self.dateTime.UnixTimestamp + (self.dateTime.UnixTimestampMillis % 1000)/1000
else
return self.dateTime.UnixTimestamp
end
end
return self.value
end
--[[
Format the DateTime as an ISO 8601 date string with time attached.
Always formats the time as UTC. There generally aren't many reasons to
generate an ISO 8601 date in another time zone.
]]
function LuaDateTime:GetIsoDate()
if GetFFlagUseDateTimeType() then
return self.dateTime:ToIsoDate()
end
return self:Format("YYYY-MM-DD[T]HH:mm:ss[Z]", TimeZone.UTC)
end
-- Used by IsSame
-- Remove when clean up GetFFlagUseDateTimeType()
local descendingGranularityUnits = {
{
unit = TimeUnit.Years,
key = "Year"
},
{
unit = TimeUnit.Months,
key = "Month"
},
{
unit = TimeUnit.Days,
key = "Day"
},
{
unit = TimeUnit.Hours,
key = "Hour"
},
{
unit = TimeUnit.Minutes,
key = "Minute"
},
{
unit = TimeUnit.Seconds,
key = "Seconds"
}
}
--[[
Checks whether two DateTime values are the same, given a granularity and
timezone value.
Granularity defaults to seconds and time zone defaults to the current local
time zone.
Remove when clean up GetFFlagUseDateTimeType()
]]
function LuaDateTime:IsSame(other, granularity, timezone)
granularity = granularity or TimeUnit.Seconds
timezone = timezone or TimeZone.Current
local selfUnix = self:GetUnixTimestamp()
local otherUnix = other:GetUnixTimestamp()
if selfUnix == otherUnix then
return true
end
local selfValues = self:GetValues(timezone)
local otherValues = other:GetValues(timezone)
-- Week logic is special
if granularity == TimeUnit.Weeks then
local diff = math.abs(selfUnix - otherUnix)
local diffDays = diff / (60 * 60 * 24)
-- Two dates separated by 7 or more whole days are never in the same week
if diffDays >= 7 then
return false
end
-- Two dates separated by less than 7 days will be sorted monotonically
-- if they're in the same week
-- TODO: Use start-of-week value to shift WeekDay for locale
if selfUnix > otherUnix then
return selfValues.WeekDay >= otherValues.WeekDay
else
return selfValues.WeekDay <= otherValues.WeekDay
end
end
for _, unit in ipairs(descendingGranularityUnits) do
local selfValue = selfValues[unit.key]
local otherValue = otherValues[unit.key]
if selfValue ~= otherValue then
return false
end
if unit.unit == granularity then
break
end
end
return true
end
--[[
Get a human-readable timestamp relative to the given epoch, which defaults
to now. The format of the time is contextual to how far away the times are.
]]
function LuaDateTime:GetLongRelativeTime(epoch, timezone, localeId)
if GetFFlagUseDateTimeType() then
-- Not relative time format for now, will do that later in DateTime v2
return self:Format("lll", timezone, localeId)
end
timezone = timezone or TimeZone.Current
epoch = epoch or LuaDateTime.now()
if FFlagChinaLicensingApp then
if self:IsSame(epoch, TimeUnit.Days, timezone) then
return self:Format("HH:mm A", timezone)
elseif self:IsSame(epoch, TimeUnit.Weeks, timezone) then
return self:Format("M月D日 | HH:mm A", timezone)
elseif self:IsSame(epoch, TimeUnit.Years, timezone) then
return self:Format("M月D日 | HH:mm A", timezone)
else
return self:Format("YYYY年M月D日 | HH:mm A", timezone)
end
else
if self:IsSame(epoch, TimeUnit.Days, timezone) then
return self:Format("h:mm A", timezone)
elseif self:IsSame(epoch, TimeUnit.Weeks, timezone) then
return self:Format("DDD | h:mm A", timezone)
elseif self:IsSame(epoch, TimeUnit.Years, timezone) then
return self:Format("MMM D | h:mm A", timezone)
else
return self:Format("MMM D, YYYY | h:mm A", timezone)
end
end
end
--[[
Get a human-readable timestamp relative to the given epoch, which defaults
to now. The format of the time is contextual to how far away the times are.
]]
function LuaDateTime:GetShortRelativeTime(epoch, timezone, localeId)
timezone = timezone or TimeZone.Current
if GetFFlagUseDateTimeType() then
-- Not relative time format for now, will do that later in DateTime v2
return self:Format("ll", timezone, localeId)
end
epoch = epoch or LuaDateTime.now()
if FFlagChinaLicensingApp then
if self:IsSame(epoch, TimeUnit.Days, timezone) then
return self:Format("HH:mm A", timezone)
elseif self:IsSame(epoch, TimeUnit.Weeks, timezone) then
return self:Format("M月D日", timezone)
elseif self:IsSame(epoch, TimeUnit.Years, timezone) then
return self:Format("M月D日", timezone)
else
return self:Format("YYYY年M月D日", timezone)
end
else
if self:IsSame(epoch, TimeUnit.Days, timezone) then
return self:Format("h:mm A", timezone)
elseif self:IsSame(epoch, TimeUnit.Weeks, timezone) then
return self:Format("DDD", timezone)
elseif self:IsSame(epoch, TimeUnit.Years, timezone) then
return self:Format("MMM D", timezone)
else
return self:Format("MMM D, YYYY", timezone)
end
end
end
LuaDateTime.__index = LuaDateTime
return LuaDateTime
@@ -0,0 +1,738 @@
local CorePackages = game:GetService("CorePackages")
local GetFFlagUseDateTimeType = require(CorePackages.AppTempCommon.LuaApp.Flags.GetFFlagUseDateTimeType)
local FFlagChinaLicensingApp = settings():GetFFlag("ChinaLicensingApp")
return function()
local LuaDateTime = require(script.Parent.DateTime)
local TimeZone = require(script.Parent.TimeZone)
local TimeUnit = require(script.Parent.TimeUnit)
local localeIds = {
"en-us",
"en-gb",
"en-au",
"en-ca",
"en-nz",
"de-de",
"es-es",
"es-mx",
"fr-fr",
"fr-ca",
"it-it",
"pt-pt",
"pt-br",
"ru-ru",
"ja-jp",
"ko-kr",
"zh-cn",
"zh-hk",
"zh-tw",
"zh-hans",
"zh-hant",
"zh-cjv",
}
describe("Constructors", function()
it("should construct with 'new'", function()
expect(LuaDateTime.new()).to.be.ok()
expect(LuaDateTime.new(2017)).to.be.ok()
expect(LuaDateTime.new(2017, 5)).to.be.ok()
expect(LuaDateTime.new(2017, 5, 3)).to.be.ok()
expect(LuaDateTime.new(2017, 5, 3, 12)).to.be.ok()
expect(LuaDateTime.new(2017, 5, 3, 12, 34)).to.be.ok()
expect(LuaDateTime.new(2017, 5, 3, 12, 34, 51)).to.be.ok()
if GetFFlagUseDateTimeType() then
expect(LuaDateTime.new(2017, 5, 3, 12, 34, 51, 999)).to.be.ok()
end
end)
it("should construct with 'now'", function()
expect(LuaDateTime.now()).to.be.ok()
end)
it("should construct from a Unix timestamp", function()
expect(LuaDateTime.fromUnixTimestamp(0)).to.be.ok()
expect(LuaDateTime.fromUnixTimestamp(os.time())).to.be.ok()
end)
it("should construct from an ISO 8601 date", function()
if GetFFlagUseDateTimeType() then
-- Basic date
do
local date = LuaDateTime.fromIsoDate("1988-03-17")
expect(date).to.be.ok()
expect(date.dateTime:ToUniversalTime().Year).to.equal(1988)
expect(date.dateTime:ToUniversalTime().Month).to.equal(3)
expect(date.dateTime:ToUniversalTime().Day).to.equal(17)
expect(date.dateTime:ToUniversalTime().Hour).to.equal(0)
expect(date.dateTime:ToUniversalTime().Minute).to.equal(0)
expect(date.dateTime:ToUniversalTime().Second).to.equal(0)
expect(date.dateTime:ToUniversalTime().Millisecond).to.equal(0)
end
-- Date and time
do
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16.999Z")
expect(date).to.be.ok()
expect(date:GetUnixTimestamp()).to.equal(1491856816.999)
expect(date.dateTime:ToUniversalTime().Year).to.equal(2017)
expect(date.dateTime:ToUniversalTime().Month).to.equal(4)
expect(date.dateTime:ToUniversalTime().Day).to.equal(10)
expect(date.dateTime:ToUniversalTime().Hour).to.equal(20)
expect(date.dateTime:ToUniversalTime().Minute).to.equal(40)
expect(date.dateTime:ToUniversalTime().Second).to.equal(16)
expect(date.dateTime:ToUniversalTime().Millisecond).to.equal(999)
end
-- Date and time with no time zone
do
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16.1")
expect(date).to.be.ok()
expect(date:GetUnixTimestamp()).to.equal(1491856816.1)
expect(date.dateTime:ToUniversalTime().Year).to.equal(2017)
expect(date.dateTime:ToUniversalTime().Month).to.equal(4)
expect(date.dateTime:ToUniversalTime().Day).to.equal(10)
expect(date.dateTime:ToUniversalTime().Hour).to.equal(20)
expect(date.dateTime:ToUniversalTime().Minute).to.equal(40)
expect(date.dateTime:ToUniversalTime().Second).to.equal(16)
expect(date.dateTime:ToUniversalTime().Millisecond).to.equal(100)
end
-- Date, time, and time zone offset
do
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16+01:00")
expect(date).to.be.ok()
expect(date:GetUnixTimestamp()).to.equal(1491856816 - 3600)
expect(date.dateTime:ToUniversalTime().Year).to.equal(2017)
expect(date.dateTime:ToUniversalTime().Month).to.equal(4)
expect(date.dateTime:ToUniversalTime().Day).to.equal(10)
expect(date.dateTime:ToUniversalTime().Hour).to.equal(19)
expect(date.dateTime:ToUniversalTime().Minute).to.equal(40)
expect(date.dateTime:ToUniversalTime().Second).to.equal(16)
expect(date.dateTime:ToUniversalTime().Millisecond).to.equal(0)
end
-- Date, time, and negative time zone offset
do
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16-01:00")
expect(date).to.be.ok()
expect(date:GetUnixTimestamp()).to.equal(1491856816 + 3600)
expect(date.dateTime:ToUniversalTime().Year).to.equal(2017)
expect(date.dateTime:ToUniversalTime().Month).to.equal(4)
expect(date.dateTime:ToUniversalTime().Day).to.equal(10)
expect(date.dateTime:ToUniversalTime().Hour).to.equal(21)
expect(date.dateTime:ToUniversalTime().Minute).to.equal(40)
expect(date.dateTime:ToUniversalTime().Second).to.equal(16)
expect(date.dateTime:ToUniversalTime().Millisecond).to.equal(0)
end
else
-- Basic date
do
local date = LuaDateTime.fromIsoDate("1988-03-17")
expect(date).to.be.ok()
end
-- Date and time
do
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16Z")
expect(date).to.be.ok()
expect(date:GetUnixTimestamp()).to.equal(1491856816)
end
-- Date and time with no time zone
do
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16")
expect(date).to.be.ok()
end
-- Date, time, and time zone offset
do
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16+01:00")
expect(date).to.be.ok()
expect(date:GetUnixTimestamp()).to.equal(1491856816 - 3600)
end
-- Date, time, and negative time zone offset
do
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16-01:00")
expect(date).to.be.ok()
expect(date:GetUnixTimestamp()).to.equal(1491856816 + 3600)
end
end
end)
end)
describe("Measurements", function()
it("should get values in UTC", function()
local date = LuaDateTime.new()
local values = date:GetValues(TimeZone.UTC)
expect(values).to.be.ok()
expect(values.Year).to.be.a("number")
expect(values.Month).to.be.a("number")
expect(values.Day).to.be.a("number")
expect(values.Hour).to.be.a("number")
expect(values.Minute).to.be.a("number")
if GetFFlagUseDateTimeType() then
expect(values.Second).to.be.a("number")
expect(values.Millisecond).to.be.a("number")
else
expect(values.Seconds).to.be.a("number")
-- Locale specific!
expect(values.WeekDay).to.be.a("number")
end
end)
it("should get values in local time", function()
local date = LuaDateTime.new()
local values = date:GetValues(TimeZone.Current)
expect(values).to.be.ok()
expect(values.Year).to.be.a("number")
expect(values.Month).to.be.a("number")
expect(values.Day).to.be.a("number")
expect(values.Hour).to.be.a("number")
expect(values.Minute).to.be.a("number")
if GetFFlagUseDateTimeType() then
expect(values.Second).to.be.a("number")
expect(values.Millisecond).to.be.a("number")
else
expect(values.Seconds).to.be.a("number")
-- Locale specific!
expect(values.WeekDay).to.be.a("number")
end
end)
it("should preserve values from 'new' constructor", function()
local date = LuaDateTime.new(2017, 11, 3, 12, 34, 51)
local values = date:GetValues(TimeZone.UTC)
expect(values.Year).to.equal(2017)
expect(values.Month).to.equal(11)
expect(values.Day).to.equal(3)
expect(values.Hour).to.equal(12)
expect(values.Minute).to.equal(34)
if GetFFlagUseDateTimeType() then
expect(values.Second).to.equal(51)
expect(values.Millisecond).to.equal(0)
else
expect(values.Seconds).to.equal(51)
end
end)
it("should preserve Unix timestamp values", function()
do
local date = LuaDateTime.fromUnixTimestamp(0)
expect(date:GetUnixTimestamp()).to.equal(0)
end
do
local date = LuaDateTime.fromUnixTimestamp(123456789)
expect(date:GetUnixTimestamp()).to.equal(123456789)
end
end)
end)
describe("Formatting", function()
it("should preserve text within brackets", function()
local date = LuaDateTime.new(2017, 1, 2, 15, 8, 9)
local function format(str)
return date:Format(str, TimeZone.UTC)
end
expect(format("[Hello, world!]")).to.equal("Hello, world!")
expect(format("[YYYY-MM-DD]")).to.equal("YYYY-MM-DD")
end)
it("should create identical ISO 8601 dates for UTC inputs", function()
local date = LuaDateTime.fromIsoDate("2017-04-10T20:40:16Z")
expect(date:GetIsoDate()).to.equal("2017-04-10T20:40:16Z")
end)
it("should have correct formatting tokens", function()
local date = LuaDateTime.new(2016, 1, 2, 15, 8, 9)
-- Shortcut time zone specification
local function format(str, localeId)
return date:Format(str, TimeZone.UTC, localeId)
end
expect(format("YYYY")).to.equal("2016")
expect(format("M")).to.equal("1")
expect(format("MM")).to.equal("01")
expect(format("D")).to.equal("2")
expect(format("DD")).to.equal("02")
expect(format("H")).to.equal("15")
expect(format("HH")).to.equal("15")
expect(format("h")).to.equal("3")
expect(format("hh")).to.equal("03")
expect(format("m")).to.equal("8")
expect(format("mm")).to.equal("08")
expect(format("s")).to.equal("9")
expect(format("ss")).to.equal("09")
-- Locale-specific tests!
if GetFFlagUseDateTimeType() then
expect(format("SSS")).to.equal("000")
expect(format("SS")).to.equal("00")
expect(format("S")).to.equal("0")
expect(format("MMM", "en-us")).to.equal("Jan")
expect(format("MMMM", "en-us")).to.equal("January")
expect(format("MMM", "zh-cn")).to.equal("1月")
expect(format("MMMM", "zh-cn")).to.equal("一月")
expect(format("A", "en-us")).to.equal("PM")
expect(format("a", "en-us")).to.equal("pm")
expect(format("A", "zh-cn")).to.equal("下午")
expect(format("a", "zh-cn")).to.equal("下午")
else
expect(format("MMM")).to.equal("Jan")
expect(format("MMMM")).to.equal("January")
if FFlagChinaLicensingApp then
expect(format("A")).to.equal("下午")
expect(format("a")).to.equal("下午")
else
expect(format("A")).to.equal("PM")
expect(format("a")).to.equal("pm")
end
end
end)
it("should handle dates around midnight", function()
local date = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
expect(date:Format("H", TimeZone.UTC)).to.equal("0")
expect(date:Format("HH", TimeZone.UTC)).to.equal("00")
expect(date:Format("h", TimeZone.UTC)).to.equal("12")
expect(date:Format("hh", TimeZone.UTC)).to.equal("12")
if GetFFlagUseDateTimeType() then
expect(date:Format("A", TimeZone.UTC, "en-us")).to.equal("AM")
expect(date:Format("a", TimeZone.UTC, "en-us")).to.equal("am")
expect(date:Format("A", TimeZone.UTC, "zh-cn")).to.equal("凌晨")
expect(date:Format("a", TimeZone.UTC, "zh-cn")).to.equal("凌晨")
else
if FFlagChinaLicensingApp then
expect(date:Format("a", TimeZone.UTC)).to.equal("上午")
else
expect(date:Format("a", TimeZone.UTC)).to.equal("am")
end
end
end)
it("should handle dates around noon", function()
local date = LuaDateTime.new(2017, 5, 23, 12, 0, 0)
expect(date:Format("H", TimeZone.UTC)).to.equal("12")
expect(date:Format("HH", TimeZone.UTC)).to.equal("12")
expect(date:Format("h", TimeZone.UTC)).to.equal("12")
expect(date:Format("hh", TimeZone.UTC)).to.equal("12")
if GetFFlagUseDateTimeType() then
expect(date:Format("A", TimeZone.UTC, "en-us")).to.equal("PM")
expect(date:Format("a", TimeZone.UTC, "en-us")).to.equal("pm")
expect(date:Format("A", TimeZone.UTC, "zh-cn")).to.equal("中午")
expect(date:Format("a", TimeZone.UTC, "zh-cn")).to.equal("中午")
else
if FFlagChinaLicensingApp then
expect(date:Format("a", TimeZone.UTC)).to.equal("下午")
else
expect(date:Format("a", TimeZone.UTC)).to.equal("pm")
end
end
end)
it("should return correct 24-hour clock sequences", function()
local expected = {
"2017-09-13 00:00:00",
"2017-09-13 01:00:00",
"2017-09-13 02:00:00",
"2017-09-13 03:00:00",
"2017-09-13 04:00:00",
"2017-09-13 05:00:00",
"2017-09-13 06:00:00",
"2017-09-13 07:00:00",
"2017-09-13 08:00:00",
"2017-09-13 09:00:00",
"2017-09-13 10:00:00",
"2017-09-13 11:00:00",
"2017-09-13 12:00:00",
"2017-09-13 13:00:00",
"2017-09-13 14:00:00",
"2017-09-13 15:00:00",
"2017-09-13 16:00:00",
"2017-09-13 17:00:00",
"2017-09-13 18:00:00",
"2017-09-13 19:00:00",
"2017-09-13 20:00:00",
"2017-09-13 21:00:00",
"2017-09-13 22:00:00",
"2017-09-13 23:00:00",
"2017-09-14 00:00:00",
"2017-09-14 01:00:00",
}
local formatString = "YYYY-MM-DD HH:mm:ss"
local date
for _, localeId in ipairs(localeIds) do
date = LuaDateTime.new(2017, 9, 13, 0, 0, 0)
for i = 1, #expected do
local result = date:Format(formatString, TimeZone.UTC, localeId)
expect(result).to.equal(expected[i])
-- Advance once hour
date = date.fromUnixTimestamp(date:GetUnixTimestamp() + 3600)
end
end
end)
it("should return correct 12-hour clock sequences", function()
local date = LuaDateTime.new(2017, 9, 13, 0, 0, 0)
local formatString = "YYYY-MM-DD hh:mm:ss a"
local expected
if GetFFlagUseDateTimeType() then
expected = {
["en-us"] = {
"2017-09-13 12:00:00 am",
"2017-09-13 01:00:00 am",
"2017-09-13 02:00:00 am",
"2017-09-13 03:00:00 am",
"2017-09-13 04:00:00 am",
"2017-09-13 05:00:00 am",
"2017-09-13 06:00:00 am",
"2017-09-13 07:00:00 am",
"2017-09-13 08:00:00 am",
"2017-09-13 09:00:00 am",
"2017-09-13 10:00:00 am",
"2017-09-13 11:00:00 am",
"2017-09-13 12:00:00 pm",
"2017-09-13 01:00:00 pm",
"2017-09-13 02:00:00 pm",
"2017-09-13 03:00:00 pm",
"2017-09-13 04:00:00 pm",
"2017-09-13 05:00:00 pm",
"2017-09-13 06:00:00 pm",
"2017-09-13 07:00:00 pm",
"2017-09-13 08:00:00 pm",
"2017-09-13 09:00:00 pm",
"2017-09-13 10:00:00 pm",
"2017-09-13 11:00:00 pm",
"2017-09-14 12:00:00 am",
"2017-09-14 01:00:00 am",
},
["zh-cn"] = {
"2017-09-13 12:00:00 凌晨",
"2017-09-13 01:00:00 凌晨",
"2017-09-13 02:00:00 凌晨",
"2017-09-13 03:00:00 凌晨",
"2017-09-13 04:00:00 凌晨",
"2017-09-13 05:00:00 凌晨",
"2017-09-13 06:00:00 早上",
"2017-09-13 07:00:00 早上",
"2017-09-13 08:00:00 早上",
"2017-09-13 09:00:00 上午",
"2017-09-13 10:00:00 上午",
"2017-09-13 11:00:00 上午",
"2017-09-13 12:00:00 中午",
"2017-09-13 01:00:00 下午",
"2017-09-13 02:00:00 下午",
"2017-09-13 03:00:00 下午",
"2017-09-13 04:00:00 下午",
"2017-09-13 05:00:00 下午",
"2017-09-13 06:00:00 晚上",
"2017-09-13 07:00:00 晚上",
"2017-09-13 08:00:00 晚上",
"2017-09-13 09:00:00 晚上",
"2017-09-13 10:00:00 晚上",
"2017-09-13 11:00:00 晚上",
"2017-09-14 12:00:00 凌晨",
"2017-09-14 01:00:00 凌晨",
}
}
for i = 1, #expected do
for j = 1, #expected[i] do
local result = date:Format(formatString, TimeZone.UTC, expected[i])
expect(result).to.equal(expected[i][j])
-- Advance once hour
date = date.fromUnixTimestamp(date:GetUnixTimestamp() + 3600)
end
end
else
if FFlagChinaLicensingApp then
expected = {
"2017-09-13 12:00:00 上午",
"2017-09-13 01:00:00 上午",
"2017-09-13 02:00:00 上午",
"2017-09-13 03:00:00 上午",
"2017-09-13 04:00:00 上午",
"2017-09-13 05:00:00 上午",
"2017-09-13 06:00:00 上午",
"2017-09-13 07:00:00 上午",
"2017-09-13 08:00:00 上午",
"2017-09-13 09:00:00 上午",
"2017-09-13 10:00:00 上午",
"2017-09-13 11:00:00 上午",
"2017-09-13 12:00:00 下午",
"2017-09-13 01:00:00 下午",
"2017-09-13 02:00:00 下午",
"2017-09-13 03:00:00 下午",
"2017-09-13 04:00:00 下午",
"2017-09-13 05:00:00 下午",
"2017-09-13 06:00:00 下午",
"2017-09-13 07:00:00 下午",
"2017-09-13 08:00:00 下午",
"2017-09-13 09:00:00 下午",
"2017-09-13 10:00:00 下午",
"2017-09-13 11:00:00 下午",
"2017-09-14 12:00:00 上午",
"2017-09-14 01:00:00 上午",
}
else
expected = {
"2017-09-13 12:00:00 am",
"2017-09-13 01:00:00 am",
"2017-09-13 02:00:00 am",
"2017-09-13 03:00:00 am",
"2017-09-13 04:00:00 am",
"2017-09-13 05:00:00 am",
"2017-09-13 06:00:00 am",
"2017-09-13 07:00:00 am",
"2017-09-13 08:00:00 am",
"2017-09-13 09:00:00 am",
"2017-09-13 10:00:00 am",
"2017-09-13 11:00:00 am",
"2017-09-13 12:00:00 pm",
"2017-09-13 01:00:00 pm",
"2017-09-13 02:00:00 pm",
"2017-09-13 03:00:00 pm",
"2017-09-13 04:00:00 pm",
"2017-09-13 05:00:00 pm",
"2017-09-13 06:00:00 pm",
"2017-09-13 07:00:00 pm",
"2017-09-13 08:00:00 pm",
"2017-09-13 09:00:00 pm",
"2017-09-13 10:00:00 pm",
"2017-09-13 11:00:00 pm",
"2017-09-14 12:00:00 am",
"2017-09-14 01:00:00 am",
}
end
for i = 1, #expected do
local result = date:Format(formatString, TimeZone.UTC)
expect(result).to.equal(expected[i])
-- Advance once hour
date = date.fromUnixTimestamp(date:GetUnixTimestamp() + 3600)
end
end
end)
describe("LongRelativeTime", function()
if GetFFlagUseDateTimeType() then
it("SHOULD handle UTC time correctly with different locales", function()
local date = LuaDateTime.new(2015, 4, 20, 13, 0, 0)
for _, localeId in ipairs(localeIds) do
local longRelativeTime = date:GetLongRelativeTime(date, TimeZone.UTC, localeId)
expect(longRelativeTime).to.equal(date.dateTime:FormatUniversalTime("lll", localeId))
end
end)
it("SHOULD handle Local time correctly with different locales", function()
local date = LuaDateTime.fromUnixTimestamp(DateTime.fromLocalTime(2015, 4, 20, 13, 0, 0).UnixTimestamp)
for _, localeId in ipairs(localeIds) do
local longRelativeTime = date:GetLongRelativeTime(date, TimeZone.Current, localeId)
expect(longRelativeTime).to.equal(date.dateTime:FormatLocalTime("lll", localeId))
end
end)
else
it("SHOULD handle same day case", function()
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
local date = LuaDateTime.new(2015, 4, 20, 13, 0, 0)
if FFlagChinaLicensingApp then
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("13:00 下午")
else
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("1:00 PM")
end
end)
it("SHOULD handle same week case", function()
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
local date = LuaDateTime.new(2015, 4, 19, 13, 0, 0)
if FFlagChinaLicensingApp then
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("4月19日 | 13:00 下午")
else
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("Sun | 1:00 PM")
end
end)
it("SHOULD handle same year case", function()
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
local date = LuaDateTime.new(2015, 1, 20, 13, 0, 0)
if FFlagChinaLicensingApp then
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("1月20日 | 13:00 下午")
else
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20 | 1:00 PM")
end
end)
it("SHOULD handle different year case", function()
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
local date = LuaDateTime.new(2010, 1, 20, 13, 0, 0)
if FFlagChinaLicensingApp then
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("2010年1月20日 | 13:00 下午")
else
expect(date:GetLongRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20, 2010 | 1:00 PM")
end
end)
end
end)
describe("ShortRelativeTime", function()
if GetFFlagUseDateTimeType() then
it("SHOULD handle UTC time correctly with different locales", function()
local date = LuaDateTime.new(2015, 4, 20, 13, 0, 0)
for _, localeId in ipairs(localeIds) do
local shortRelativeTime = date:GetShortRelativeTime(date, TimeZone.UTC, localeId)
expect(shortRelativeTime).to.equal(date.dateTime:FormatUniversalTime("ll", localeId))
end
end)
it("SHOULD handle Local time correctly with different locales", function()
local date = LuaDateTime.fromUnixTimestamp(DateTime.fromLocalTime(2015, 4, 20, 13, 0, 0).UnixTimestamp)
for _, localeId in ipairs(localeIds) do
local shortRelativeTime = date:GetShortRelativeTime(date, TimeZone.Current, localeId)
expect(shortRelativeTime).to.equal(date.dateTime:FormatLocalTime("ll", localeId))
end
end)
else
it("SHOULD handle same day case", function()
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
local date = LuaDateTime.new(2015, 4, 20, 13, 0, 0)
if FFlagChinaLicensingApp then
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("13:00 下午")
else
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("1:00 PM")
end
end)
it("SHOULD handle same week case", function()
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
local date = LuaDateTime.new(2015, 4, 19, 13, 0, 0)
if FFlagChinaLicensingApp then
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("4月19日")
else
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("Sun")
end
end)
it("SHOULD handle same year case", function()
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
local date = LuaDateTime.new(2015, 1, 20, 13, 0, 0)
if FFlagChinaLicensingApp then
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("1月20日")
else
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20")
end
end)
it("SHOULD handle different year case", function()
local now = LuaDateTime.new(2015, 4, 20, 0, 0, 0)
local date = LuaDateTime.new(2010, 1, 20, 13, 0, 0)
if FFlagChinaLicensingApp then
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("2010年1月20日")
else
expect(date:GetShortRelativeTime(now, TimeZone.UTC)).to.equal("Jan 20, 2010")
end
end)
end
end)
end)
if not GetFFlagUseDateTimeType() then
describe("Comparisons", function()
describe("IsSame", function()
it("should equate dates with different granularity", function()
local value = LuaDateTime.new(2003, 6, 11, 15, 8, 9)
local same = LuaDateTime.new(2003, 6, 11, 15, 8, 9)
expect(value:IsSame(value)).to.equal(true)
expect(value:IsSame(same)).to.equal(true)
local units = {TimeUnit.Years, TimeUnit.Months, TimeUnit.Days, TimeUnit.Hours, TimeUnit.Minutes}
for _, unit in ipairs(units) do
expect(value:IsSame(same, unit)).to.equal(true)
end
local sameMinute = LuaDateTime.new(2003, 6, 11, 15, 8, 10)
expect(value:IsSame(sameMinute)).to.equal(false)
expect(value:IsSame(sameMinute, TimeUnit.Minutes)).to.equal(true)
expect(value:IsSame(sameMinute, TimeUnit.Years)).to.equal(true)
local sameHour = LuaDateTime.new(2003, 6, 11, 15, 9, 0)
expect(value:IsSame(sameHour)).to.equal(false)
expect(value:IsSame(sameHour, TimeUnit.Hours)).to.equal(true)
expect(value:IsSame(sameHour, TimeUnit.Years)).to.equal(true)
local sameDay = LuaDateTime.new(2003, 6, 11, 14, 8, 9)
expect(value:IsSame(sameDay)).to.equal(false)
expect(value:IsSame(sameDay, TimeUnit.Days)).to.equal(true)
expect(value:IsSame(sameDay, TimeUnit.Years)).to.equal(true)
local sameMonth = LuaDateTime.new(2003, 6, 12, 15, 8, 9)
expect(value:IsSame(sameMonth)).to.equal(false)
expect(value:IsSame(sameMonth, TimeUnit.Months)).to.equal(true)
expect(value:IsSame(sameMonth, TimeUnit.Years)).to.equal(true)
local sameYear = LuaDateTime.new(2003, 7, 12, 15, 8, 9)
expect(value:IsSame(sameYear)).to.equal(false)
expect(value:IsSame(sameYear, TimeUnit.Years)).to.equal(true)
local diffYear = LuaDateTime.new(2004, 6, 11, 15, 8, 9)
expect(value:IsSame(diffYear)).to.equal(false)
expect(value:IsSame(diffYear, TimeUnit.Years)).to.equal(false)
end)
it("should equate values using week boundaries", function()
local sunday = LuaDateTime.new(2017, 5, 7)
local saturday = LuaDateTime.new(2017, 5, 13)
local monday = LuaDateTime.new(2017, 5, 8)
local tuesday = LuaDateTime.new(2017, 5, 9)
-- TODO: Specify locale when that lands; default may break tests
local function sameWeek(a, b)
return a:IsSame(b, TimeUnit.Weeks, TimeZone.UTC)
end
expect(sameWeek(monday, monday)).to.equal(true)
expect(sameWeek(sunday, monday)).to.equal(true)
expect(sameWeek(tuesday, monday)).to.equal(true)
expect(sameWeek(saturday, monday)).to.equal(true)
local nextSunday = LuaDateTime.new(2017, 5, 14)
expect(sameWeek(nextSunday, monday)).to.equal(false)
end)
end)
end)
end
end
@@ -0,0 +1,8 @@
{
"language": {
"mode": "nonstrict"
},
"lint": {
"ImplicitReturn": "fatal"
}
}
@@ -0,0 +1,10 @@
local CorePackages = game:GetService("CorePackages")
local Players = game:GetService("Players")
local ThrottleUserId = require(CorePackages.AppTempCommon.LuaApp.Utils.ThrottleUserId)
return function()
return ThrottleUserId(
game:DefineFastInt("LuaChatUseNewFriendsEndpointsV2", 0),
Players.LocalPlayer.UserId
)
end
@@ -0,0 +1,8 @@
{
"language": {
"mode": "nonstrict"
},
"lint": {
"ImplicitReturn": "fatal"
}
}
@@ -0,0 +1,45 @@
local CorePackages = game:GetService("CorePackages")
local MockId = require(CorePackages.AppTempCommon.LuaApp.MockId)
local FFlagLuaAppConvertUniverseIdToString = settings():GetFFlag("LuaAppConvertUniverseIdToStringV364")
local PlaceInfoModel = {}
function PlaceInfoModel.new()
local self = {}
return self
end
function PlaceInfoModel.mock()
local self = PlaceInfoModel.new()
self.builder = "builder"
self.builderId = MockId()
self.description = "description"
self.imageToken = MockId()
self.isPlayable = true
self.name = "name"
self.placeId = MockId()
self.price = 0
self.reasonProhibited = nil
self.universeId = MockId()
self.universeRootPlaceId = MockId()
self.url = "url"
return self
end
function PlaceInfoModel.fromWeb(data)
local self = data or {}
self.placeId = tostring(self.placeId)
if FFlagLuaAppConvertUniverseIdToString then
self.universeId = tostring(self.universeId)
end
return self
end
return PlaceInfoModel
@@ -0,0 +1,8 @@
{
"language": {
"mode": "nonstrict"
},
"lint": {
"ImplicitReturn": "fatal"
}
}
@@ -0,0 +1,12 @@
local CorePackages = game:GetService("CorePackages")
local SetFriendCount = require(CorePackages.AppTempCommon.LuaApp.Actions.SetFriendCount)
return function(state, action)
state = state or 0
if action.type == SetFriendCount.name then
state = action.count
end
return state
end
@@ -0,0 +1,18 @@
return function()
local CorePackages = game:GetService("CorePackages")
local FriendCount = require(CorePackages.AppTempCommon.LuaChat.Reducers.FriendCount)
local SetFriendCount = require(CorePackages.AppTempCommon.LuaApp.Actions.SetFriendCount)
it("should be zero by default", function()
local state = FriendCount(nil, {})
expect(state).to.equal(0)
end)
it("should respond to SetFriendCount", function()
local state = FriendCount(nil, {})
state = FriendCount(state, SetFriendCount(520))
expect(state).to.equal(520)
end)
end
@@ -0,0 +1,22 @@
local CorePackages = game:GetService("CorePackages")
local Common = CorePackages.AppTempCommon.Common
local LuaChat = CorePackages.AppTempCommon.LuaChat
local ReceivedMultiplePlaceInfos = require(LuaChat.Actions.ReceivedMultiplePlaceInfos)
local Immutable = require(Common.Immutable)
return function(state, action)
state = state or {}
if action.type == ReceivedMultiplePlaceInfos.name then
local newInfos = {}
for _, placeInfo in ipairs(action.placeInfos) do
newInfos[placeInfo.placeId] = placeInfo
end
state = Immutable.JoinDictionaries(state, newInfos)
end
return state
end
@@ -0,0 +1,36 @@
return function()
local CorePackages = game:GetService("CorePackages")
local LuaApp = CorePackages.AppTempCommon.LuaApp
local LuaChat = CorePackages.AppTempCommon.LuaChat
local MockId = require(LuaApp.MockId)
local ReceivedMultiplePlaceInfos = require(LuaChat.Actions.ReceivedMultiplePlaceInfos)
local PlaceInfosReducer = require(script.Parent.PlaceInfos)
describe("initial state", function()
it("should return an initial table when passed nil", function()
local state = PlaceInfosReducer(nil, {})
expect(state).to.be.a("table")
end)
end)
describe("ReceivedMultiplePlaceInfos", function()
it("should add place info to the store", function()
local state = PlaceInfosReducer(nil, {})
local placeId = MockId()
local returnedPlaceInfo = ReceivedMultiplePlaceInfos({
{
placeId = placeId,
imageToken = "image-token",
},
})
state = PlaceInfosReducer(state, returnedPlaceInfo)
expect(state[placeId]).to.equal(returnedPlaceInfo.placeInfos[1])
end)
end)
end
@@ -0,0 +1,17 @@
local TimeUnit = setmetatable({}, {
__index = function(self, key)
error(("Invalid TimeUnit \"%s\""):format(tostring(key)), 2)
end
})
TimeUnit.Seconds = "Seconds"
TimeUnit.Minutes = "Minutes"
TimeUnit.Hours = "Hours"
TimeUnit.Days = "Days"
TimeUnit.Months = "Months"
TimeUnit.Years = "Years"
-- Locale-specific
TimeUnit.Weeks = "Weeks"
return TimeUnit
@@ -0,0 +1,10 @@
local TimeZone = setmetatable({}, {
__index = function(self, key)
error(("Invalid TimeZone \"%s\""):format(tostring(key)), 2)
end
})
TimeZone.UTC = -2
TimeZone.Current = -1
return TimeZone
@@ -0,0 +1,8 @@
{
"language": {
"mode": "nonstrict"
},
"lint": {
"ImplicitReturn": "fatal"
}
}
@@ -0,0 +1,19 @@
local CorePackages = game:GetService("CorePackages")
local User = require(CorePackages.AppTempCommon.LuaApp.Models.User)
local WebPresenceMap = require(CorePackages.AppTempCommon.LuaApp.Enum.WebPresenceMap)
local convertUniverseIdToString = require(CorePackages.AppTempCommon.LuaApp.Flags.ConvertUniverseIdToString)
return function(friendsPresence, store)
local placeIds = {}
for _, presenceModel in pairs(friendsPresence) do
local universeId = convertUniverseIdToString(presenceModel.universeId)
if WebPresenceMap[presenceModel.userPresenceType] == User.PresenceType.IN_GAME
and (not store:getState().UniversePlaceInfos[universeId]) then
table.insert(placeIds, presenceModel.placeId)
end
end
return placeIds
end
@@ -0,0 +1,32 @@
local CorePackages = game:GetService("CorePackages")
local ReceivedUserPresence = require(CorePackages.AppTempCommon.LuaChat.Actions.ReceivedUserPresence)
local WebPresenceMap = require(CorePackages.AppTempCommon.LuaApp.Enum.WebPresenceMap)
local FFlagLuaAppConvertUniverseIdToString = settings():GetFFlag("LuaAppConvertUniverseIdToStringV364")
return function(friendsPresence, store)
for _, presenceModel in pairs(friendsPresence) do
local userInStore = store:getState().Users[tostring(presenceModel.userId)]
local previousUniverseId = userInStore and userInStore.universeId or nil
local universeId
if FFlagLuaAppConvertUniverseIdToString then
universeId = presenceModel.universeId and tostring(presenceModel.universeId) or nil
else
universeId = presenceModel.universeId
end
store:dispatch(ReceivedUserPresence(
tostring(presenceModel.userId),
WebPresenceMap[presenceModel.userPresenceType],
presenceModel.lastLocation,
presenceModel.placeId and tostring(presenceModel.placeId) or nil,
presenceModel.rootPlaceId and tostring(presenceModel.rootPlaceId) or nil,
presenceModel.gameId and tostring(presenceModel.gameId) or nil,
presenceModel.lastOnline and tostring(presenceModel.lastOnline) or nil,
universeId,
previousUniverseId
))
end
end