layout.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. import { createStore } from "solid-js/store"
  2. import { createMemo } from "solid-js"
  3. import { createSimpleContext } from "@opencode-ai/ui/context"
  4. import { makePersisted } from "@solid-primitives/storage"
  5. import { useGlobalSync } from "./global-sync"
  6. export const { use: useLayout, provider: LayoutProvider } = createSimpleContext({
  7. name: "Layout",
  8. init: () => {
  9. const globalSync = useGlobalSync()
  10. const [store, setStore] = makePersisted(
  11. createStore({
  12. projects: [] as { directory: string; expanded: boolean }[],
  13. sidebar: {
  14. opened: true,
  15. width: 280,
  16. },
  17. review: {
  18. state: "pane" as "pane" | "tab",
  19. },
  20. }),
  21. {
  22. name: "___default-layout",
  23. },
  24. )
  25. return {
  26. projects: {
  27. list: createMemo(() =>
  28. globalSync.data.defaultProject
  29. ? [{ directory: globalSync.data.defaultProject!.worktree, expanded: true }, ...store.projects]
  30. : store.projects,
  31. ),
  32. open(directory: string) {
  33. if (store.projects.find((x) => x.directory === directory)) return
  34. setStore("projects", (x) => [...x, { directory, expanded: true }])
  35. },
  36. close(directory: string) {
  37. setStore("projects", (x) => x.filter((x) => x.directory !== directory))
  38. },
  39. expand(directory: string) {
  40. setStore("projects", (x) => x.map((x) => (x.directory === directory ? { ...x, expanded: true } : x)))
  41. },
  42. collapse(directory: string) {
  43. setStore("projects", (x) => x.map((x) => (x.directory === directory ? { ...x, expanded: false } : x)))
  44. },
  45. },
  46. sidebar: {
  47. opened: createMemo(() => store.sidebar.opened),
  48. open() {
  49. setStore("sidebar", "opened", true)
  50. },
  51. close() {
  52. setStore("sidebar", "opened", false)
  53. },
  54. toggle() {
  55. setStore("sidebar", "opened", (x) => !x)
  56. },
  57. width: createMemo(() => store.sidebar.width),
  58. resize(width: number) {
  59. setStore("sidebar", "width", width)
  60. },
  61. },
  62. review: {
  63. state: createMemo(() => store.review?.state ?? "closed"),
  64. pane() {
  65. setStore("review", "state", "pane")
  66. },
  67. tab() {
  68. setStore("review", "state", "tab")
  69. },
  70. },
  71. }
  72. },
  73. })