Skip to content

Display unavailable storybooks #318

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

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added img/Alert.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
94 changes: 94 additions & 0 deletions src/Common/CodeBlock.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
local Highlighter = require("@pkg/Highlighter")
local React = require("@pkg/React")
local Sift = require("@pkg/Sift")

local SelectableTextLabel = require("@root/Forms/SelectableTextLabel")
local nextLayoutOrder = require("@root/Common/nextLayoutOrder")
local useTheme = require("@root/Common/useTheme")

local useMemo = React.useMemo

local function getLineNumbers(str: string): string
return Sift.List.reduce(str:split("\n"), function(accumulator, _item, index)
return if index == 1 then tostring(index) else `{accumulator}\n{index}`
end, "")
end

export type Props = {
source: string,
sourceColor: Color3?,
layoutOrder: number?,
}

local function CodeBlock(props: Props)
local theme = useTheme()

local sourceColor = useMemo(function()
return if props.sourceColor then props.sourceColor else theme.text
end, { props.sourceColor })

local source = useMemo(function()
if props.sourceColor then
return props.source
else
return table.concat(
Highlighter.buildRichTextLines({
src = props.source,
}),
"\n"
)
end
end, { props.source })

return React.createElement("Frame", {
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 0.5,
BorderSizePixel = 0,
BackgroundColor3 = theme.sidebar,
LayoutOrder = props.layoutOrder,
}, {
Layout = React.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Horizontal,
Padding = theme.padding,
}),

BorderRadius = React.createElement("UICorner", {
CornerRadius = theme.corner,
}),

Padding = React.createElement("UIPadding", {
PaddingTop = theme.padding,
PaddingRight = theme.padding,
PaddingBottom = theme.padding,
PaddingLeft = theme.padding,
}),

LineNumbers = React.createElement("TextLabel", {
LayoutOrder = nextLayoutOrder(),
AutomaticSize = Enum.AutomaticSize.XY,
Text = getLineNumbers(source),
TextSize = theme.textSize,
LineHeight = 1,
BackgroundTransparency = 1,
Font = Enum.Font.RobotoMono,
TextColor3 = theme.textFaded,
TextXAlignment = Enum.TextXAlignment.Right,
}),

SourceCode = React.createElement(SelectableTextLabel, {
RichText = true,
LayoutOrder = nextLayoutOrder(),
Size = UDim2.fromScale(1, 0),
AutomaticSize = Enum.AutomaticSize.Y,
Text = source,
TextColor3 = sourceColor,
TextSize = theme.textSize,
TextWrapped = false,
LineHeight = 1,
Font = Enum.Font.RobotoMono,
}),
})
end

return CodeBlock
9 changes: 5 additions & 4 deletions src/Navigation/Screen.luau
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
local ModuleLoader = require("@pkg/ModuleLoader")
local React = require("@pkg/React")
local Storyteller = require("@pkg/Storyteller")

Expand All @@ -7,14 +6,13 @@ local NavigationContext = require("@root/Navigation/NavigationContext")
local NoStorySelected = require("@root/Storybook/NoStorySelected")
local SettingsView = require("@root/UserSettings/SettingsView")
local StoryCanvas = require("@root/Storybook/StoryCanvas")
local StorybookError = require("@root/Storybook/StorybookError")

local useMemo = React.useMemo

type ModuleLoader = ModuleLoader.ModuleLoader
type LoadedStorybook = Storyteller.LoadedStorybook

export type Props = {
loader: ModuleLoader,
story: ModuleScript?,
storybook: LoadedStorybook?,
}
Expand All @@ -27,10 +25,13 @@ local function Screen(props: Props)
if currentScreen == "Home" then
if props.story and props.storybook then
return React.createElement(StoryCanvas, {
loader = props.loader,
story = props.story,
storybook = props.storybook,
})
elseif props.unavailableStorybook then
return React.createElement(StorybookError, {
unavailableStorybook = props.unavailableStorybook,
})
else
return React.createElement(NoStorySelected)
end
Expand Down
8 changes: 7 additions & 1 deletion src/Panels/Sidebar.luau
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ local StorybookTreeView = require("@root/Storybook/StorybookTreeView")
local useTheme = require("@root/Common/useTheme")

type LoadedStorybook = Storyteller.LoadedStorybook
type UnavailableStorybook = Storyteller.UnavailableStorybook

local e = React.createElement

type Props = {
layoutOrder: number?,
onStoryChanged: (storyModule: ModuleScript?, storybook: LoadedStorybook?) -> (),
storybooks: { LoadedStorybook },
onShowErrorPage: (unavailableStorybook: UnavailableStorybook) -> (),
storybooks: {
avialable: { LoadedStorybook },
unavailable: { UnavailableStorybook },
},
}

local function Sidebar(props: Props)
Expand Down Expand Up @@ -82,6 +87,7 @@ local function Sidebar(props: Props)
searchTerm = search,
storybooks = props.storybooks,
onStoryChanged = props.onStoryChanged,
onShowErrorPage = props.onShowErrorPage,
}),
}),
})
Expand Down
20 changes: 13 additions & 7 deletions src/Plugin/PluginApp.luau
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
local ModuleLoader = require("@pkg/ModuleLoader")
local React = require("@pkg/React")
local Storyteller = require("@pkg/Storyteller")

Expand All @@ -15,6 +14,7 @@ local useTheme = require("@root/Common/useTheme")
local TOPBAR_HEIGHT_PX = 32

type LoadedStorybook = Storyteller.LoadedStorybook
type UnavailableStorybook = Storyteller.UnavailableStorybook

export type Props = {
loader: ModuleLoader.ModuleLoader,
Expand All @@ -26,20 +26,25 @@ local function App(props: Props)
local storybooks = Storyteller.useStorybooks(game, props.loader)
local storyModule: ModuleScript?, setStoryModule = React.useState(nil :: ModuleScript?)
local storybook, setStorybook = React.useState(nil :: LoadedStorybook?)
local unavailableStorybook, setUnavailableStorybook = React.useState(nil :: LoadedStorybook?)
local initialSidebarWidth = settingsContext.getSetting("sidebarWidth")
local sidebarWidth, setSidebarWidth = React.useState(initialSidebarWidth)
local navigation = NavigationContext.use()

local onStoryChanged = React.useCallback(function(newStoryModule: ModuleScript?, newStorybook: LoadedStorybook?)
navigation.navigateTo("Home")

setStoryModule(function(prev: ModuleScript?)
return if prev ~= newStoryModule then newStoryModule else nil
end)

setUnavailableStorybook(nil)
setStoryModule(newStoryModule)
setStorybook(newStorybook)
end, { navigation.navigateTo } :: { unknown })

local onShowErrorPage = React.useCallback(function(newUnavailableStorybook: UnavailableStorybook)
setStoryModule(nil)
setStorybook(nil)
setUnavailableStorybook(newUnavailableStorybook)
end, {})

local onSidebarResized = React.useCallback(function(newSize: Vector2)
setSidebarWidth(newSize.X)
end, {})
Expand Down Expand Up @@ -67,7 +72,8 @@ local function App(props: Props)
}, {
Sidebar = React.createElement(Sidebar, {
onStoryChanged = onStoryChanged,
storybooks = storybooks.available,
onShowErrorPage = onShowErrorPage,
storybooks = storybooks,
}),
}),

Expand All @@ -91,9 +97,9 @@ local function App(props: Props)
BackgroundTransparency = 1,
}, {
Screen = React.createElement(Screen, {
loader = props.loader,
story = storyModule,
storybook = storybook,
unavailableStorybook = unavailableStorybook,
}),
}),
}),
Expand Down
27 changes: 23 additions & 4 deletions src/Storybook/StoryError.luau
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
local React = require("@pkg/React")
local SelectableTextLabel = require("@root/Forms/SelectableTextLabel")

