mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-10-21 20:21:38 +00:00
Add permission management listings
This commit is contained in:
parent
4275783ba4
commit
7c1afd5aa9
5 changed files with 256 additions and 0 deletions
164
plugin/src/App/StatusPages/Permissions/Listing.lua
Normal file
164
plugin/src/App/StatusPages/Permissions/Listing.lua
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
local TextService = game:GetService("TextService")
|
||||
|
||||
local Rojo = script:FindFirstAncestor("Rojo")
|
||||
local Plugin = Rojo.Plugin
|
||||
local Packages = Rojo.Packages
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local Settings = require(Plugin.Settings)
|
||||
local Assets = require(Plugin.Assets)
|
||||
local Theme = require(Plugin.App.Theme)
|
||||
|
||||
local Checkbox = require(Plugin.App.Components.Checkbox)
|
||||
local Dropdown = require(Plugin.App.Components.Dropdown)
|
||||
local IconButton = require(Plugin.App.Components.IconButton)
|
||||
local SlicedImage = require(Plugin.App.Components.SlicedImage)
|
||||
|
||||
local e = Roact.createElement
|
||||
|
||||
local DIVIDER_FADE_SIZE = 0.1
|
||||
|
||||
local function getTextBounds(text, textSize, font, lineHeight, bounds)
|
||||
local textBounds = TextService:GetTextSize(text, textSize, font, bounds)
|
||||
|
||||
local lineCount = textBounds.Y / textSize
|
||||
local lineHeightAbsolute = textSize * lineHeight
|
||||
|
||||
return Vector2.new(textBounds.X, lineHeightAbsolute * lineCount - (lineHeightAbsolute - textSize))
|
||||
end
|
||||
|
||||
local Listing = Roact.Component:extend("Listing")
|
||||
|
||||
function Listing:init()
|
||||
self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0))
|
||||
self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0))
|
||||
end
|
||||
|
||||
function Listing:render()
|
||||
return Theme.with(function(theme)
|
||||
theme = theme.Settings
|
||||
|
||||
return e("Frame", {
|
||||
Size = self.contentSize:map(function(value)
|
||||
return UDim2.new(1, 0, 0, 20 + value.Y + 20)
|
||||
end),
|
||||
LayoutOrder = self.props.layoutOrder,
|
||||
ZIndex = -self.props.layoutOrder,
|
||||
BackgroundTransparency = 1,
|
||||
|
||||
[Roact.Change.AbsoluteSize] = function(object)
|
||||
self.setContainerSize(object.AbsoluteSize)
|
||||
end,
|
||||
}, {
|
||||
Settings = e("TextButton", {
|
||||
Text = "",
|
||||
BackgroundTransparency = 1,
|
||||
Size = UDim2.fromOffset(28, 28),
|
||||
Position = UDim2.fromScale(1, 0.5),
|
||||
AnchorPoint = Vector2.new(1, 0.5),
|
||||
|
||||
[Roact.Event.Activated] = function()
|
||||
self.props.onClick()
|
||||
end,
|
||||
}, {
|
||||
Button = Theme.with(function(theme)
|
||||
theme = theme.Checkbox
|
||||
return e(SlicedImage, {
|
||||
slice = Assets.Slices.RoundedBorder,
|
||||
color = theme.Inactive.BorderColor,
|
||||
transparency = self.props.transparency,
|
||||
size = UDim2.new(1, 0, 1, 0),
|
||||
}, {
|
||||
Icon = e("ImageLabel", {
|
||||
Image = Assets.Images.Icons.Settings,
|
||||
ImageColor3 = theme.Inactive.IconColor,
|
||||
ImageTransparency = self.props.transparency,
|
||||
|
||||
Size = UDim2.new(0, 16, 0, 16),
|
||||
Position = UDim2.new(0.5, 0, 0.5, 0),
|
||||
AnchorPoint = Vector2.new(0.5, 0.5),
|
||||
|
||||
BackgroundTransparency = 1,
|
||||
}),
|
||||
})
|
||||
end),
|
||||
}),
|
||||
|
||||
Text = e("Frame", {
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
Name = e("TextLabel", {
|
||||
Text = self.props.name,
|
||||
Font = Enum.Font.GothamBold,
|
||||
TextSize = 17,
|
||||
TextColor3 = theme.Setting.NameColor,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
TextTransparency = self.props.transparency,
|
||||
|
||||
Size = UDim2.new(1, 0, 0, 17),
|
||||
|
||||
LayoutOrder = 1,
|
||||
BackgroundTransparency = 1,
|
||||
}),
|
||||
|
||||
Description = e("TextLabel", {
|
||||
Text = self.props.description,
|
||||
Font = Enum.Font.Gotham,
|
||||
LineHeight = 1.2,
|
||||
TextSize = 14,
|
||||
TextColor3 = theme.Setting.DescriptionColor,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
TextTransparency = self.props.transparency,
|
||||
TextWrapped = true,
|
||||
|
||||
Size = self.containerSize:map(function(value)
|
||||
local textBounds = getTextBounds(
|
||||
self.props.description, 14, Enum.Font.Gotham, 1.2,
|
||||
Vector2.new(value.X - 40, math.huge)
|
||||
)
|
||||
return UDim2.new(1, - 40, 0, textBounds.Y)
|
||||
end),
|
||||
|
||||
LayoutOrder = 2,
|
||||
BackgroundTransparency = 1,
|
||||
}),
|
||||
|
||||
Layout = e("UIListLayout", {
|
||||
VerticalAlignment = Enum.VerticalAlignment.Center,
|
||||
FillDirection = Enum.FillDirection.Vertical,
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
Padding = UDim.new(0, 6),
|
||||
|
||||
[Roact.Change.AbsoluteContentSize] = function(object)
|
||||
self.setContentSize(object.AbsoluteContentSize)
|
||||
end,
|
||||
}),
|
||||
|
||||
Padding = e("UIPadding", {
|
||||
PaddingTop = UDim.new(0, 20),
|
||||
PaddingBottom = UDim.new(0, 20),
|
||||
}),
|
||||
}),
|
||||
|
||||
Divider = e("Frame", {
|
||||
BackgroundColor3 = theme.DividerColor,
|
||||
BackgroundTransparency = self.props.transparency,
|
||||
Size = UDim2.new(1, 0, 0, 1),
|
||||
BorderSizePixel = 0,
|
||||
}, {
|
||||
Gradient = e("UIGradient", {
|
||||
Transparency = NumberSequence.new({
|
||||
NumberSequenceKeypoint.new(0, 1),
|
||||
NumberSequenceKeypoint.new(DIVIDER_FADE_SIZE, 0),
|
||||
NumberSequenceKeypoint.new(1 - DIVIDER_FADE_SIZE, 0),
|
||||
NumberSequenceKeypoint.new(1, 1),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
end)
|
||||
end
|
||||
|
||||
return Listing
|
||||
|
|
@ -11,6 +11,7 @@ local Theme = require(Plugin.App.Theme)
|
|||
local IconButton = require(Plugin.App.Components.IconButton)
|
||||
local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame)
|
||||
local Tooltip = require(Plugin.App.Components.Tooltip)
|
||||
local Listing = require(script.Listing)
|
||||
|
||||
local e = Roact.createElement
|
||||
|
||||
|
|
@ -64,6 +65,42 @@ function PermissionsPage:render()
|
|||
return Theme.with(function(theme)
|
||||
theme = theme.Settings
|
||||
|
||||
local sources = {}
|
||||
if next(self.props.headlessAPI._permissions) == nil then
|
||||
sources.noSources = e("TextLabel", {
|
||||
Text = "No third-party plugins have been granted permissions.",
|
||||
Font = Enum.Font.Gotham,
|
||||
TextSize = 18,
|
||||
TextColor3 = theme.Setting.DescriptionColor,
|
||||
TextTransparency = self.props.transparency,
|
||||
TextWrapped = true,
|
||||
|
||||
Size = UDim2.new(1, 0, 0, 48),
|
||||
LayoutOrder = 0,
|
||||
|
||||
BackgroundTransparency = 1,
|
||||
})
|
||||
else
|
||||
for source in self.props.headlessAPI._permissions do
|
||||
local meta = self.props.headlessAPI:_getMetaFromSource(source)
|
||||
sources[source] = e(Listing, {
|
||||
layoutOrder = string.byte(source),
|
||||
transparency = self.props.transparency,
|
||||
|
||||
name = meta.Name,
|
||||
description = string.format(
|
||||
"%s plugin%s",
|
||||
meta.Type,
|
||||
if meta.Creator then " by " .. meta.Creator else ""
|
||||
),
|
||||
|
||||
onClick = function()
|
||||
self.props.onEdit(source, meta, self.props.headlessAPI._permissions[source] or {})
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
return e(ScrollingFrame, {
|
||||
size = UDim2.new(1, 0, 1, 0),
|
||||
contentSize = self.contentSize,
|
||||
|
|
@ -84,6 +121,8 @@ function PermissionsPage:render()
|
|||
end,
|
||||
}),
|
||||
|
||||
Sources = Roact.createFragment(sources),
|
||||
|
||||
Padding = e("UIPadding", {
|
||||
PaddingLeft = UDim.new(0, 20),
|
||||
PaddingRight = UDim.new(0, 20),
|
||||
|
|
|
|||
|
|
@ -519,11 +519,26 @@ function App:render()
|
|||
}),
|
||||
|
||||
Permissions = createPageElement(AppStatus.Permissions, {
|
||||
headlessAPI = self.headlessAPI,
|
||||
|
||||
onBack = function()
|
||||
self:setState({
|
||||
appStatus = AppStatus.Settings,
|
||||
})
|
||||
end,
|
||||
|
||||
onEdit = function(source, meta, apiMap)
|
||||
local apiList = {}
|
||||
for api in apiMap do
|
||||
table.insert(apiList, api)
|
||||
end
|
||||
self:requestPermission(
|
||||
source,
|
||||
meta.Name .. if meta.Creator then " by " .. meta.Creator else "",
|
||||
apiList,
|
||||
apiMap
|
||||
)
|
||||
end,
|
||||
}),
|
||||
|
||||
Error = createPageElement(AppStatus.Error, {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ local Assets = {
|
|||
Back = "rbxassetid://6017213752",
|
||||
Reset = "rbxassetid://10142422327",
|
||||
Expand = "rbxassetid://12045401097",
|
||||
Settings = "rbxassetid://12046309515",
|
||||
},
|
||||
Checkbox = {
|
||||
Active = "rbxassetid://6016251644",
|
||||
|
|
|
|||
|
|
@ -95,6 +95,43 @@ function API.new(app)
|
|||
return "Command Bar"
|
||||
end
|
||||
|
||||
function Rojo:_getMetaFromSource(source)
|
||||
local localPlugin = string.match(source, "user_(.+)")
|
||||
if localPlugin then
|
||||
return {
|
||||
Type = "Local",
|
||||
Name = localPlugin,
|
||||
}
|
||||
end
|
||||
|
||||
local cloudId = string.match(source, "cloud_(%d+)")
|
||||
if cloudId then
|
||||
local info = cloudIdInfoCache[cloudId]
|
||||
if info then
|
||||
return {
|
||||
Type = "Cloud",
|
||||
Name = info.Name,
|
||||
Creator = info.Creator.Name,
|
||||
}
|
||||
else
|
||||
local success, newInfo = pcall(MarketplaceService.GetProductInfo, MarketplaceService, tonumber(cloudId), Enum.InfoType.Asset)
|
||||
if success then
|
||||
cloudIdInfoCache[cloudId] = newInfo
|
||||
return {
|
||||
Type = "Cloud",
|
||||
Name = newInfo.Name,
|
||||
Creator = newInfo.Creator.Name,
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
Type = "Studio",
|
||||
Name = "Command Bar",
|
||||
}
|
||||
end
|
||||
|
||||
function Rojo:_getCallerType()
|
||||
local traceback = string.split(debug.traceback(), "\n")
|
||||
local topLevel = traceback[#traceback - 1]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue