Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inform non-connected users of active serves #588

Closed
wants to merge 9 commits into from
1 change: 1 addition & 0 deletions plugin/src/App/Components/BorderedContainer.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ local function BorderedContainer(props)
slice = Assets.Slices.RoundedBackground,
color = theme.BorderedContainer.BackgroundColor,
transparency = props.transparency,
clipsDescendants = props.clipsDescendants,

size = props.size,
position = props.position,
Expand Down
1 change: 1 addition & 0 deletions plugin/src/App/Components/SlicedImage.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ local function SlicedImage(props)
ZIndex = props.zIndex,
LayoutOrder = props.layoutOrder,
BackgroundTransparency = 1,
ClipsDescendants = props.clipsDescendants,
}, props[Roact.Children])
end

Expand Down
4 changes: 2 additions & 2 deletions plugin/src/App/Components/TextButton.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ end
function TextButton:render()
return Theme.with(function(theme)
local textSize = TextService:GetTextSize(
self.props.text, 18, Enum.Font.GothamSemibold,
self.props.text, 18, Enum.Font.GothamMedium,
Vector2.new(math.huge, math.huge)
)

Expand Down Expand Up @@ -85,7 +85,7 @@ function TextButton:render()

Text = e("TextLabel", {
Text = self.props.text,
Font = Enum.Font.GothamSemibold,
Font = Enum.Font.GothamMedium,
TextSize = 18,
TextColor3 = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.TextColor, theme.Disabled.TextColor),
TextTransparency = self.props.transparency,
Expand Down
148 changes: 81 additions & 67 deletions plugin/src/App/Notifications.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ local Theme = require(Plugin.App.Theme)
local Assets = require(Plugin.Assets)

local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
local TextButton = require(Plugin.App.Components.TextButton)

local baseClock = DateTime.now().UnixTimestampMillis

Expand Down Expand Up @@ -86,12 +87,10 @@ function Notification:willUnmount()
end

function Notification:render()
local time = DateTime.fromUnixTimestampMillis(self.props.timestamp)

local textBounds = TextService:GetTextSize(
self.props.text,
15,
Enum.Font.GothamSemibold,
Enum.Font.GothamMedium,
Vector2.new(350, 700)
)

Expand All @@ -101,76 +100,90 @@ function Notification:render()

local size = self.binding:map(function(value)
return UDim2.fromOffset(
(35+40+textBounds.X)*value,
math.max(14+20+textBounds.Y, 32+20)
(40+textBounds.X)*value,
textBounds.Y + 34 + 20 + 10
)
end)

return Theme.with(function(theme)
return e("TextButton", {
BackgroundTransparency = 1,
Size = size,
LayoutOrder = self.props.layoutOrder,
Text = "",
ClipsDescendants = true,

[Roact.Event.Activated] = function()
local actionButtons = {}
actionButtons.Layout = e("UIListLayout", {
FillDirection = Enum.FillDirection.Horizontal,
SortOrder = Enum.SortOrder.LayoutOrder,
HorizontalAlignment = Enum.HorizontalAlignment.Right,
Padding = UDim.new(0, 5),
})

if self.props.actions and next(self.props.actions) then
for text, action in self.props.actions do
actionButtons[text] = e(TextButton, {
layoutOrder = -(action.layoutOrder or 1),
text = action.text or text,
style = action.style or "Bordered",
transparency = transparency,
onClick = function()
task.spawn(pcall, action.onClick)
self:dismiss()
end,
})
end
else
actionButtons["Dismiss"] = e(TextButton, {
text = "Dismiss",
style = "Bordered",
transparency = transparency,
onClick = function()
self:dismiss()
end,
})
end

return Theme.with(function(theme)
return e(BorderedContainer, {
size = size,
layoutOrder = self.props.layoutOrder,
clipsDescendants = true,
transparency = transparency,
}, {
e(BorderedContainer, {
transparency = transparency,
size = UDim2.new(1, 0, 1, 0),
}, {
TextContainer = e("Frame", {
Size = UDim2.new(0, 35+textBounds.X, 1, -20),
Position = UDim2.new(0, 0, 0, 10),
BackgroundTransparency = 1
}, {
Logo = e("ImageLabel", {
ImageTransparency = transparency,
Image = Assets.Images.PluginButton,
BackgroundTransparency = 1,
Size = UDim2.new(0, 32, 0, 32),
Position = UDim2.new(0, 0, 0.5, 0),
AnchorPoint = Vector2.new(0, 0.5),
}),
Info = e("TextLabel", {
Text = self.props.text,
Font = Enum.Font.GothamSemibold,
TextSize = 15,
TextColor3 = theme.Notification.InfoColor,
TextTransparency = transparency,
TextXAlignment = Enum.TextXAlignment.Left,
TextWrapped = true,

Size = UDim2.new(0, textBounds.X, 0, textBounds.Y),
Position = UDim2.fromOffset(35, 0),

LayoutOrder = 1,
BackgroundTransparency = 1,
}),
Time = e("TextLabel", {
Text = time:FormatLocalTime("LTS", "en-us"),
Font = Enum.Font.Code,
TextSize = 12,
TextColor3 = theme.Notification.InfoColor,
TextTransparency = transparency,
TextXAlignment = Enum.TextXAlignment.Left,

Size = UDim2.new(1, -35, 0, 14),
Position = UDim2.new(0, 35, 1, -14),

LayoutOrder = 1,
BackgroundTransparency = 1,
}),
}),

Padding = e("UIPadding", {
PaddingLeft = UDim.new(0, 17),
PaddingRight = UDim.new(0, 15),
}),
})
Info = e("TextLabel", {
Text = self.props.text,
Font = Enum.Font.GothamMedium,
TextSize = 15,
TextColor3 = theme.Notification.InfoColor,
TextTransparency = transparency,
TextXAlignment = Enum.TextXAlignment.Left,
TextWrapped = true,

Size = UDim2.new(1, 0, 0, textBounds.Y),

LayoutOrder = 1,
BackgroundTransparency = 1,
}),

Logo = e("ImageLabel", {
Image = Assets.Images.Logo,
ImageColor3 = theme.Header.LogoColor,
ImageTransparency = transparency,
ScaleType = Enum.ScaleType.Fit,
BackgroundTransparency = 1,

Size = UDim2.new(0, 60, 0, 34),
Position = UDim2.new(0, 0, 1, 0),
AnchorPoint = Vector2.new(0, 1),
}),

Actions = e("Frame", {
Size = UDim2.new(1, -70, 0, 34),
Position = UDim2.new(1, 0, 1, 0),
AnchorPoint = Vector2.new(1, 1),
BackgroundTransparency = 1,
}, actionButtons),

Padding = e("UIPadding", {
PaddingLeft = UDim.new(0, 17),
PaddingRight = UDim.new(0, 10),
PaddingTop = UDim.new(0, 10),
PaddingBottom = UDim.new(0, 10),
}),
})
end)
end
Expand All @@ -186,6 +199,7 @@ function Notifications:render()
text = notif.text,
timestamp = notif.timestamp,
timeout = notif.timeout,
actions = notif.actions,
layoutOrder = (notif.timestamp - baseClock),
onClose = function()
self.props.onClose(index)
Expand Down
14 changes: 11 additions & 3 deletions plugin/src/App/StatusPages/Settings/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,28 +78,36 @@ function SettingsPage:render()
layoutOrder = 1,
}),

FindServedProjects = e(Setting, {
id = "findServedProjects",
name = "Find Served Projects",
description = "Periodically scan for served projects when not yet connected",
transparency = self.props.transparency,
layoutOrder = 2,
}),

ShowNotifications = e(Setting, {
id = "showNotifications",
name = "Show Notifications",
description = "Popup notifications in viewport",
transparency = self.props.transparency,
layoutOrder = 2,
layoutOrder = 3,
}),

PlaySounds = e(Setting, {
id = "playSounds",
name = "Play Sounds",
description = "Toggle sound effects",
transparency = self.props.transparency,
layoutOrder = 3,
layoutOrder = 4,
}),

TwoWaySync = e(Setting, {
id = "twoWaySync",
name = "Two-Way Sync",
description = "EXPERIMENTAL! Editing files in Studio will sync them into the filesystem",
transparency = self.props.transparency,
layoutOrder = 4,
layoutOrder = 5,
}),

Layout = e("UIListLayout", {
Expand Down
78 changes: 73 additions & 5 deletions plugin/src/App/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,22 @@ function App:init()
notifications = {},
toolbarIcon = Assets.Images.PluginButton,
})

self.ignoredScans = {}
self.scanLoop = true
task.defer(function()
while self.scanLoop do
self:scanForNonconnectedProject()
task.wait(30)
end
end)
end

function App:willUnmount()
self.scanLoop = false
end

function App:addNotification(text: string, timeout: number?)
function App:addNotification(text: string, timeout: number?, actions: {[string]: () -> any}?)
if not Settings:get("showNotifications") then
return
end
Expand All @@ -66,6 +79,7 @@ function App:addNotification(text: string, timeout: number?)
text = text,
timestamp = DateTime.now().UnixTimestampMillis,
timeout = timeout or 3,
actions = actions,
})

self:setState({
Expand All @@ -86,10 +100,60 @@ function App:getHostAndPort()
local host = self.host:getValue()
local port = self.port:getValue()

local host = if #host > 0 then host else Config.defaultHost
local port = if #port > 0 then port else Config.defaultPort
return
if #host > 0 then host else Config.defaultHost,
if #port > 0 then port else Config.defaultPort
end

function App:findServedProject()
local host, port = self:getHostAndPort()

local baseUrl = ("http://%s:%s"):format(host, port)
local apiContext = ApiContext.new(baseUrl)

return host, port
local _, found, value = apiContext:connect()
:andThen(function(serverInfo)
apiContext:disconnect()
return true, serverInfo.projectName
end)
:catch(function(err)
return false, err
end):await()

return found, value
end

function App:scanForNonconnectedProject()
if self.serveSession ~= nil or not Settings:get("findServedProjects") then
return
end

local found, projectName = self:findServedProject()
if found == false or self.ignoredScans[projectName] then
return
end

local msg = string.format(
"Found served project '%s', but you are not connected. Did you mean to connect?",
projectName
)
Log.warn(msg)
self:addNotification(msg, 10, {
Connect = {
onClick = function()
self:startSession()
end,
style = "Solid",
layoutOrder = 1,
},
Ignore = {
onClick = function()
self.ignoredScans[projectName] = true
end,
style = "Bordered",
layoutOrder = 2,
},
})
end

function App:startSession()
Expand Down Expand Up @@ -309,7 +373,11 @@ function App:render()
end),
}),

RojoNotifications = e("ScreenGui", {}, {
RojoNotifications = e("ScreenGui", {
ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
ResetOnSpawn = false,
DisplayOrder = 100,
}, {
layout = e("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
HorizontalAlignment = Enum.HorizontalAlignment.Right,
Expand Down
1 change: 1 addition & 0 deletions plugin/src/Settings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ local defaultSettings = {
openScriptsExternally = false,
twoWaySync = false,
showNotifications = true,
findServedProjects = true,
playSounds = true,
}

Expand Down