local CodeBlock = require("@root/Common/CodeBlock")
local ScrollingFrame = require("@root/Common/ScrollingFrame")
local useTheme = require("@root/Common/useTheme")

export type Props = {
Expand All @@ -10,10 +12,27 @@ export type Props = {
local function StoryError(props: Props)
local theme = useTheme()

return React.createElement(SelectableTextLabel, {
return React.createElement(ScrollingFrame, {
ScrollingDirection = Enum.ScrollingDirection.XY,
LayoutOrder = props.layoutOrder,
Text = props.err,
TextColor3 = theme.alert,
}, {
Layout = React.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Horizontal,
Padding = theme.padding,
}),

Padding = React.createElement("UIPadding", {
PaddingTop = theme.paddingSmall,
PaddingRight = theme.paddingSmall,
PaddingBottom = theme.paddingSmall,
PaddingLeft = theme.paddingSmall,
}),

CodeBlock = React.createElement(CodeBlock, {
source = props.err,
sourceColor = theme.alert,
}),
})
end

Expand Down
111 changes: 111 additions & 0 deletions src/Storybook/StorybookError.luau
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
local React = require("@pkg/React")
local Storyteller = require("@pkg/Storyteller")

local CodeBlock = require("@root/Common/CodeBlock")
local ScrollingFrame = require("@root/Common/ScrollingFrame")
local nextLayoutOrder = require("@root/Common/nextLayoutOrder")
local useTheme = require("@root/Common/useTheme")

type UnavailableStorybook = Storyteller.UnavailableStorybook

export type Props = {
unavailableStorybook: UnavailableStorybook,
layoutOrder: number?,
}

local function StorybookError(props: Props)
local theme = useTheme()

local storybookSource = props.unavailableStorybook.storybook.source.Source

return React.createElement(ScrollingFrame, {
ScrollingDirection = Enum.ScrollingDirection.XY,
LayoutOrder = props.layoutOrder,
}, {
Layout = React.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Vertical,
Padding = theme.paddingLarge,
}),

Padding = React.createElement("UIPadding", {
PaddingTop = theme.paddingLarge,
PaddingRight = theme.paddingLarge,
PaddingBottom = theme.paddingLarge,
PaddingLeft = theme.paddingLarge,
}),

MainText = React.createElement("TextLabel", {
LayoutOrder = nextLayoutOrder(),
Text = `Failed to load {props.unavailableStorybook.storybook.name}`,
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
Font = theme.font,
TextColor3 = theme.text,
TextSize = theme.textSize,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Center,
}),

Problem = React.createElement("Frame", {
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
LayoutOrder = nextLayoutOrder(),
}, {
Layout = React.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Vertical,
Padding = theme.padding,
}),

Title = React.createElement("TextLabel", {
LayoutOrder = nextLayoutOrder(),
Text = "Error",
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
Font = theme.headerFont,
TextColor3 = theme.text,
TextSize = theme.headerTextSize,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Center,
}),

CodeBlock = React.createElement(CodeBlock, {
source = props.unavailableStorybook.problem,
sourceColor = theme.alert,
layoutOrder = nextLayoutOrder(),
}),
}),

StorybookSource = React.createElement("Frame", {
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
LayoutOrder = nextLayoutOrder(),
}, {
Layout = React.createElement("UIListLayout", {
SortOrder = Enum.SortOrder.LayoutOrder,
FillDirection = Enum.FillDirection.Vertical,
Padding = theme.padding,
}),

Title = React.createElement("TextLabel", {
LayoutOrder = nextLayoutOrder(),
Text = "Storybook Source",
AutomaticSize = Enum.AutomaticSize.XY,
BackgroundTransparency = 1,
Font = theme.headerFont,
TextColor3 = theme.text,
TextSize = theme.headerTextSize,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Center,
}),

CodeBlock = React.createElement(CodeBlock, {
source = storybookSource,
layoutOrder = nextLayoutOrder(),
}),
}),
})
end

return StorybookError
Loading
Loading