diff --git a/applications/uk.tcsw.dashboard/backend/index.ts b/applications/uk.tcsw.dashboard/backend/index.ts index 4d8e0e9..5daf5f7 100644 --- a/applications/uk.tcsw.dashboard/backend/index.ts +++ b/applications/uk.tcsw.dashboard/backend/index.ts @@ -136,6 +136,13 @@ const router = t.router({ "show_edit_button", ); }), + showSearchBar: procedure.output(z.boolean()).query(async (opt) => { + return await opt.ctx.instance.sys.settings.getUserApplicationSetting( + opt.ctx.userId, + "uk.tcsw.dashboard", + "show_search_bar", + ); + }), getWallpaperOptions: procedure .output( z.object({ @@ -254,4 +261,11 @@ instance.sys.event.on(WorkspacesEvent.BeforeStartupComplete, () => { "Should the edit button be displayed on the dashboard to allow quick navigation to this settings page.", ), ); + instance.sys.settings.registerApplicationSetting( + new BooleanApplicationSetting("uk.tcsw.dashboard", "show_search_bar", false) + .setDisplayName("Show Search Bar on Dashboard") + .setDescription( + "Should a search bar be displayed on the dashboard to allow for quick web searches.", + ), + ); }); diff --git a/applications/uk.tcsw.dashboard/web/pages/root/index.module.scss b/applications/uk.tcsw.dashboard/web/pages/root/index.module.scss index d0b97e0..564a9a9 100644 --- a/applications/uk.tcsw.dashboard/web/pages/root/index.module.scss +++ b/applications/uk.tcsw.dashboard/web/pages/root/index.module.scss @@ -1,116 +1,146 @@ .root { - position: relative; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - gap: 2rem; - padding: 1rem; - width: 100%; - height: 100%; - //background-position: center; - background-repeat: no-repeat; - background-size: cover; - background-position: center; - - animation: fadeIn forwards 0.25s var(--uk-sys-motion-easing-standard-decelerate); - - @keyframes fadeIn { - from { - opacity: 0; - filter: blur(0.25rem); - } - to { - opacity: 1; - filter: blur(0); - } + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 1rem; + padding: 1rem; + width: 100%; + height: 100%; + //background-position: center; + background-repeat: no-repeat; + background-size: cover; + background-position: center; + + animation: fadeIn forwards 0.25s + var(--uk-sys-motion-easing-standard-decelerate); + + @keyframes fadeIn { + from { + opacity: 0; + filter: blur(0.25rem); } + to { + opacity: 1; + filter: blur(0); + } + } } .wallpaper { - position: absolute; - width: 100%; - height: 100%; - user-select: none; - pointer-events: none; - z-index: -1; - animation: fadeIn forwards 0.25s var(--uk-sys-motion-easing-standard-decelerate); - - @keyframes fadeIn { - from { - opacity: 0; - filter: blur(0.25rem); - } - to { - opacity: 1; - filter: blur(0); - } + position: absolute; + width: 100%; + height: 100%; + user-select: none; + pointer-events: none; + z-index: -1; + animation: fadeIn forwards 0.25s + var(--uk-sys-motion-easing-standard-decelerate); + + @keyframes fadeIn { + from { + opacity: 0; + filter: blur(0.25rem); + } + to { + opacity: 1; + filter: blur(0); } + } - --transform-x: 0; - --transform-y: 0; + --transform-x: 0; + --transform-y: 0; - .left { - left: 0.25rem; - } + .left { + left: 0.25rem; + } - .center { - left: 50%; - --transform-x: -50%; - } + .center { + left: 50%; + --transform-x: -50%; + } - .right { - right: 0.25rem; - } + .right { + right: 0.25rem; + } - .top { - top: 0.25rem; - } + .top { + top: 0.25rem; + } - .middle { - top: 50%; - --transform-y: -50%; - } + .middle { + top: 50%; + --transform-y: -50%; + } - .bottom { - bottom: 0.25rem; - } + .bottom { + bottom: 0.25rem; + } - transform: translateX(var(--transform-x, 0)) translateY(var(--transform-y, 0)); + transform: translateX(var(--transform-x, 0)) translateY(var(--transform-y, 0)); } .wallpaperSpinner { - position: absolute; - top: 50%; - left: calc(50% + 24px); - transform: translate(-50%, -50%); - z-index: -1; + position: absolute; + top: 50%; + left: calc(50% + 24px); + transform: translate(-50%, -50%); + z-index: -1; } .welcomeMessage { - padding: 1.5rem; + padding: 1.5rem; } .widgets { - width: max-content; - max-width: calc(100% - 2rem); - display: grid; - grid-template-columns: repeat(auto-fit, minmax(16rem, 23rem)); - grid-auto-rows: 7rem; - padding: 1rem; - gap: 1rem; + width: max-content; + max-width: calc(100% - 2rem); + display: grid; + grid-template-columns: repeat(auto-fit, minmax(16rem, 23rem)); + grid-auto-rows: 7rem; + padding: 1rem; + gap: 1rem; } .root[data-show-background="true"] { - .welcomeMessage { - border-radius: var(--uk-sys-shape-corner-medium); - background: #0004; - backdrop-filter: blur(2rem); - } + .welcomeMessage { + border-radius: var(--uk-sys-shape-corner-medium); + background: #0004; + backdrop-filter: blur(2rem); + } + + .widgets { + border-radius: calc(var(--uk-sys-shape-corner-medium) + 1rem); + backdrop-filter: blur(2rem); + background: #0004; + } +} - .widgets { - border-radius: calc(var(--uk-sys-shape-corner-medium) + 1rem); - backdrop-filter: blur(2rem); - background: #0004; - } +.searchBar { + width: 100%; + max-width: 32rem; + display: flex; + border-radius: calc(var(--uk-sys-shape-corner-medium) + 0.5rem); + backdrop-filter: blur(2rem); + background: #0004; + padding: 0.5rem; + gap: 0.5rem; +} + +.searchBarInput { + flex: 1; + padding: 1rem 1rem; + + border: none; + outline: none; + background-color: rgb(var(--uk-sys-color-surface-container-highest)); + color: rgb(var(--uk-sys-color-on-surface)); + box-shadow: 0 0 1px rgb(var(--uk-sys-color-shadow)); + border-radius: var(--uk-sys-shape-corner-medium); +} + +.searchBarSearch { + height: 100% !important; + aspect-ratio: 1; } diff --git a/applications/uk.tcsw.dashboard/web/pages/root/index.tsx b/applications/uk.tcsw.dashboard/web/pages/root/index.tsx index cab81e6..9873452 100644 --- a/applications/uk.tcsw.dashboard/web/pages/root/index.tsx +++ b/applications/uk.tcsw.dashboard/web/pages/root/index.tsx @@ -1,14 +1,16 @@ -import { createResource, For, Suspense, type Component } from "solid-js"; -import Widgets from "../../widgets/widgets"; -import styles from "./index.module.scss"; -import UKText from "@tcsw/uikit-solid/src/components/text/UKText.jsx"; -import trpc from "../../lib/trpc"; +import EDIT_ICON from "@material-symbols/svg-700/outlined/edit.svg"; +import SEARCH_ICON from "@material-symbols/svg-700/outlined/search.svg"; +import { useNavigate } from "@solidjs/router"; +import UKButton from "@tcsw/uikit-solid/src/components/button/UKButton.jsx"; +import UKIconButton from "@tcsw/uikit-solid/src/components/iconButton/UKIconButton.jsx"; import UKIndeterminateSpinner from "@tcsw/uikit-solid/src/components/indeterminateSpinner/UKIndeterminateSpinner.jsx"; +import UKText from "@tcsw/uikit-solid/src/components/text/UKText.jsx"; import clsx from "clsx"; +import { type Component, createResource, createSignal, For, Suspense } from "solid-js"; import PLACEHOLDER_WALLPAPER from "./../../assets/placeholder_wallpaper.png"; -import UKButton from "@tcsw/uikit-solid/src/components/button/UKButton.jsx"; -import { useNavigate } from "@solidjs/router"; -import EDIT_ICON from "@material-symbols/svg-700/outlined/edit.svg" +import trpc from "../../lib/trpc"; +import Widgets from "../../widgets/widgets"; +import styles from "./index.module.scss"; const RootPage: Component = () => { const navigate = useNavigate(); @@ -19,24 +21,16 @@ const RootPage: Component = () => { }), ); const [widgets] = createResource(() => trpc.dashboard.getWidgets.query()); - const [wallpaperOptions] = createResource(() => - trpc.dashboard.getWallpaperOptions.query(), - ); - const [welcomeMessage] = createResource(() => - trpc.dashboard.welcomeMessage.query(Date.now()), - ); - const [contentBackground] = createResource(() => - trpc.dashboard.contentBackground.query(), - ); - const [showEditButton] = createResource(() => - trpc.dashboard.showEditButton.query(), - ); + const [wallpaperOptions] = createResource(() => trpc.dashboard.getWallpaperOptions.query()); + const [welcomeMessage] = createResource(() => trpc.dashboard.welcomeMessage.query(Date.now())); + const [contentBackground] = createResource(() => trpc.dashboard.contentBackground.query()); + const [showEditButton] = createResource(() => trpc.dashboard.showEditButton.query()); + const [showSearchBar] = createResource(() => trpc.dashboard.showSearchBar.query()); + const [searchQuery, setSearchQuery] = createSignal(""); return (
- } - > + }> {""} { /> {welcomeMessage() && ( - + {welcomeMessage()} )} + {showSearchBar() && ( +
+ { + setSearchQuery(e.currentTarget.value); + if (e.key === "Enter") { + window.location.href = `https://duckduckgo.com/?q=${encodeURIComponent(searchQuery())}`; + } + }} + /> + { + window.location.href = `https://duckduckgo.com/?q=${encodeURIComponent(searchQuery())}`; + }} + alt="search" + /> +
+ )}
{(widgetId) => { diff --git a/applications/uk.tcsw.files/web/components/ViewContainer/ViewContainer.tsx b/applications/uk.tcsw.files/web/components/ViewContainer/ViewContainer.tsx index fd06b25..7c848a7 100644 --- a/applications/uk.tcsw.files/web/components/ViewContainer/ViewContainer.tsx +++ b/applications/uk.tcsw.files/web/components/ViewContainer/ViewContainer.tsx @@ -1,297 +1,296 @@ -import { createEffect, createSignal, Match, Switch, useContext, type Component } from "solid-js"; import { Ref } from "@solid-primitives/refs"; -import GridView from "./Grid/Grid"; -import { ViewContext } from "./ViewContext"; -import ListView from "./List/List"; -import UKMenu from "@tcsw/uikit-solid/src/components/menu/UKMenu.jsx"; import { useParams } from "@solidjs/router"; -import styles from "./ViewContainer.module.scss"; +import UKContextMenu from "@tcsw/uikit-solid/src/components/contextMenu/UKContextMenu.jsx"; +import UKMenu from "@tcsw/uikit-solid/src/components/menu/UKMenu.jsx"; import path from "path-browserify"; +import { type Component, createEffect, createSignal, Match, Switch, useContext } from "solid-js"; import trpc from "../../lib/trpc"; +import GridView from "./Grid/Grid"; +import ListView from "./List/List"; +import styles from "./ViewContainer.module.scss"; +import { ViewContext } from "./ViewContext"; const ViewContainer: Component = () => { - let params = useParams<{ currentPath: string }>(); - const [ref, setRef] = createSignal(); - const viewCtx = useContext(ViewContext); - const [dragRegion, setDragRegion] = createSignal< - | { - initialPosition: { x: number; y: number }; - region: { - start: { - x: number; - y: number; - }; - end: { - x: number; - y: number; - }; - }; - currentPosition: { x: number; y: number }; - } - | undefined - >(undefined); - const [mouseDownAt, setMouseDownAt] = createSignal(0); + const params = useParams<{ currentPath: string }>(); + const [ref, setRef] = createSignal(); + const viewCtx = useContext(ViewContext); + const [dragRegion, setDragRegion] = createSignal< + | { + initialPosition: { x: number; y: number }; + region: { + start: { + x: number; + y: number; + }; + end: { + x: number; + y: number; + }; + }; + currentPosition: { x: number; y: number }; + } + | undefined + >(undefined); + const [mouseDownAt, setMouseDownAt] = createSignal(0); - createEffect(() => { - const region = dragRegion(); - const itemContainer = ref(); + createEffect(() => { + const region = dragRegion(); + const itemContainer = ref(); - if (region === undefined) return; - if (!itemContainer) return; + if (region === undefined) return; + if (!itemContainer) return; - let newSelectedItems = []; - const reg = region.region; + const newSelectedItems = []; + const reg = region.region; - const sel = { - left: Math.min(reg.start.x, reg.end.x), - right: Math.max(reg.start.x, reg.end.x), - top: Math.min(reg.start.y, reg.end.y), - bottom: Math.max(reg.start.y, reg.end.y), - }; + const sel = { + left: Math.min(reg.start.x, reg.end.x), + right: Math.max(reg.start.x, reg.end.x), + top: Math.min(reg.start.y, reg.end.y), + bottom: Math.max(reg.start.y, reg.end.y), + }; - if (sel.left === sel.right || sel.top === sel.bottom) return; + if (sel.left === sel.right || sel.top === sel.bottom) return; - for (const child of itemContainer.children) { - const rect = child.getBoundingClientRect(); + for (const child of itemContainer.children) { + const rect = child.getBoundingClientRect(); - if (sel.right < rect.left || sel.left > rect.right || sel.bottom < rect.top || sel.top > rect.bottom) { - continue; - } + if ( + sel.right < rect.left || + sel.left > rect.right || + sel.bottom < rect.top || + sel.top > rect.bottom + ) { + continue; + } - let path = child.getAttribute("data-path"); - if (path !== null) newSelectedItems.push(path); - } + const path = child.getAttribute("data-path"); + if (path !== null) newSelectedItems.push(path); + } - viewCtx?.setSelectedItems(newSelectedItems); - }); + viewCtx?.setSelectedItems(newSelectedItems); + }); - return ( -
{ - if (e.button === 0) { - setDragRegion({ - currentPosition: { - x: e.clientX, - y: e.clientY, - }, - region: { - start: { - x: e.clientX, - y: e.clientY, - }, - end: { - x: e.clientX, - y: e.clientY, - }, - }, - initialPosition: { - x: e.clientX, - y: e.clientY, - }, - }); - setMouseDownAt(Date.now()); - } - }} - onMouseMove={(e) => { - setDragRegion((dr) => { - if (!dr) return undefined; + return ( +
{ + if (e.button === 0) { + setDragRegion({ + currentPosition: { + x: e.clientX, + y: e.clientY, + }, + region: { + start: { + x: e.clientX, + y: e.clientY, + }, + end: { + x: e.clientX, + y: e.clientY, + }, + }, + initialPosition: { + x: e.clientX, + y: e.clientY, + }, + }); + setMouseDownAt(Date.now()); + } + }} + onMouseMove={(e) => { + setDragRegion((dr) => { + if (!dr) return undefined; - const currentPosition = { - x: e.clientX, - y: e.clientY, - }; + const currentPosition = { + x: e.clientX, + y: e.clientY, + }; - let region = { - start: { - x: 0, - y: 0, - }, - end: { - x: 0, - y: 0, - }, - }; + const region = { + start: { + x: 0, + y: 0, + }, + end: { + x: 0, + y: 0, + }, + }; - if (currentPosition.x < dr.initialPosition.x) { - region.start.x = currentPosition.x; - region.end.x = dr.initialPosition.x; - } - if (dr.initialPosition.x < currentPosition.x) { - region.start.x = dr.initialPosition.x; - region.end.x = currentPosition.x; - } - if (currentPosition.y < dr.initialPosition.y) { - region.start.y = currentPosition.y; - region.end.y = dr.initialPosition.y; - } - if (dr.initialPosition.y < currentPosition.y) { - region.start.y = dr.initialPosition.y; - region.end.y = currentPosition.y; - } + if (currentPosition.x < dr.initialPosition.x) { + region.start.x = currentPosition.x; + region.end.x = dr.initialPosition.x; + } + if (dr.initialPosition.x < currentPosition.x) { + region.start.x = dr.initialPosition.x; + region.end.x = currentPosition.x; + } + if (currentPosition.y < dr.initialPosition.y) { + region.start.y = currentPosition.y; + region.end.y = dr.initialPosition.y; + } + if (dr.initialPosition.y < currentPosition.y) { + region.start.y = dr.initialPosition.y; + region.end.y = currentPosition.y; + } - return { - currentPosition, - initialPosition: dr.initialPosition, - region: region, - }; - }); - }} - onMouseUp={(e) => { - if (e.button === 0) { - setDragRegion(undefined); - } + return { + currentPosition, + initialPosition: dr.initialPosition, + region: region, + }; + }); + }} + onMouseUp={(e) => { + if (e.button === 0) { + setDragRegion(undefined); + } - if (mouseDownAt() + 75 > Date.now()) { - setDragRegion(undefined); - viewCtx!.setSelectedItems([]); - } - }} - onMouseEnter={(e) => { - // if the left mouse button is not pressed - if (!Boolean(e.buttons & (1 << 0))) { - setDragRegion(undefined); - } - }} - > - {!!dragRegion()?.region ? ( -
- ) : null} - 0 || viewCtx!.copyItems().length > 0 - ? { - type: "button", - label: "Paste", - leadingIcon: "content_paste", - async onClick() { - let copyItems = viewCtx!.copyItems(); + if (mouseDownAt() + 75 > Date.now()) { + setDragRegion(undefined); + viewCtx!.setSelectedItems([]); + } + }} + onMouseEnter={(e) => { + // if the left mouse button is not pressed + if (!(e.buttons & (1 << 0))) { + setDragRegion(undefined); + } + }} + > + {dragRegion()?.region ? ( +
+ ) : null} + {/* 0 || viewCtx!.copyItems().length > 0 + ? { + type: "button", + label: "Paste", + leadingIcon: "content_paste", + async onClick() { + const copyItems = viewCtx!.copyItems(); - if (copyItems.length > 0) { - await trpc.batchCopy.mutate( - copyItems.map((item) => { - let newPath = path.join(params.currentPath || "", path.basename(item)); + if (copyItems.length > 0) { + await trpc.batchCopy.mutate( + copyItems.map((item) => { + let newPath = path.join(params.currentPath || "", path.basename(item)); - if (path.join(item, "..") === params.currentPath || "") { - newPath = path.join( - params.currentPath || "", - path.basename(item) + - ` (${ - viewCtx! - .viewItems() - .filter((i) => - i.path.startsWith( - path.join( - params.currentPath, - path.basename(item), - ), - ), - ).length - })`, - ); - } + if (path.join(item, "..") === params.currentPath || "") { + newPath = path.join( + params.currentPath || "", + path.basename(item) + + ` (${viewCtx! + .viewItems() + .filter((i) => + i.path.startsWith( + path.join(params.currentPath, path.basename(item)), + ), + ).length + })`, + ); + } - return { - path: item, - newPath: newPath, - }; - }), - ); - } + return { + path: item, + newPath: newPath, + }; + }), + ); + } - let cutItems = viewCtx!.cutItems(); + const cutItems = viewCtx!.cutItems(); - if (cutItems.length > 0) { - await trpc.batchMove.mutate( - cutItems.map((item) => { - let newPath = path.join(params.currentPath || "", path.basename(item)); + if (cutItems.length > 0) { + await trpc.batchMove.mutate( + cutItems.map((item) => { + let newPath = path.join(params.currentPath || "", path.basename(item)); - if (path.join(item, "..") === params.currentPath || "") { - newPath = path.join( - params.currentPath || "", - path.basename(item) + - ` (${ - viewCtx! - .viewItems() - .filter((i) => - i.path.startsWith( - path.join( - params.currentPath, - path.basename(item), - ), - ), - ).length - })`, - ); - } + if (path.join(item, "..") === params.currentPath || "") { + newPath = path.join( + params.currentPath || "", + path.basename(item) + + ` (${viewCtx! + .viewItems() + .filter((i) => + i.path.startsWith( + path.join(params.currentPath, path.basename(item)), + ), + ).length + })`, + ); + } - return { - path: item, - newPath: newPath, - }; - }), - ); - } + return { + path: item, + newPath: newPath, + }; + }), + ); + } - viewCtx!.setSelectedItems([]); - viewCtx!.setCutItems([]); - viewCtx!.setReload(); - }, - } - : undefined, - viewCtx!.selectedItems().length === viewCtx!.viewItems().length - ? undefined - : { - type: "button", - label: "Select All", - leadingIcon: "select_all", - onClick() { - viewCtx!.setSelectedItems(viewCtx!.viewItems().map((i) => i.path)); - }, - }, - viewCtx!.selectedItems().length === 0 - ? undefined - : { - type: "button", - label: "Deselect All", - leadingIcon: "remove_selection", - onClick() { - viewCtx!.setSelectedItems([]); - }, - }, - { - type: "button", - label: "Refresh", - leadingIcon: "refresh", - onClick() { - viewCtx!.setReload(); - }, - }, - ]} - > - You have no view type selected?}> - - - - - - - - - - - -
-
- ); + viewCtx!.setSelectedItems([]); + viewCtx!.setCutItems([]); + viewCtx!.setReload(); + }, + } + : undefined, + viewCtx!.selectedItems().length === viewCtx!.viewItems().length + ? undefined + : { + type: "button", + label: "Select All", + leadingIcon: "select_all", + onClick() { + viewCtx!.setSelectedItems(viewCtx!.viewItems().map((i) => i.path)); + }, + }, + viewCtx!.selectedItems().length === 0 + ? undefined + : { + type: "button", + label: "Deselect All", + leadingIcon: "remove_selection", + onClick() { + viewCtx!.setSelectedItems([]); + }, + }, + { + type: "button", + label: "Refresh", + leadingIcon: "refresh", + onClick() { + viewCtx!.setReload(); + }, + }, + ].filter(i => i !== undefined)}/> + > + */} + You have no view type selected?}> + + + + + + + + + + + + {/**/} +
+ ); }; export default ViewContainer; diff --git a/applications/uk.tcsw.settings/web/pages/customization/quickShortcuts/Index.tsx b/applications/uk.tcsw.settings/web/pages/customization/quickShortcuts/Index.tsx index e060223..be47244 100644 --- a/applications/uk.tcsw.settings/web/pages/customization/quickShortcuts/Index.tsx +++ b/applications/uk.tcsw.settings/web/pages/customization/quickShortcuts/Index.tsx @@ -5,7 +5,6 @@ import UKIcon from "@tcsw/uikit-solid/src/components/icon/UKIcon.tsx"; import UKStack from "@tcsw/uikit-solid/src/components/stack/UKStack.tsx"; import UKText from "@tcsw/uikit-solid/src/components/text/UKText.tsx"; import UKTopAppBar from "@tcsw/uikit-solid/src/components/topAppBar/UKTopAppBar.jsx"; -import CoreApplicationLayoutContext from "@tcsw/workspaces-instance-web/src/pages/app/CoreApplicationLayoutContext.ts"; import { type Component, createResource, useContext } from "solid-js"; import trpc from "../../../lib/trpc"; import AddShortcutButton from "./components/addShortcutButton/AddShortcutButton.tsx"; @@ -15,7 +14,6 @@ import styles from "./Index.module.scss"; const QuickShortcutsPage: Component = () => { const navigate = useNavigate(); - const coreApplicationLayoutContext = useContext(CoreApplicationLayoutContext); const [data, { refetch: refetchData }] = createResource(() => trpc.customization.quickShortcuts.get.query(), ); @@ -69,7 +67,6 @@ const QuickShortcutsPage: Component = () => { }); refetchData(); - coreApplicationLayoutContext.refetchQuickShortcuts(); }} /> )} @@ -78,13 +75,11 @@ const QuickShortcutsPage: Component = () => { { refetchData(); - coreApplicationLayoutContext.refetchQuickShortcuts(); }} /> { refetchData(); - coreApplicationLayoutContext.refetchQuickShortcuts(); }} addShortcut={async (shortcutId) => { await trpc.application.setApplicationStringListSettingValue.mutate({ @@ -93,7 +88,6 @@ const QuickShortcutsPage: Component = () => { value: [...(data()?.currentValue ?? []), shortcutId], }); refetchData(); - coreApplicationLayoutContext.refetchQuickShortcuts(); }} />
diff --git a/instance/src/web/src/pages/app/CoreApplicationLayoutContext.ts b/instance/src/web/src/pages/app/CoreApplicationLayoutContext.ts deleted file mode 100644 index bd1fcc4..0000000 --- a/instance/src/web/src/pages/app/CoreApplicationLayoutContext.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "solid-js"; - -const CoreApplicationLayoutContext = createContext({ refetchQuickShortcuts: () => {} }); - -export default CoreApplicationLayoutContext; diff --git a/instance/src/web/src/pages/app/Layout.module.scss b/instance/src/web/src/pages/app/Layout.module.scss index 53ffafc..147ed43 100644 --- a/instance/src/web/src/pages/app/Layout.module.scss +++ b/instance/src/web/src/pages/app/Layout.module.scss @@ -1,24 +1,10 @@ .page { - display: flex; - flex-direction: column; - width: 100%; - height: 100%; - - /* remove later */ - align-items: center; - justify-content: center; -} - -.versionLabel { - margin-bottom: 0.5rem; - user-select: none; -} - -.rail { - border-right: 1px solid rgb(var(--uk-sys-color-outline-variant)); - - *[data-navigation-rail-mobile-mode="true"] > & { - border-top: 1px solid rgb(var(--uk-sys-color-outline-variant)); - border-right: none; - } + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + + /* remove later */ + align-items: center; + justify-content: center; } diff --git a/instance/src/web/src/pages/app/Layout.tsx b/instance/src/web/src/pages/app/Layout.tsx index e9108fa..9565a47 100644 --- a/instance/src/web/src/pages/app/Layout.tsx +++ b/instance/src/web/src/pages/app/Layout.tsx @@ -1,128 +1,20 @@ -import { type RouteSectionProps, useLocation, useNavigate } from "@solidjs/router"; +import type { RouteSectionProps } from "@solidjs/router"; import UKIndeterminateSpinner from "@tcsw/uikit-solid/src/components/indeterminateSpinner/UKIndeterminateSpinner.jsx"; -import UKNavigationRail from "@tcsw/uikit-solid/src/components/navigationRail/UKNavigationRail.jsx"; -import UKText from "@tcsw/uikit-solid/src/components/text/UKText.tsx"; -import useIsMobile from "@tcsw/uikit-solid/src/core/useIsMobile.ts"; -import { type Component, createResource, createSignal, Show, Suspense } from "solid-js"; -import trpc from "../../lib/trpc"; -import CoreApplicationLayoutContext from "./CoreApplicationLayoutContext.ts"; +import { type Component, lazy, Suspense } from "solid-js"; import styles from "./Layout.module.scss"; -import NavigationRailApplications from "./navigationRailApplications/NavigationRailApplications.tsx"; -import NavigationRailAvatar from "./navigationRailAvatar/NavigationRailAvatar"; -import NavigationRailClock from "./navigationRailClock/NavigationRailClock.tsx"; -import NavigationRailNotifications from "./navigationRailNotifications/NavigationRailNotifications.tsx"; -const AppLayout: Component> = (props) => { - const location = useLocation(); - const navigate = useNavigate(); - const isMobile = useIsMobile(); - - const [quickShortcuts, { refetch: refetchQuickShortcuts }] = createResource(() => - trpc.app.navigation.getQuickShortcuts.query(), - ); - const [expanded, setExpanded] = createSignal(false); - const [toggledDrawer, setToggledDrawer] = createSignal<"applications" | "notifications" | false>( - false, - ); +const AppNavigation = lazy(() => import("./Navigation.tsx")); +const AppLayout: Component> = (props) => { return ( <> - refetchQuickShortcuts() }} - > - {window.localStorage.getItem("tricolor_workspaces_no_app_navigation_rail") !== "true" ? ( - { - return { - icon: sc.icon || { - type: "icon", - value: "indeterminate_question_box", - }, - label: sc.label, - active: location.pathname.startsWith(sc.location.value), - onClick() { - if (sc.location.type === "local") { - navigate(sc.location.value); - } else if (sc.location.type === "remote") { - window.location.href = sc.location.value; - } - }, - onMiddleClick() { - if (sc.location.type === "local") { - window.open(sc.location.value, "_blank"); - } else if (sc.location.type === "remote") { - window.open(sc.location.value, "_blank"); - } - }, - }; - }), - ]} - setExpanded={(exp) => setExpanded(exp)} - anchorPoints={{ - topMost: ( - <> - - - - - ), - top: ( - <> - - - ), - bottom: ( - <> - { - if (toggledDrawer() === "applications") { - setToggledDrawer(false); - } else { - setToggledDrawer(str); - } - }} - expanded={expanded()} - /> - - - Dev Build - - - { - if (toggledDrawer() === "notifications") { - setToggledDrawer(false); - } else { - setToggledDrawer(str); - } - }} - expanded={expanded()} - /> - - ), - }} - > -
- }>{props.children} -
-
- ) : ( -
- }>{props.children} -
- )} -
+ {window.localStorage.getItem("tricolor_workspaces_no_app_navigation_rail") !== "true" ? ( + {props.children} + ) : ( +
+ }>{props.children} +
+ )} ); }; diff --git a/instance/src/web/src/pages/app/Navigation.module.scss b/instance/src/web/src/pages/app/Navigation.module.scss new file mode 100644 index 0000000..b11acca --- /dev/null +++ b/instance/src/web/src/pages/app/Navigation.module.scss @@ -0,0 +1,24 @@ +.versionLabel { + margin-bottom: 0.5rem; + user-select: none; +} + +.rail { + border-right: 1px solid rgb(var(--uk-sys-color-outline-variant)); + + *[data-navigation-rail-mobile-mode="true"] > & { + border-top: 1px solid rgb(var(--uk-sys-color-outline-variant)); + border-right: none; + } +} + +.page { + display: flex; + flex-direction: column; + width: 100%; + height: 100%; + + /* remove later */ + align-items: center; + justify-content: center; +} diff --git a/instance/src/web/src/pages/app/Navigation.tsx b/instance/src/web/src/pages/app/Navigation.tsx new file mode 100644 index 0000000..f8d7ba3 --- /dev/null +++ b/instance/src/web/src/pages/app/Navigation.tsx @@ -0,0 +1,122 @@ +import { useLocation, useNavigate } from "@solidjs/router"; +import UKIndeterminateSpinner from "@tcsw/uikit-solid/src/components/indeterminateSpinner/UKIndeterminateSpinner.jsx"; +import UKNavigationRail from "@tcsw/uikit-solid/src/components/navigationRail/UKNavigationRail.jsx"; +import UKText from "@tcsw/uikit-solid/src/components/text/UKText.jsx"; +import useIsMobile from "@tcsw/uikit-solid/src/core/useIsMobile.js"; +import { + type Component, + createResource, + createSignal, + type ParentProps, + Show, + Suspense, +} from "solid-js"; +import trpc from "../../lib/trpc"; +import styles from "./Navigation.module.scss"; +import NavigationRailApplications from "./navigationRailApplications/NavigationRailApplications"; +import NavigationRailAvatar from "./navigationRailAvatar/NavigationRailAvatar"; +import NavigationRailClock from "./navigationRailClock/NavigationRailClock"; +import NavigationRailNotifications from "./navigationRailNotifications/NavigationRailNotifications"; + +const AppNavigation: Component = (props) => { + const location = useLocation(); + const navigate = useNavigate(); + const isMobile = useIsMobile(); + + const [quickShortcuts] = createResource(() => trpc.app.navigation.getQuickShortcuts.query()); + const [expanded, setExpanded] = createSignal(false); + const [toggledDrawer, setToggledDrawer] = createSignal<"applications" | "notifications" | false>( + false, + ); + + return ( + { + return { + icon: sc.icon || { + type: "icon", + value: "indeterminate_question_box", + }, + label: sc.label, + active: location.pathname.startsWith(sc.location.value), + onClick() { + if (sc.location.type === "local") { + navigate(sc.location.value); + } else if (sc.location.type === "remote") { + window.location.href = sc.location.value; + } + }, + onMiddleClick() { + if (sc.location.type === "local") { + window.open(sc.location.value, "_blank"); + } else if (sc.location.type === "remote") { + window.open(sc.location.value, "_blank"); + } + }, + }; + }), + ]} + setExpanded={(exp) => setExpanded(exp)} + anchorPoints={{ + topMost: ( + <> + + + + + ), + top: ( + <> + + + ), + bottom: ( + <> + { + if (toggledDrawer() === "applications") { + setToggledDrawer(false); + } else { + setToggledDrawer(str); + } + }} + expanded={expanded()} + /> + + + Dev Build + + + { + if (toggledDrawer() === "notifications") { + setToggledDrawer(false); + } else { + setToggledDrawer(str); + } + }} + expanded={expanded()} + /> + + ), + }} + > +
+ }>{props.children} +
+
+ ); +}; + +export default AppNavigation; diff --git a/instance/src/web/vite.config.ts b/instance/src/web/vite.config.ts index 67ec3a6..162b207 100644 --- a/instance/src/web/vite.config.ts +++ b/instance/src/web/vite.config.ts @@ -16,6 +16,11 @@ export default defineConfig({ server: { host: true, allowedHosts: [process.env.ALLOW_HOST || "localhost", "localhost"], + hmr: { + clientPort: 443, + protocol: "wss", + host: process.env.ALLOW_HOST || "localhost", + }, }, resolve: { alias: { diff --git a/uikit-solid/src/components/contextMenu/UKContextMenu.tsx b/uikit-solid/src/components/contextMenu/UKContextMenu.tsx index 1baacc9..4b5468b 100644 --- a/uikit-solid/src/components/contextMenu/UKContextMenu.tsx +++ b/uikit-solid/src/components/contextMenu/UKContextMenu.tsx @@ -1,37 +1,37 @@ -import { type Component, createEffect, createSignal, type ParentProps } from "solid-js"; import { Ref } from "@solid-primitives/refs"; -import UKMenu from "../menu/UKMenu.tsx"; +import { type Component, createEffect, createSignal, type ParentProps } from "solid-js"; +import type UKMenu from "../menu/UKMenu.tsx"; const UKContextMenu: Component< - ParentProps<{ - menu: typeof UKMenu; - }> + ParentProps<{ + menu: typeof UKMenu; + }> > = (props) => { - const [ref, setRef] = createSignal(); - const [showMenu, setShowMenu] = createSignal<{ x: number; y: number } | false>(false); + const [ref, setRef] = createSignal(); + const [showMenu, setShowMenu] = createSignal<{ x: number; y: number } | false>(false); - createEffect(() => { - const element = ref(); + createEffect(() => { + const element = ref(); - if (!element) return; + if (!element) return; - element.addEventListener("contextmenu", (e) => { - e.preventDefault(); + element.addEventListener("contextmenu", (e) => { + e.preventDefault(); - if (e.target === element) - setShowMenu({ - x: (e as unknown as MouseEvent).clientX, - y: (e as unknown as MouseEvent).clientY, - }); + if (e.target === element) + setShowMenu({ + x: (e as unknown as MouseEvent).clientX, + y: (e as unknown as MouseEvent).clientY, }); }); + }); - return ( - <> - {props.children ||
no menu children provided?
}
- {showMenu() && props.menu} - - ); + return ( + <> + {props.children ||
no menu children provided?
}
+ {showMenu() && props.menu} + + ); }; export default UKContextMenu; diff --git a/uikit-solid/src/components/menu/UKMenu.tsx b/uikit-solid/src/components/menu/UKMenu.tsx index d7fa2f6..3c24130 100644 --- a/uikit-solid/src/components/menu/UKMenu.tsx +++ b/uikit-solid/src/components/menu/UKMenu.tsx @@ -1,168 +1,170 @@ -import { type Component, createSignal, For } from "solid-js"; -import UKDivider from "../divider/UKDivider.tsx"; import clsx from "clsx"; -import styles from "./UKMenu.module.scss"; +import { type Component, createSignal, For } from "solid-js"; import { Portal } from "solid-js/web"; -import UKText from "../text/UKText.tsx"; +import UKDivider from "../divider/UKDivider.tsx"; import UKIcon from "../icon/UKIcon.tsx"; +import UKText from "../text/UKText.tsx"; +import styles from "./UKMenu.module.scss"; type MenuItem = - | { - type: "button"; - leadingIcon?: string; - label?: string; - supportingText?: string; - badge?: string; - onClick(): void; - selected?: boolean; - disabled?: boolean; - } - | { - type: "category"; - leadingIcon?: string; - supportingText?: string; - label?: string; - badge?: string; - children?: MenuItem[]; - onClick?(): void; - selected?: boolean; - disabled?: boolean; - } - | { - type: "divider"; - } - | { - type: "spacer"; - }; + | { + type: "button"; + leadingIcon?: string; + label?: string; + supportingText?: string; + badge?: string; + onClick(): void | Promise; + selected?: boolean; + disabled?: boolean; + } + | { + type: "category"; + leadingIcon?: string; + supportingText?: string; + label?: string; + badge?: string; + children?: MenuItem[]; + onClick?(): void; + selected?: boolean; + disabled?: boolean; + } + | { + type: "divider"; + } + | { + type: "spacer"; + }; const UKMenu: Component<{ - items: (MenuItem | undefined)[]; - class?: string; - showMenu?: { x: number; y: number } | false; - vibrant?: boolean; + items: (MenuItem | undefined)[]; + class?: string; + showMenu?: { x: number; y: number } | false; + vibrant?: boolean; }> = (props) => { - const [ref, setRef] = createSignal(); - const [showMenu, setShowMenu] = createSignal<{ x: number; y: number } | false>(props.showMenu || false); + const [ref, setRef] = createSignal(); + const [showMenu, setShowMenu] = createSignal<{ x: number; y: number } | false>( + props.showMenu || false, + ); - return ( - <> - {/*{selected() !== undefined && ( + return ( + <> + {/*{selected() !== undefined && ( )}*/} - {showMenu() !== false && ( - -
{ - e.preventDefault(); - e.stopPropagation(); - setShowMenu(false); - let element = document.elementFromPoint(e.clientX, e.clientY); - if (!element) return; - if ("click" in element) if (typeof element.click === "function") element.click(); - }} - onContextMenu={(e) => { - e.preventDefault(); - setShowMenu(false); - // let element = document.elementFromPoint(e.clientX, e.clientY); - // if (!element) return; - // - // element.dispatchEvent( - // new Event("contextmenu", { bubbles: true, cancelable: true }), - // ); - }} - onMouseDown={(e) => { - e.stopPropagation(); - }} - onMouseUp={(e) => { - e.stopPropagation(); - }} - onMouseMove={(e) => { - e.stopPropagation(); + {showMenu() !== false && ( + +
{ + e.preventDefault(); + e.stopPropagation(); + setShowMenu(false); + const element = document.elementFromPoint(e.clientX, e.clientY); + if (!element) return; + if ("click" in element) if (typeof element.click === "function") element.click(); + }} + onContextMenu={(e) => { + e.preventDefault(); + setShowMenu(false); + // let element = document.elementFromPoint(e.clientX, e.clientY); + // if (!element) return; + // + // element.dispatchEvent( + // new Event("contextmenu", { bubbles: true, cancelable: true }), + // ); + }} + onMouseDown={(e) => { + e.stopPropagation(); + }} + onMouseUp={(e) => { + e.stopPropagation(); + }} + onMouseMove={(e) => { + e.stopPropagation(); + }} + >
+
e.preventDefault()} + onClick={() => setShowMenu(false)} + class={clsx(styles.root, props.class)} + style={{ + top: (showMenu() as { y: number }).y + "px", + left: (showMenu() as { x: number }).x + "px", + }} + > + + {(item, index) => { + if (item === undefined) return null; + + return ( + <> + {item.type === "divider" && ( + + )} + {item.type === "spacer" &&
} + {item.type === "button" && ( +
-
e.preventDefault()} - onClick={() => setShowMenu(false)} - class={clsx(styles.root, props.class)} - style={{ - top: (showMenu() as { y: number }).y + "px", - left: (showMenu() as { x: number }).x + "px", + > + {item.leadingIcon && ( + {item.leadingIcon} + )} +
+ + {item.label} + + + {item.supportingText} + +
+ + )} + {item.type === "category" && ( + - )} - {item.type === "category" && ( - - )} - - ); - }} - -
- - )} - - ); + > + {item.leadingIcon && ( + {item.leadingIcon} + )} +
+ + {item.label} + + + {item.supportingText} + +
+ arrow_right + + )} + + ); + }} +
+
+
+ )} + + ); }; export default UKMenu;