mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-09 07:48:55 +00:00
LF it all!! - And actual tgui3
This commit is contained in:
@@ -8,6 +8,8 @@ env:
|
||||
es6: true
|
||||
browser: true
|
||||
node: true
|
||||
globals:
|
||||
Byond: readonly
|
||||
plugins:
|
||||
- react
|
||||
settings:
|
||||
@@ -388,7 +390,7 @@ rules:
|
||||
## Enforce a particular style for multiline comments
|
||||
# multiline-comment-style: error
|
||||
## Enforce newlines between operands of ternary expressions
|
||||
multiline-ternary: [error, always-multiline]
|
||||
# multiline-ternary: [error, always-multiline]
|
||||
## Require constructor names to begin with a capital letter
|
||||
# new-cap: error
|
||||
## Enforce or disallow parentheses when invoking a constructor with no
|
||||
|
||||
9
tgui/.gitattributes
vendored
9
tgui/.gitattributes
vendored
@@ -2,9 +2,18 @@
|
||||
|
||||
## Enforce text mode and LF line breaks
|
||||
*.js text eol=lf
|
||||
*.jsx text eol=lf
|
||||
*.ts text eol=lf
|
||||
*.tsx text eol=lf
|
||||
*.css text eol=lf
|
||||
*.scss text eol=lf
|
||||
*.html text eol=lf
|
||||
*.json text eol=lf
|
||||
*.yml text eol=lf
|
||||
*.md text eol=lf
|
||||
*.bat text eol=lf
|
||||
yarn.lock text eol=lf
|
||||
bin/tgui text eol=lf
|
||||
|
||||
## Treat bundles as binary and ignore them during conflicts
|
||||
*.bundle.* binary merge=tgui-merge-bundle
|
||||
|
||||
@@ -67,8 +67,9 @@ Run one of the following:
|
||||
game as you code it. Very useful, highly recommended.
|
||||
- In order to use it, you should start the game server first, connect to it
|
||||
and wait until the world has been properly loaded and you are no longer
|
||||
in the lobby. Start tgui dev server. You'll know that it's hooked correctly
|
||||
if data gets dumped to the log when tgui windows are opened.
|
||||
in the lobby. Start tgui dev server, and once it has finished building,
|
||||
press F5 on any tgui window. You'll know that it's hooked correctly if
|
||||
you see a green bug icon in titlebar and data gets dumped to the console.
|
||||
- `bin/tgui --dev --reload` - reload byond cache once.
|
||||
- `bin/tgui --dev --debug` - run server with debug logging enabled.
|
||||
- `bin/tgui --dev --no-hot` - disable hot module replacement (helps when
|
||||
@@ -134,11 +135,11 @@ logs and time spent on rendering. Use this information to optimize your
|
||||
code, and try to keep re-renders below 16ms.
|
||||
|
||||
**Kitchen Sink.**
|
||||
Press `Ctrl+Alt+=` to open the KitchenSink interface. This interface is a
|
||||
Press `F12` to open the KitchenSink interface. This interface is a
|
||||
playground to test various tgui components.
|
||||
|
||||
**Layout Debugger.**
|
||||
Press `Ctrl+Alt+-` to toggle the *layout debugger*. It will show outlines of
|
||||
Press `F11` to toggle the *layout debugger*. It will show outlines of
|
||||
all tgui elements, which makes it easy to understand how everything comes
|
||||
together, and can reveal certain layout bugs which are not normally visible.
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ task-dev-server() {
|
||||
task-eslint() {
|
||||
cd "${base_dir}"
|
||||
eslint ./packages "${@}"
|
||||
echo "tgui: eslint check passed"
|
||||
}
|
||||
|
||||
## Mr. Proper
|
||||
@@ -153,6 +154,13 @@ if [[ ${1} == '--lint-harder' ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ ${1} == '--fix' ]]; then
|
||||
shift 1
|
||||
task-install
|
||||
task-eslint --fix "${@}"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
## Analyze the bundle
|
||||
if [[ ${1} == '--analyze' ]]; then
|
||||
task-install
|
||||
|
||||
@@ -275,11 +275,11 @@ interface.
|
||||
|
||||
Example (button):
|
||||
|
||||
```
|
||||
```jsx
|
||||
<ByondUi
|
||||
params={{
|
||||
id: 'test_button', // optional, can be auto-generated
|
||||
parent: config.window,
|
||||
parent: 'some_container', // optional, defaults to the current window
|
||||
type: 'button',
|
||||
text: 'Hello, world!',
|
||||
}} />
|
||||
@@ -287,11 +287,10 @@ Example (button):
|
||||
|
||||
Example (map):
|
||||
|
||||
```
|
||||
```jsx
|
||||
<ByondUi
|
||||
params={{
|
||||
id: 'test_map',
|
||||
parent: config.window,
|
||||
type: 'map',
|
||||
}} />
|
||||
```
|
||||
@@ -982,6 +981,7 @@ Example:
|
||||
- `className: string` - Applies a CSS class to the element.
|
||||
- `theme: string` - A name of the theme.
|
||||
- For a list of themes, see `packages/tgui/styles/themes`.
|
||||
- `title: string` - Window title.
|
||||
- `resizable: boolean` - Controls resizability of the window.
|
||||
- `children: any` - Child elements, which are rendered directly inside the
|
||||
window. If you use a [Dimmer](#dimmer) or [Modal](#modal) in your UI,
|
||||
|
||||
@@ -73,6 +73,7 @@ This might look a bit intimidating compared to the reactive part but it's not as
|
||||
You don't really need to know all this to understand how to use it, but I find it helps with understanding when things go wrong.
|
||||
|
||||
Ractive conditionals can have an `else` as well
|
||||
|
||||
```ractive
|
||||
{{#if data.condition}}
|
||||
value
|
||||
@@ -116,7 +117,7 @@ and you can mix string literals, values, and tags as well.
|
||||
Ractive has loops for iterating over data and inserting something for each
|
||||
member of an array or object
|
||||
|
||||
```
|
||||
```ractive
|
||||
{{#each data.list_of_foo}}
|
||||
foo {{number}} is here.
|
||||
{{/each}}
|
||||
@@ -135,6 +136,7 @@ Objects are represented by `{}`, arrays by `[]`
|
||||
`list("bla", "blo")` would become `["bla", "blo"]` and `list("foo" = 1, "bar" = 2)` would become `{"foo": 1, "bar": 2}`
|
||||
|
||||
First things first, above the `return` of the function you're making the interface in, you're going to want to add something like this
|
||||
|
||||
```jsx
|
||||
const things = data.things || [];
|
||||
```
|
||||
@@ -142,6 +144,7 @@ const things = data.things || [];
|
||||
This ensures that you'll never be reading a null entry by mistake. Substitute `{}` for objects as appropriate.
|
||||
|
||||
If it's an array, you'll want to do this in the template
|
||||
|
||||
```jsx
|
||||
{things.map(thing => (
|
||||
<Fragment>
|
||||
@@ -187,7 +190,7 @@ const fooArray = toArray(fooObject);
|
||||
|
||||
Also occasionally you'd see an else:
|
||||
|
||||
```
|
||||
```ractive
|
||||
{{#each data.potentially_empty_list}}
|
||||
Thing "{{name}}" is in this list!
|
||||
{{else}}
|
||||
@@ -220,7 +223,7 @@ This will be a reference of tgui components and the tgui-next equivalent.
|
||||
|
||||
Equivalent of `<ui-display>` is `<Section>`
|
||||
|
||||
```
|
||||
```ractive
|
||||
<ui-display title="Status">
|
||||
Contents
|
||||
</ui-display>
|
||||
@@ -236,7 +239,7 @@ becomes
|
||||
|
||||
A feature sometimes used is if `ui-display` has the `button` property, it will contain a `partial` command. This becomes the `buttons` property on `Section`:
|
||||
|
||||
```
|
||||
```ractive
|
||||
<ui-display title="Status" button>
|
||||
{{#partial button}}
|
||||
<ui-button /> // lots more button bullshit here
|
||||
@@ -263,7 +266,7 @@ Very important to note `ui-section` is NOT the equivalent of `Section`
|
||||
|
||||
`<ui-section>` does not have a direct equivalent, but the closest equivalent is `<LabeledList>`
|
||||
|
||||
```
|
||||
```ractive
|
||||
<ui-section label="power">
|
||||
No Power
|
||||
</ui-section>
|
||||
@@ -293,7 +296,7 @@ Also good to know that if you need the contents of a `LabeledList.Item` to be co
|
||||
|
||||
`<ui-notice>` has a direct equivalent in `<NoticeBox>`
|
||||
|
||||
```
|
||||
```ractive
|
||||
<ui-notice>
|
||||
Notice stuff!
|
||||
</ui-notice>
|
||||
@@ -311,7 +314,7 @@ becomes
|
||||
|
||||
The equivalent of `ui-button` is `Button` but it works quite a bit differently.
|
||||
|
||||
```
|
||||
```ractive
|
||||
<ui-button
|
||||
state='{{data.condition ? "disabled" : null}}'
|
||||
action="ui_action"
|
||||
|
||||
91
tgui/docs/migration-to-v4-from-v3.md
Normal file
91
tgui/docs/migration-to-v4-from-v3.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# tgui Migration Guide to v4 from v3
|
||||
|
||||
## The Easy Part
|
||||
|
||||
- Copy and replace the following files in bulk:
|
||||
- `code/__DEFINES/tgui.dm`
|
||||
- `code/controllers/subsystem/tgui.dm`
|
||||
- `code/modules/tgui/**`
|
||||
- `tgui/**`
|
||||
- Except: `tgui/packages/tgui/interfaces`
|
||||
- Manually resolve conflicts for files that were touched outside the
|
||||
`interfaces` folder.
|
||||
- Copy the updated `log_tgui` proc from:
|
||||
- `code/__HELPERS/_logging.dm`
|
||||
|
||||
If you have a dual nano/tgui setup, then make sure to rename all ui procs
|
||||
on `/datum`, such as `ui_interact` to `tgui_interact`, to avoid namespace
|
||||
clashing. Usual stuff.
|
||||
|
||||
## Update `ui_interact` proc signatures
|
||||
|
||||
First of all, tgui states need to move from `ui_interact` to `ui_state`.
|
||||
|
||||
One way of doing it, is to just cherry pick those procs from upstream.
|
||||
|
||||
If you want to search and replace manually, search for `state = GLOB`, and
|
||||
extract those things into `ui_state` procs like so:
|
||||
|
||||
```dm
|
||||
.../ui_state(mob/user)
|
||||
return GLOB.default_state
|
||||
```
|
||||
|
||||
Then reduce `ui_interact` until you finish with something like this:
|
||||
|
||||
```dm
|
||||
.../ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "FooBar", "Foo Bar UI", 600, 400)
|
||||
ui.open()
|
||||
```
|
||||
|
||||
## Update asset delivery code
|
||||
|
||||
Remove all asset code that injects stylesheets by modifying tgui's `basehtml`.
|
||||
You no longer need to do that.
|
||||
|
||||
Find all occurences of `asset.send(user)` in `ui_interact`, and refactor those
|
||||
snippets to the following proc:
|
||||
|
||||
```dm
|
||||
.../ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/simple/foobar),
|
||||
)
|
||||
```
|
||||
|
||||
## Check `ui_act` for new bugs
|
||||
|
||||
Code behind `ui_act` was recently refactored to use JSON-encoded payloads
|
||||
instead of just strings. Since it can now carry numbers and other complex
|
||||
types, you should check that the code is type agnostic and does not break
|
||||
due to an assumption that every parameter is a string.
|
||||
|
||||
One of such offenders is the personal crafting interface, where it needlessly
|
||||
compares parameters to `""` and `"0"`. You can now replace this code with
|
||||
simple assignments, because an empty category will now be properly `null`
|
||||
instead of an empty string.
|
||||
|
||||
## Backend data changes
|
||||
|
||||
Interfaces that relied on `config.window.id`, must now use
|
||||
`window.__windowId__`, which is a global constant unique for the page
|
||||
the script is running on (so you can be sure it never changes).
|
||||
|
||||
In case of `ByondUi`, this parameter can be completely omitted, because
|
||||
parent will always default to the current window id.
|
||||
|
||||
Affected interfaces:
|
||||
|
||||
- `CameraConsole`
|
||||
- Any interface that uses the `ByondUi` component
|
||||
|
||||
---
|
||||
|
||||
That's all folks!
|
||||
|
||||
There is a lot of stuff that was refactored under the hood, but normal UI
|
||||
stuff wouldn't and shouldn't touch it, so you should be good with just
|
||||
going through the checklist above.
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
Basic tgui backend code consists of the following vars and procs:
|
||||
|
||||
```
|
||||
ui_interact(mob/user, ui_key, datum/tgui/ui, force_open,
|
||||
datum/tgui/master_ui, datum/ui_state/state)
|
||||
```dm
|
||||
ui_interact(mob/user, datum/tgui/ui)
|
||||
ui_data(mob/user)
|
||||
ui_act(action, params)
|
||||
ui_state()
|
||||
```
|
||||
|
||||
- `src_object` - The atom, which UI corresponds to in the game world.
|
||||
@@ -19,9 +19,9 @@ or set up a new instance of UI by calling the `SStgui` subsystem.
|
||||
has into an associative list, which will then be sent to UI as a JSON string.
|
||||
- `ui_act` - This proc receives user actions and reacts to them by changing
|
||||
the state of the game.
|
||||
- `ui_state` (set in `ui_interact`) - This var dictates under what conditions
|
||||
a UI may be interacted with. This may be the standard checks that check if
|
||||
you are in range and conscious, or more.
|
||||
- `ui_state` - This proc dictates under what conditions a UI may be interacted
|
||||
with. This may be the standard checks that check if you are in range and
|
||||
conscious, or more.
|
||||
|
||||
Once backend is complete, you create an new interface component on the
|
||||
frontend, which will receive this JSON data and render it on screen.
|
||||
@@ -37,10 +37,10 @@ powerful interactions for embedded objects or remote access.
|
||||
Let's start with a very basic hello world.
|
||||
|
||||
```dm
|
||||
/obj/machinery/my_machine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/my_machine/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "my_machine", name, 300, 300, master_ui, state)
|
||||
ui = new(user, src, "MyMachine")
|
||||
ui.open()
|
||||
```
|
||||
|
||||
@@ -48,9 +48,7 @@ This is the proc that defines our interface. There's a bit going on here, so
|
||||
let's break it down. First, we override the ui_interact proc on our object. This
|
||||
will be called by `interact` for you, which is in turn called by `attack_hand`
|
||||
(or `attack_self` for items). `ui_interact` is also called to update a UI (hence
|
||||
the `try_update_ui`), so we accept an existing UI to update. The `state` is a
|
||||
default argument so that a caller can overload it with named arguments
|
||||
(`ui_interact(state = overloaded_state)`) if needed.
|
||||
the `try_update_ui`), so we accept an existing UI to update.
|
||||
|
||||
Inside the `if(!ui)` block (which means we are creating a new UI), we choose our
|
||||
template, title, and size; we can also set various options like `style` (for
|
||||
@@ -294,10 +292,10 @@ here's what you need (note that you'll probably be forced to clean your shit up
|
||||
upon code review):
|
||||
|
||||
```dm
|
||||
/obj/copypasta/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = default_state) // Remember to use the appropriate state.
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/copypasta/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "copypasta", name, 300, 300, master_ui, state)
|
||||
ui = new(user, src, "copypasta")
|
||||
ui.open()
|
||||
|
||||
/obj/copypasta/ui_data(mob/user)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-eslint": "^10.0.3",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint": "^7.4.0",
|
||||
"eslint-plugin-react": "^7.17.0"
|
||||
}
|
||||
}
|
||||
|
||||
2330
tgui/yarn.lock
2330
tgui/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user