diff --git a/.changeset/admin-buttons.md b/.changeset/admin-buttons.md new file mode 100644 index 00000000..fd3cb98f --- /dev/null +++ b/.changeset/admin-buttons.md @@ -0,0 +1,5 @@ +--- +"@empirica/core": patch +--- + +Make admin buttons look right again. diff --git a/.changeset/menu-positions.md b/.changeset/menu-positions.md new file mode 100644 index 00000000..f85df58c --- /dev/null +++ b/.changeset/menu-positions.md @@ -0,0 +1,6 @@ +--- +"@empirica/core": patch +--- + +`EmpiricaMenu` component improvements. Add `top` and `bottom` positions. Improve +styling and readability. Use Lucide icons. diff --git a/.changeset/reliable-subprocs.md b/.changeset/reliable-subprocs.md new file mode 100644 index 00000000..c1f5d257 --- /dev/null +++ b/.changeset/reliable-subprocs.md @@ -0,0 +1,5 @@ +--- +"@empirica/core": patch +--- + +Make subprocs terminate more reliably. diff --git a/cmds/empirica/cmd/export.go b/cmds/empirica/cmd/export.go index b44481b2..e5375ad6 100644 --- a/cmds/empirica/cmd/export.go +++ b/cmds/empirica/cmd/export.go @@ -7,6 +7,7 @@ import ( "os/exec" "path" "strings" + "syscall" "time" "github.com/empiricaly/empirica/internal/build" @@ -145,6 +146,9 @@ func addExportCommand(parent *cobra.Command) error { Msg("exporting data") c := exec.CommandContext(ctx, "empirica", exportArgs...) + c.SysProcAttr = &syscall.SysProcAttr{ + Pdeathsig: syscall.SIGKILL, + } c.Stderr = os.Stderr c.Stdout = os.Stdout diff --git a/cmds/proxy/cmd/root.go b/cmds/proxy/cmd/root.go index 893e9ef8..b61fb29c 100644 --- a/cmds/proxy/cmd/root.go +++ b/cmds/proxy/cmd/root.go @@ -60,6 +60,9 @@ func root(args []string) error { Msg("proxy: chosen binary path") c := exec.CommandContext(ctx, path, args...) + c.SysProcAttr = &syscall.SysProcAttr{ + Pdeathsig: syscall.SIGKILL, + } c.Stderr = os.Stderr c.Stdout = os.Stdout diff --git a/internal/bundle/serve.go b/internal/bundle/serve.go index ac53de61..3f40ac91 100644 --- a/internal/bundle/serve.go +++ b/internal/bundle/serve.go @@ -8,6 +8,7 @@ import ( "path" "path/filepath" "strings" + "syscall" "github.com/empiricaly/empirica" "github.com/empiricaly/empirica/internal/server" @@ -76,6 +77,9 @@ func Serve(ctx context.Context, config *empirica.Config, in string, clean, devMo Msg("serve: start server command") c := exec.CommandContext(ctx, cmd, args...) + c.SysProcAttr = &syscall.SysProcAttr{ + Pdeathsig: syscall.SIGKILL, + } p := path.Join(dir, "callbacks") diff --git a/internal/callbacks/callbacks.go b/internal/callbacks/callbacks.go index efa9a4d7..32ee4026 100644 --- a/internal/callbacks/callbacks.go +++ b/internal/callbacks/callbacks.go @@ -50,6 +50,10 @@ func Build(ctx context.Context, config *Config) error { } c := exec.CommandContext(ctx, parts[0], args...) + c.SysProcAttr = &syscall.SysProcAttr{ + Setpgid: true, + Pdeathsig: syscall.SIGKILL, + } c.Stderr = os.Stderr c.Stdout = os.Stdout @@ -116,6 +120,14 @@ const ( ) func (cb *Callbacks) sigint() { + if cb.c == nil { + log.Debug().Msg("callback: no process to send signal to") + + return + } + + log.Debug().Msg("callback: cancelling process") + pgid, err := syscall.Getpgid(cb.c.Process.Pid) if err != nil { log.Debug().Err(err).Msg("callback: failed to send signal") @@ -127,9 +139,9 @@ func (cb *Callbacks) sigint() { log.Debug().Err(err).Msg("callback: failed to send signal") } - // if err := cb.c.Process.Signal(os.Interrupt); err != nil { - // log.Debug().Err(err).Msg("callback: failed to send signal") - // } + if err := cb.c.Process.Signal(os.Interrupt); err != nil { + log.Debug().Err(err).Msg("callback: failed to send signal") + } cb.c = nil } @@ -271,7 +283,9 @@ func (cb *Callbacks) run(ctx context.Context) { select { case <-ctx.Done(): + cb.Lock() cb.sigint() + cb.Unlock() return case err = <-waiting: @@ -282,7 +296,9 @@ func (cb *Callbacks) run(ctx context.Context) { var exitError *exec.ExitError if errors.As(err, &exitError) { + cb.Lock() cb.c = nil + cb.Unlock() if hardExits, shouldExit = checkHardExit(lastHardExit, hardExits, err); shouldExit { return @@ -354,7 +370,10 @@ func (cb *Callbacks) runOnce(ctx context.Context) (*exec.Cmd, error) { } c := exec.CommandContext(ctx, parts[0], remainder...) // #nosec G204 - c.SysProcAttr = &syscall.SysProcAttr{Setpgid: true, Pgid: 0} + c.SysProcAttr = &syscall.SysProcAttr{ + Setpgid: true, + Pdeathsig: syscall.SIGKILL, + } c.Stderr = cb.stderr c.Stdout = cb.stdout diff --git a/internal/experiment/utils.go b/internal/experiment/utils.go index fc3507e4..41d19c0f 100644 --- a/internal/experiment/utils.go +++ b/internal/experiment/utils.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "strings" + "syscall" "time" "github.com/briandowns/spinner" @@ -35,6 +36,9 @@ func RunCmdSilent(ctx context.Context, dir, command string, args ...string) erro func runCmdSilence(ctx context.Context, dir string, silent bool, command string, args ...string) error { c := exec.CommandContext(ctx, command, args...) + c.SysProcAttr = &syscall.SysProcAttr{ + Pdeathsig: syscall.SIGKILL, + } if !silent { c.Stderr = os.Stderr diff --git a/internal/player/player.go b/internal/player/player.go index 04600d10..9a5c1b3c 100644 --- a/internal/player/player.go +++ b/internal/player/player.go @@ -8,6 +8,7 @@ import ( "os/exec" "path" "strings" + "syscall" "time" "github.com/empiricaly/empirica/internal/term" @@ -37,6 +38,9 @@ func Build(ctx context.Context, config *Config) error { } c := exec.CommandContext(ctx, parts[0], args...) + c.SysProcAttr = &syscall.SysProcAttr{ + Pdeathsig: syscall.SIGKILL, + } c.Stderr = os.Stderr c.Stdout = os.Stdout @@ -164,6 +168,9 @@ func (p *Player) runDevCmd(ctx context.Context) (*exec.Cmd, error) { log.Trace().Str("cmd", strings.Join(parts, " ")).Msg("player: run player dev command") c := exec.CommandContext(ctx, parts[0], args...) + c.SysProcAttr = &syscall.SysProcAttr{ + Pdeathsig: syscall.SIGKILL, + } c.Stderr = os.Stderr c.Stdout = p.stdout diff --git a/internal/settings/shared.go b/internal/settings/shared.go index 23be9484..82182631 100644 --- a/internal/settings/shared.go +++ b/internal/settings/shared.go @@ -6,6 +6,7 @@ import ( "os/exec" "path" "strings" + "syscall" "github.com/adrg/xdg" "github.com/pkg/errors" @@ -84,6 +85,9 @@ func InstallVolta(ctx context.Context) error { func runCmd(ctx context.Context, dir, command string, args ...string) error { c := exec.CommandContext(ctx, command, args...) + c.SysProcAttr = &syscall.SysProcAttr{ + Pdeathsig: syscall.SIGKILL, + } c.Stderr = os.Stderr c.Stdout = os.Stdout diff --git a/lib/@empirica/core/src/player/react/EmpiricaMenu.tsx b/lib/@empirica/core/src/player/react/EmpiricaMenu.tsx index de8faa6b..4d6aacfe 100644 --- a/lib/@empirica/core/src/player/react/EmpiricaMenu.tsx +++ b/lib/@empirica/core/src/player/react/EmpiricaMenu.tsx @@ -4,7 +4,13 @@ import { Logo } from "./Logo"; import { useParticipantContext } from "./hooks"; export type EmpiricaMenuProps = { - position: "top-left" | "top-right" | "bottom-left" | "bottom-right"; + position: + | "top" + | "top-left" + | "top-right" + | "bottom" + | "bottom-left" + | "bottom-right"; }; export function EmpiricaMenu({ position = "bottom-left" }: EmpiricaMenuProps) { @@ -20,14 +26,20 @@ export function EmpiricaMenu({ position = "bottom-left" }: EmpiricaMenuProps) { } let className = - "backdrop-blur-md bg-gray-200 rounded fixed z-20 flex space-x-1 text-gray-500"; + "backdrop-blur-md bg-gray-200/50 rounded fixed z-20 flex space-x-1 text-gray-500"; switch (position) { + case "top": + className += " top-0 mt-2 ml-1/2 -translate-x-1/2"; + break; case "top-left": className += " top-0 left-0 mt-2 ml-2"; break; case "top-right": className += " top-0 right-0 mt-2 mr-2"; break; + case "bottom": + className += " bottom-0 mb-2 ml-1/2 -translate-x-1/2"; + break; case "bottom-right": className += " bottom-0 right-0 mb-2 mr-2"; break; @@ -50,10 +62,17 @@ export function EmpiricaMenu({ position = "bottom-left" }: EmpiricaMenuProps) { icon: ( - + + + + ), inDevOnly: true, @@ -64,10 +83,15 @@ export function EmpiricaMenu({ position = "bottom-left" }: EmpiricaMenuProps) { icon: ( - + + ), inDevOnly: true, @@ -80,10 +104,14 @@ export function EmpiricaMenu({ position = "bottom-left" }: EmpiricaMenuProps) { icon: ( - + ), inDevOnly: true, @@ -96,10 +124,15 @@ export function EmpiricaMenu({ position = "bottom-left" }: EmpiricaMenuProps) { icon: ( - + + ), inDevOnly: true, diff --git a/lib/admin-ui/src/style.css b/lib/admin-ui/src/style.css index 21445023..bb139e5c 100644 --- a/lib/admin-ui/src/style.css +++ b/lib/admin-ui/src/style.css @@ -1,3 +1,10 @@ +@layer base { + button { + -webkit-appearance: none !important; + background-color: transparent; + } +} + @layer utilities { /* Chrome, Safari, Edge, Opera */ input.number-arrows-none::-webkit-outer-spin-button, diff --git a/lib/admin-ui/uno.config.ts b/lib/admin-ui/uno.config.ts index 97aed5a3..568b0734 100644 --- a/lib/admin-ui/uno.config.ts +++ b/lib/admin-ui/uno.config.ts @@ -1,3 +1,4 @@ +import { presetForms } from "@julr/unocss-preset-forms"; import { defineConfig, presetAttributify, @@ -8,9 +9,18 @@ import { transformerDirectives, transformerVariantGroup, } from "unocss"; -import { presetForms } from "@julr/unocss-preset-forms"; export default defineConfig({ + safelist: [ + ...["blue", "green", "yellow", "grey"] + .map((color) => [ + `border-${color}-600`, + `text-${color}-600`, + `bg-${color}-600`, + `hover:bg-${color}-700`, + ]) + .flat(), + ], theme: { colors: { empirica: { @@ -30,14 +40,14 @@ export default defineConfig({ presets: [ presetUno(), presetForms(), - presetAttributify(), - presetIcons(), + // presetAttributify(), + // presetIcons(), presetTypography(), - presetWebFonts({ - fonts: { - // ... - }, - }), + // presetWebFonts({ + // fonts: { + // // ... + // }, + // }), ], transformers: [transformerDirectives(), transformerVariantGroup()], });