Shannon Sterz [Tue, 3 Dec 2024 11:04:50 +0000 (12:04 +0100)]
language: make LANGUAGE thread local
in rust edition 2024 [1] it is no longer allowed to use references to
`static mut` variables. the recommended way of dealing with this is to
use inner mutability. this usually requires the wrapped trait to
implement `Sync` to be thread safe. however, `SharedState` uses `Rc`s
for its implementation, which do not implement `Sync` and so
`SharedState` cannot be `Sync`.
using `Rc`s in WASM is usually fine as WASM code generally isn't
multi-threaded. there are some ways to exploit parallelism, but they are
fairly limited (e.g. web workers). so following this logic, make
`LANGUAGE` thread local. this will allow us to use edition 2024 without
too many changes.
Shannon Sterz [Tue, 3 Dec 2024 11:04:49 +0000 (12:04 +0100)]
gettext_wrapper: use inner mutability for CATALOG
in the rust edition 2024 [1] `static mut` are not allowed to be
referenced anymore, as doing so has always been undefined behaviour. the
recommended way to work around this is to use inner mutability. so use a
`RWLock` here.
Shannon Sterz [Tue, 3 Dec 2024 11:04:48 +0000 (12:04 +0100)]
language: use inner mutability for AVAILABLE_LANUGAGES
in rust edition 2024 taking references to `static mut` variables will be
disallowed [1]. the recommended way to adapting to this is using inner
mutability. so use a OnceLock here to ensure that the set of available
languages can only be set once.
in the `load` method, we just setup the loading itself, but the write
guard does that on every `Drop`. To prevent that and only trigger
the `on_change` callback when the data really changed, combine the
calls to `write()` here so we only have one guard and disable the
notification on it.
Dominik Csapak [Mon, 18 Nov 2024 12:02:34 +0000 (13:02 +0100)]
widget: dropdown: make popover behavior manual
otherwise the popover is dismissed by e.g. clicking in the field
when it's editable, which produces an undesired effect.
(It's then "closed" but still visible because of our css classes, and
now our aligning logic is wrong because popovers behave differently when
open vs closed)
Dominik Csapak [Thu, 14 Nov 2024 14:36:48 +0000 (15:36 +0100)]
widget: dropdown: properly focus the selected element
we currently always have a datatable as a picker, so the selected
element must be the cell, as the row (which gets the 'selected' class)
is not selectable (it has no tabindex)
Dominik Csapak [Thu, 14 Nov 2024 14:36:47 +0000 (15:36 +0100)]
widget: dropdown: use popover instead of a dialog
by using popovers, we don't have get the messy focus behaviour of
dialogs, for example those focus the first element when the dialog is
opened, which often is the header menu of a datatable.
This also makes the code a bit shorter, since we can restore the focus
before the popover is fully closed (and simply hide it as soon as
possible).
for now we have to use our own bindings to show/hide/togglePopover, but
this can be removed with a later web-sys version.
Shannon Sterz [Wed, 23 Oct 2024 12:52:56 +0000 (14:52 +0200)]
widget: remove useless `try_from` call in theme density selector
the enum member `SetThemeDensity` already only takes values of type
`ThemeDensity`. so the `try_from` here converts from `ThemeDensity`
to `ThemeDensity` which is pointless and trivially must always
succeed. remove it so that the compiler stops complaining about
irrefutable patterns.
Shannon Sterz [Tue, 8 Oct 2024 09:02:19 +0000 (11:02 +0200)]
widget: form: make selector load only when enabled
loading when a selector is disabled doesn't serve any purpose as users
can't select the loaded entries anyway. so only load when the
selector is enabled. also makes sure that the selector loads if it
was previously disabled and is now enabled.
Dominik Csapak [Tue, 8 Oct 2024 10:31:33 +0000 (12:31 +0200)]
widget: data table: react to column changes
the headers are part of the properties, so if they change, we should
react to that. Until now, we only accepted them at the first 'create'
call, which meant that when the columns changed afterwards (e.g. when we
want to pass different data to the renderer) it did not get rerendered
with the new information.
To do this, refactor the header processing code from 'create' into it's
own function, and call it also when the headers changed in the 'changed'
method.
Dominik Csapak [Mon, 7 Oct 2024 10:25:53 +0000 (12:25 +0200)]
widget: input panel: fix key generation for labels
yews key mechanism does not work on markup level, but on component
level. So the attempt to auto-generate keys for FieldLabels in the view
method instead of the input panel was misguided, since that does not
actually give the label itself a key.
This was noticed on all input panels where we dynamically added/removed
fields, since then the whole form was reset because of the missing keys.
(E.g. the ACME DNS plugin panel)
Instead generate the label key like before in the input panel itself,
but only when the FieldLabel itself does not already have one set.
(so users can manually override that if they want)
Fixes: bd58deb (widget: input panel: use FieldLabel instead of just text) Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
Dominik Csapak [Thu, 3 Oct 2024 13:24:50 +0000 (15:24 +0200)]
widget: input panel: adapt to recent grid column change
we changed the layout to a 5 column grid (one spacer in the middle),
but forgot to add the middle column when we set the label_width or
field_width manually.
and remove old `Checkbox` implementation. Since we now have a separate
RadioButton component and the Boolean one has more features that should
cover all use cases of the old Checkbox field, simply rename the Boolean
to Checkbox.
Also having only one Checkbox component instead of two separate ones is
less confusing and less error prone.
This makes it necessary to adapt all code paths using either Checkbox or
Boolean, but these changes should be rather trivial:
* either changing the submit_on/off_values where we used a checkbox
previously
* or rename Boolean to Checkbox
If we missed some use case for the Checkbox, we can either simply add it
again, or use a more generic Field with input_type 'checkbox' instead.
instead of reusing the Checkbox component for creating radio buttons,
have a separate component for that. This makes it easier to specialize
the code for that use case.
The code is mostly a mix of Checkbox and Boolean (for some of the newer
features), with the irrelevant portions stripped out.
sometimes it's useful to map the checked/unchecked state to different
submit values than true/false, e.g. for inverted checkboxes or if the
api does not accept true/false but e.g. 1/0 instead.
widget: move FieldLabel functionality into Boolean
We only ever need labels on the right side (called box label now), only
on checkboxes, so it does not really make sense to have a separate
widget for that.
For now we only accept text as the label, but we could change that
later if we need that.
This makes the 'FieldLabel' available and ready to use elsewhere, e.g.
the input panel.
For convenience, we implement some From traits for it, so one can use a
bare string to create such a field label.
widget: checkbox: make clickable area react to clicks
the outer container contains the visual cues for clicking the checkbox,
but only the inner actual checkbox reacted to clicks. Move the onclick
handler to the outer container so the click behavior matches the
visuals.
this can be useful if the theme or project defines it's own color
schemes, but still want to refer to them in the code without having to
use bare css classes