diff --git a/ui/v2/package.json b/ui/v2/package.json index 38f437392..771557831 100644 --- a/ui/v2/package.json +++ b/ui/v2/package.json @@ -17,6 +17,7 @@ "bulma": "0.7.4", "formik": "1.5.1", "graphql": "14.1.1", + "localforage": "1.7.3", "lodash": "4.17.11", "node-sass": "4.11.0", "query-string": "6.2.0", diff --git a/ui/v2/src/components/Settings/Settings.tsx b/ui/v2/src/components/Settings/Settings.tsx index 8e6593e9c..61f8294c9 100644 --- a/ui/v2/src/components/Settings/Settings.tsx +++ b/ui/v2/src/components/Settings/Settings.tsx @@ -8,6 +8,7 @@ import React, { FunctionComponent, useEffect, useState } from "react"; import { IBaseProps } from "../../models"; import { SettingsAboutPanel } from "./SettingsAboutPanel"; import { SettingsConfigurationPanel } from "./SettingsConfigurationPanel"; +import { SettingsInterfacePanel } from "./SettingsInterfacePanel"; import { SettingsLogsPanel } from "./SettingsLogsPanel"; import { SettingsTasksPanel } from "./SettingsTasksPanel/SettingsTasksPanel"; @@ -39,6 +40,7 @@ export const Settings: FunctionComponent = (props: IProps) => { defaultSelectedTabId={getTabId()} > } /> + } /> } /> } /> } /> diff --git a/ui/v2/src/components/Settings/SettingsInterfacePanel.tsx b/ui/v2/src/components/Settings/SettingsInterfacePanel.tsx new file mode 100644 index 000000000..16c91c74a --- /dev/null +++ b/ui/v2/src/components/Settings/SettingsInterfacePanel.tsx @@ -0,0 +1,35 @@ +import { + Checkbox, + FormGroup, + H4, +} from "@blueprintjs/core"; +import _ from "lodash"; +import React, { FunctionComponent } from "react"; +import { useInterfaceLocalForage } from "../../hooks/LocalForage"; + +interface IProps {} + +export const SettingsInterfacePanel: FunctionComponent = () => { + const {data, setData} = useInterfaceLocalForage(); + + return ( + <> +

User Interface

+ + { + if (!data) { return; } + const newSettings = _.cloneDeep(data); + newSettings.wall.textContainerEnabled = !data.wall.textContainerEnabled; + setData(newSettings); + }} + /> + + + ); +}; diff --git a/ui/v2/src/components/Stats.tsx b/ui/v2/src/components/Stats.tsx index 62a92a2de..b14a58727 100644 --- a/ui/v2/src/components/Stats.tsx +++ b/ui/v2/src/components/Stats.tsx @@ -55,8 +55,6 @@ export const Stats: FunctionComponent = () => { This is still an early version, some things are still a work in progress. * Filters for performers and studios only supports one item, even though it's a multi select. - * All of the task buttons in settings do work, but provide no feedback in the UI currently. - * The tasks tab is the only tab with content in the settings menu. TODO: * List view for scenes / performers diff --git a/ui/v2/src/components/Wall/Wall.scss b/ui/v2/src/components/Wall/Wall.scss index 1a87e65ea..097de8ab7 100644 --- a/ui/v2/src/components/Wall/Wall.scss +++ b/ui/v2/src/components/Wall/Wall.scss @@ -39,8 +39,8 @@ .scene-wall-item-container { display: flex; justify-content: center; - align-items: center; - overflow: hidden; + // align-items: center; + // overflow: hidden; // Commented out since it shows gaps in the wall position: relative; width: 100%; height: 100%; diff --git a/ui/v2/src/components/Wall/WallItem.tsx b/ui/v2/src/components/Wall/WallItem.tsx index e7e04921e..143b797f2 100644 --- a/ui/v2/src/components/Wall/WallItem.tsx +++ b/ui/v2/src/components/Wall/WallItem.tsx @@ -2,6 +2,7 @@ import _ from "lodash"; import React, { FunctionComponent, useRef, useState } from "react"; import { Link } from "react-router-dom"; import * as GQL from "../../core/generated-graphql"; +import { useInterfaceLocalForage } from "../../hooks/LocalForage"; import { VideoHoverHook } from "../../hooks/VideoHover"; import { TextUtils } from "../../utils/text"; @@ -16,6 +17,8 @@ interface IWallItemProps { export const WallItem: FunctionComponent = (props: IWallItemProps) => { const [videoPath, setVideoPath] = useState(undefined); const videoHoverHook = VideoHoverHook.useVideoHover({resetOnMouseLeave: true}); + const interfaceSettings = useInterfaceLocalForage(); + const showTextContainer = !!interfaceSettings.data ? interfaceSettings.data.wall.textContainerEnabled : true; function onMouseEnter() { VideoHoverHook.onMouseEnter(videoHoverHook); @@ -101,12 +104,14 @@ export const WallItem: FunctionComponent = (props: IWallItemProp ref={videoHoverHook.videoEl} /> -
-
- {title} -
- {tags} -
+ {showTextContainer ? +
+
+ {title} +
+ {tags} +
: undefined + } diff --git a/ui/v2/src/hooks/LocalForage.ts b/ui/v2/src/hooks/LocalForage.ts new file mode 100644 index 000000000..45add7cc4 --- /dev/null +++ b/ui/v2/src/hooks/LocalForage.ts @@ -0,0 +1,67 @@ +import localForage from "localforage"; +import _ from "lodash"; +import React from "react"; + +interface IInterfaceWallConfig { + textContainerEnabled: boolean; +} +export interface IInterfaceConfig { + wall: IInterfaceWallConfig; +} + +type ValidTypes = IInterfaceConfig | undefined; + +interface ILocalForage { + data: T; + setData: React.Dispatch>; + error: Error | null; +} + +export function useInterfaceLocalForage(): ILocalForage { + const result = useLocalForage("interface"); + // Set defaults + React.useEffect(() => { + if (result.data === undefined) { + result.setData({ + wall: { + textContainerEnabled: true, + }, + }); + } + }); + return result; +} + +function useLocalForage(item: string): ILocalForage { + const [json, setJson] = React.useState(undefined); + + const prevJson = React.useRef(undefined); + React.useEffect(() => { + async function runAsync() { + if (typeof json !== "undefined" && !_.isEqual(json, prevJson.current)) { + await localForage.setItem(item, JSON.stringify(json)); + } + prevJson.current = json; + } + runAsync(); + }); + + const [err, setErr] = React.useState(null); + React.useEffect(() => { + async function runAsync() { + try { + const serialized = await localForage.getItem(item); + const parsed = JSON.parse(serialized); + if (typeof json === "undefined" && !Object.is(parsed, null)) { + setErr(null); + setJson(parsed); + } + } catch (error) { + setErr(error); + } + } + runAsync(); + }); + + return {data: json, setData: setJson, error: err}; +} diff --git a/ui/v2/yarn.lock b/ui/v2/yarn.lock index ef918b583..a6b8415db 100755 --- a/ui/v2/yarn.lock +++ b/ui/v2/yarn.lock @@ -5448,6 +5448,11 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps= + immer@1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" @@ -6751,6 +6756,13 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lie@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" + integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4= + dependencies: + immediate "~3.0.5" + listr-silent-renderer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" @@ -6838,6 +6850,13 @@ loader-utils@1.2.3, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1. emojis-list "^2.0.0" json5 "^1.0.1" +localforage@1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.7.3.tgz#0082b3ca9734679e1bd534995bdd3b24cf10f204" + integrity sha512-1TulyYfc4udS7ECSBT2vwJksWbkwwTX8BzeUIiq8Y07Riy7bDAAnxDaPU/tWyOVmQAcWJIEIFP9lPfBGqVoPgQ== + dependencies: + lie "3.1.1" + locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"