mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
chore: update location store handler (#1273)
* chore: update location store handler * chore: update search bar
This commit is contained in:
@ -31,6 +31,7 @@ const Header = () => {
|
|||||||
<Link
|
<Link
|
||||||
to="/"
|
to="/"
|
||||||
className="px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
|
className="px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
|
||||||
|
onClick={() => locationStore.clearQuery()}
|
||||||
>
|
>
|
||||||
<Icon.Home className="mr-4 w-6 h-auto opacity-80" /> {t("common.home")}
|
<Icon.Home className="mr-4 w-6 h-auto opacity-80" /> {t("common.home")}
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import { isUndefined } from "lodash-es";
|
import { isUndefined } from "lodash-es";
|
||||||
import { useEffect } from "react";
|
|
||||||
import { useLocationStore } from "../store/module";
|
|
||||||
import ShortcutList from "./ShortcutList";
|
import ShortcutList from "./ShortcutList";
|
||||||
import TagList from "./TagList";
|
import TagList from "./TagList";
|
||||||
import SearchBar from "./SearchBar";
|
import SearchBar from "./SearchBar";
|
||||||
@ -8,13 +6,6 @@ import UsageHeatMap from "./UsageHeatMap";
|
|||||||
import "../less/home-sidebar.less";
|
import "../less/home-sidebar.less";
|
||||||
|
|
||||||
const HomeSidebar = () => {
|
const HomeSidebar = () => {
|
||||||
const locationStore = useLocationStore();
|
|
||||||
const query = locationStore.state.query;
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
toggleHomeSidebar(false);
|
|
||||||
}, [query]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="mask" onClick={() => toggleHomeSidebar(false)}></div>
|
<div className="mask" onClick={() => toggleHomeSidebar(false)}></div>
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
import { useEffect, useState, useRef } from "react";
|
import { useEffect, useState, useRef } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import useDebounce from "../hooks/useDebounce";
|
import useDebounce from "../hooks/useDebounce";
|
||||||
import { useLocationStore, useDialogStore } from "../store/module";
|
import { useLocationStore, useDialogStore } from "../store/module";
|
||||||
import { memoSpecialTypes } from "../helpers/filter";
|
|
||||||
import Icon from "./Icon";
|
import Icon from "./Icon";
|
||||||
import "../less/search-bar.less";
|
|
||||||
|
|
||||||
const SearchBar = () => {
|
const SearchBar = () => {
|
||||||
const { t } = useTranslation();
|
|
||||||
const locationStore = useLocationStore();
|
const locationStore = useLocationStore();
|
||||||
const dialogStore = useDialogStore();
|
const dialogStore = useDialogStore();
|
||||||
const memoType = locationStore.state.query.type;
|
|
||||||
const [queryText, setQueryText] = useState("");
|
const [queryText, setQueryText] = useState("");
|
||||||
const [isFocus, setIsFocus] = useState(false);
|
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -49,68 +43,22 @@ const SearchBar = () => {
|
|||||||
[queryText]
|
[queryText]
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleMemoTypeItemClick = (type: MemoSpecType | undefined) => {
|
|
||||||
const { type: prevType } = locationStore.getState().query ?? {};
|
|
||||||
if (type === prevType) {
|
|
||||||
type = undefined;
|
|
||||||
}
|
|
||||||
locationStore.setMemoTypeQuery(type);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleTextQueryInput = (event: React.FormEvent<HTMLInputElement>) => {
|
const handleTextQueryInput = (event: React.FormEvent<HTMLInputElement>) => {
|
||||||
const text = event.currentTarget.value;
|
const text = event.currentTarget.value;
|
||||||
setQueryText(text);
|
setQueryText(text);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFocus = () => {
|
|
||||||
setIsFocus(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleBlur = () => {
|
|
||||||
setIsFocus(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`search-bar-container ${isFocus ? "is-focus" : ""}`}>
|
<div className="w-full h-9 flex flex-row justify-start items-center py-2 px-3 rounded-md bg-gray-200 dark:bg-zinc-700">
|
||||||
<div className="search-bar-inputer">
|
<Icon.Search className="w-4 h-auto opacity-30 dark:text-gray-200" />
|
||||||
<Icon.Search className="icon-img" />
|
<input
|
||||||
<input
|
className="flex ml-2 w-24 grow text-sm outline-none bg-transparent dark:text-gray-200"
|
||||||
className="text-input"
|
type="text"
|
||||||
autoComplete="new-password"
|
placeholder="Search memos"
|
||||||
type="text"
|
ref={inputRef}
|
||||||
placeholder=""
|
value={queryText}
|
||||||
ref={inputRef}
|
onChange={handleTextQueryInput}
|
||||||
value={queryText}
|
/>
|
||||||
onChange={handleTextQueryInput}
|
|
||||||
onFocus={handleFocus}
|
|
||||||
onBlur={handleBlur}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="quickly-action-wrapper !hidden">
|
|
||||||
<div className="quickly-action-container">
|
|
||||||
<p className="title-text">{t("search.quickly-filter").toUpperCase()}</p>
|
|
||||||
<div className="section-container types-container">
|
|
||||||
<span className="section-text">{t("common.type").toUpperCase()}:</span>
|
|
||||||
<div className="values-container">
|
|
||||||
{memoSpecialTypes.map((type, idx) => {
|
|
||||||
return (
|
|
||||||
<div key={type.value}>
|
|
||||||
<span
|
|
||||||
className={`type-item ${memoType === type.value ? "selected" : ""}`}
|
|
||||||
onClick={() => {
|
|
||||||
handleMemoTypeItemClick(type.value as MemoSpecType);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t(type.text)}
|
|
||||||
</span>
|
|
||||||
{idx + 1 < memoSpecialTypes.length ? <span className="split-text">/</span> : null}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2,9 +2,8 @@ import { useEffect, useState } from "react";
|
|||||||
import { compare } from "semver";
|
import { compare } from "semver";
|
||||||
import * as api from "../helpers/api";
|
import * as api from "../helpers/api";
|
||||||
import * as storage from "../helpers/storage";
|
import * as storage from "../helpers/storage";
|
||||||
import Icon from "./Icon";
|
|
||||||
import "../less/about-site-dialog.less";
|
|
||||||
import { useGlobalStore } from "../store/module";
|
import { useGlobalStore } from "../store/module";
|
||||||
|
import Icon from "./Icon";
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
latestVersion: string;
|
latestVersion: string;
|
||||||
@ -52,7 +51,7 @@ const UpdateVersionBanner: React.FC = () => {
|
|||||||
<Icon.ArrowUpCircle className="w-5 h-auto mr-2" />
|
<Icon.ArrowUpCircle className="w-5 h-auto mr-2" />
|
||||||
New Update <span className="ml-1 font-bold">{state.latestVersion}</span>
|
New Update <span className="ml-1 font-bold">{state.latestVersion}</span>
|
||||||
</a>
|
</a>
|
||||||
<button className="absolute opacity-20 right-4 btn" title="Skip this version" onClick={onSkip}>
|
<button className="absolute opacity-80 right-4 hover:opacity-100" title="Skip this version" onClick={onSkip}>
|
||||||
<Icon.X />
|
<Icon.X />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
.search-bar-container {
|
|
||||||
@apply relative w-full;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:active {
|
|
||||||
> .quickly-action-wrapper {
|
|
||||||
@apply flex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.is-focus {
|
|
||||||
> .quickly-action-wrapper {
|
|
||||||
@apply flex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .search-bar-inputer {
|
|
||||||
@apply h-9 flex flex-row justify-start items-center w-full py-2 px-3 sm:px-4 rounded-md bg-gray-200 dark:bg-zinc-700;
|
|
||||||
|
|
||||||
> .icon-img {
|
|
||||||
@apply w-4 h-auto opacity-30 dark:text-gray-200;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .text-input {
|
|
||||||
@apply flex ml-2 w-24 grow text-sm outline-none bg-transparent dark:text-gray-200;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .quickly-action-wrapper {
|
|
||||||
@apply hidden absolute top-9 -right-2 p-2 w-60 z-10;
|
|
||||||
|
|
||||||
> .quickly-action-container {
|
|
||||||
@apply flex flex-col justify-start items-start w-full bg-white dark:bg-zinc-700 px-4 py-3 rounded-lg;
|
|
||||||
box-shadow: 0 0 4px 0 rgb(0 0 0 / 20%);
|
|
||||||
|
|
||||||
> .title-text {
|
|
||||||
@apply text-gray-600 dark:text-gray-400 text-xs;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .types-container {
|
|
||||||
@apply flex flex-row justify-start items-start w-full text-xs mt-2;
|
|
||||||
|
|
||||||
> .section-text {
|
|
||||||
@apply text-gray-600 dark:text-gray-400 mr-1 shrink-0 leading-6;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .values-container {
|
|
||||||
@apply flex flex-row justify-start items-start flex-wrap select-none;
|
|
||||||
|
|
||||||
> div {
|
|
||||||
@apply flex flex-row justify-start items-center leading-6;
|
|
||||||
|
|
||||||
.type-item {
|
|
||||||
@apply cursor-pointer px-2 rounded dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-600;
|
|
||||||
|
|
||||||
&.selected {
|
|
||||||
@apply !bg-green-600 text-white;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.split-text {
|
|
||||||
@apply text-gray-400 mx-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user