diff --git a/web/src/components/ActivityCalendar/ActivityCalendar.tsx b/web/src/components/ActivityCalendar/ActivityCalendar.tsx
index bb0fb733..aea59114 100644
--- a/web/src/components/ActivityCalendar/ActivityCalendar.tsx
+++ b/web/src/components/ActivityCalendar/ActivityCalendar.tsx
@@ -1,5 +1,6 @@
import { Tooltip } from "@mui/joy";
import dayjs from "dayjs";
+import { observer } from "mobx-react-lite";
import { memo, useMemo } from "react";
import { workspaceStore } from "@/store/v2";
import type { ActivityCalendarProps, CalendarDay } from "@/types/statistics";
@@ -67,104 +68,106 @@ const CalendarCell = memo(
CalendarCell.displayName = "CalendarCell";
-export const ActivityCalendar = memo((props: ActivityCalendarProps) => {
- const t = useTranslate();
- const { month: monthStr, data, onClick } = props;
- const weekStartDayOffset = workspaceStore.state.generalSetting.weekStartDayOffset;
+export const ActivityCalendar = memo(
+ observer((props: ActivityCalendarProps) => {
+ const t = useTranslate();
+ const { month: monthStr, data, onClick } = props;
+ const weekStartDayOffset = workspaceStore.state.generalSetting.weekStartDayOffset;
- const { days, weekDays, maxCount } = useMemo(() => {
- const yearValue = dayjs(monthStr).toDate().getFullYear();
- const monthValue = dayjs(monthStr).toDate().getMonth();
- const dayInMonth = new Date(yearValue, monthValue + 1, 0).getDate();
- const firstDay = (((new Date(yearValue, monthValue, 1).getDay() - weekStartDayOffset) % 7) + 7) % 7;
- const lastDay = new Date(yearValue, monthValue, dayInMonth).getDay() - weekStartDayOffset;
- const prevMonthDays = new Date(yearValue, monthValue, 0).getDate();
+ const { days, weekDays, maxCount } = useMemo(() => {
+ const yearValue = dayjs(monthStr).toDate().getFullYear();
+ const monthValue = dayjs(monthStr).toDate().getMonth();
+ const dayInMonth = new Date(yearValue, monthValue + 1, 0).getDate();
+ const firstDay = (((new Date(yearValue, monthValue, 1).getDay() - weekStartDayOffset) % 7) + 7) % 7;
+ const lastDay = new Date(yearValue, monthValue, dayInMonth).getDay() - weekStartDayOffset;
+ const prevMonthDays = new Date(yearValue, monthValue, 0).getDate();
- const WEEK_DAYS = [t("days.sun"), t("days.mon"), t("days.tue"), t("days.wed"), t("days.thu"), t("days.fri"), t("days.sat")];
- const weekDaysOrdered = WEEK_DAYS.slice(weekStartDayOffset).concat(WEEK_DAYS.slice(0, weekStartDayOffset));
+ const WEEK_DAYS = [t("days.sun"), t("days.mon"), t("days.tue"), t("days.wed"), t("days.thu"), t("days.fri"), t("days.sat")];
+ const weekDaysOrdered = WEEK_DAYS.slice(weekStartDayOffset).concat(WEEK_DAYS.slice(0, weekStartDayOffset));
- const daysArray: CalendarDay[] = [];
+ const daysArray: CalendarDay[] = [];
- // Previous month's days
- for (let i = firstDay - 1; i >= 0; i--) {
- daysArray.push({ day: prevMonthDays - i, isCurrentMonth: false });
- }
+ // Previous month's days
+ for (let i = firstDay - 1; i >= 0; i--) {
+ daysArray.push({ day: prevMonthDays - i, isCurrentMonth: false });
+ }
- // Current month's days
- for (let i = 1; i <= dayInMonth; i++) {
- const date = dayjs(`${yearValue}-${monthValue + 1}-${i}`).format("YYYY-MM-DD");
- daysArray.push({ day: i, isCurrentMonth: true, date });
- }
+ // Current month's days
+ for (let i = 1; i <= dayInMonth; i++) {
+ const date = dayjs(`${yearValue}-${monthValue + 1}-${i}`).format("YYYY-MM-DD");
+ daysArray.push({ day: i, isCurrentMonth: true, date });
+ }
- // Next month's days
- for (let i = 1; i < 7 - lastDay; i++) {
- daysArray.push({ day: i, isCurrentMonth: false });
- }
+ // Next month's days
+ for (let i = 1; i < 7 - lastDay; i++) {
+ daysArray.push({ day: i, isCurrentMonth: false });
+ }
- const maxCountValue = Math.max(...Object.values(data), 1);
+ const maxCountValue = Math.max(...Object.values(data), 1);
- return {
- year: yearValue,
- month: monthValue,
- days: daysArray,
- weekDays: weekDaysOrdered,
- maxCount: maxCountValue,
- };
- }, [monthStr, data, weekStartDayOffset, t]);
+ return {
+ year: yearValue,
+ month: monthValue,
+ days: daysArray,
+ weekDays: weekDaysOrdered,
+ maxCount: maxCountValue,
+ };
+ }, [monthStr, data, weekStartDayOffset, t]);
- const today = useMemo(() => dayjs().format("YYYY-MM-DD"), []);
- const selectedDateFormatted = useMemo(() => dayjs(props.selectedDate).format("YYYY-MM-DD"), [props.selectedDate]);
+ const today = useMemo(() => dayjs().format("YYYY-MM-DD"), []);
+ const selectedDateFormatted = useMemo(() => dayjs(props.selectedDate).format("YYYY-MM-DD"), [props.selectedDate]);
+
+ return (
+
+ {weekDays.map((day, index) => (
+
+ {day}
+
+ ))}
+ {days.map((dayInfo, index) => {
+ if (!dayInfo.isCurrentMonth) {
+ return (
+
+ );
+ }
+
+ const date = dayInfo.date!;
+ const count = data[date] || 0;
+ const isToday = today === date;
+ const isSelected = selectedDateFormatted === date;
+ const tooltipText =
+ count === 0
+ ? date
+ : t("memo.count-memos-in-date", {
+ count: count,
+ memos: count === 1 ? t("common.memo") : t("common.memos"),
+ date: date,
+ }).toLowerCase();
- return (
-
- {weekDays.map((day, index) => (
-
- {day}
-
- ))}
- {days.map((dayInfo, index) => {
- if (!dayInfo.isCurrentMonth) {
return (
onClick?.(date)}
+ tooltipText={tooltipText}
/>
);
- }
-
- const date = dayInfo.date!;
- const count = data[date] || 0;
- const isToday = today === date;
- const isSelected = selectedDateFormatted === date;
- const tooltipText =
- count === 0
- ? date
- : t("memo.count-memos-in-date", {
- count: count,
- memos: count === 1 ? t("common.memo") : t("common.memos"),
- date: date,
- }).toLowerCase();
-
- return (
- onClick?.(date)}
- tooltipText={tooltipText}
- />
- );
- })}
-
- );
-});
+ })}
+
+ );
+ }),
+);
ActivityCalendar.displayName = "ActivityCalendar";
diff --git a/web/src/components/BrandBanner.tsx b/web/src/components/BrandBanner.tsx
index 443015ab..97ac17ea 100644
--- a/web/src/components/BrandBanner.tsx
+++ b/web/src/components/BrandBanner.tsx
@@ -1,3 +1,4 @@
+import { observer } from "mobx-react-lite";
import { workspaceStore } from "@/store/v2";
import { cn } from "@/utils";
import UserAvatar from "./UserAvatar";
@@ -7,7 +8,7 @@ interface Props {
collapsed?: boolean;
}
-const BrandBanner = (props: Props) => {
+const BrandBanner = observer((props: Props) => {
const { collapsed } = props;
const workspaceGeneralSetting = workspaceStore.state.generalSetting;
const title = workspaceGeneralSetting.customProfile?.title || "Memos";
@@ -21,6 +22,6 @@ const BrandBanner = (props: Props) => {
);
-};
+});
export default BrandBanner;
diff --git a/web/src/components/MemoActionMenu.tsx b/web/src/components/MemoActionMenu.tsx
index 5d1affb8..a27c1101 100644
--- a/web/src/components/MemoActionMenu.tsx
+++ b/web/src/components/MemoActionMenu.tsx
@@ -16,8 +16,7 @@ import toast from "react-hot-toast";
import { useLocation } from "react-router-dom";
import { markdownServiceClient } from "@/grpcweb";
import useNavigateTo from "@/hooks/useNavigateTo";
-import { memoStore } from "@/store/v2";
-import { userStore } from "@/store/v2";
+import { memoStore, userStore } from "@/store/v2";
import { State } from "@/types/proto/api/v1/common";
import { NodeType } from "@/types/proto/api/v1/markdown_service";
import { Memo } from "@/types/proto/api/v1/memo_service";
diff --git a/web/src/components/MemoContent/Tag.tsx b/web/src/components/MemoContent/Tag.tsx
index 581fb3e3..560f8add 100644
--- a/web/src/components/MemoContent/Tag.tsx
+++ b/web/src/components/MemoContent/Tag.tsx
@@ -1,9 +1,10 @@
+import { observer } from "mobx-react-lite";
import { useContext } from "react";
import { useLocation } from "react-router-dom";
import useNavigateTo from "@/hooks/useNavigateTo";
import { Routes } from "@/router";
-import memoFilterStore, { MemoFilter } from "@/store/v2/memoFilter";
-import { stringifyFilters } from "@/store/v2/memoFilter";
+import { memoFilterStore } from "@/store/v2";
+import { stringifyFilters, MemoFilter } from "@/store/v2/memoFilter";
import { cn } from "@/utils";
import { RendererContext } from "./types";
@@ -11,7 +12,7 @@ interface Props {
content: string;
}
-const Tag: React.FC = ({ content }: Props) => {
+const Tag = observer(({ content }: Props) => {
const context = useContext(RendererContext);
const location = useLocation();
const navigateTo = useNavigateTo();
@@ -50,6 +51,6 @@ const Tag: React.FC = ({ content }: Props) => {
#{content}
);
-};
+});
export default Tag;
diff --git a/web/src/components/MemoFilters.tsx b/web/src/components/MemoFilters.tsx
index 7f66248e..dc9430a3 100644
--- a/web/src/components/MemoFilters.tsx
+++ b/web/src/components/MemoFilters.tsx
@@ -1,12 +1,13 @@
import { isEqual } from "lodash-es";
import { CalendarIcon, CheckCircleIcon, CodeIcon, EyeIcon, HashIcon, LinkIcon, BookmarkIcon, SearchIcon, XIcon } from "lucide-react";
+import { observer } from "mobx-react-lite";
import { useEffect } from "react";
import { useSearchParams } from "react-router-dom";
-import memoFilterStore from "@/store/v2/memoFilter";
+import { memoFilterStore } from "@/store/v2";
import { FilterFactor, getMemoFilterKey, MemoFilter, stringifyFilters } from "@/store/v2/memoFilter";
import { useTranslate } from "@/utils/i18n";
-const MemoFilters = () => {
+const MemoFilters = observer(() => {
const t = useTranslate();
const [, setSearchParams] = useSearchParams();
const filters = memoFilterStore.filters;
@@ -60,7 +61,7 @@ const MemoFilters = () => {
))}
);
-};
+});
const FactorIcon = ({ factor, className }: { factor: FilterFactor; className?: string }) => {
const iconMap = {
diff --git a/web/src/components/MemoReactionListView.tsx b/web/src/components/MemoReactionListView.tsx
index 5ec1189c..f7853527 100644
--- a/web/src/components/MemoReactionListView.tsx
+++ b/web/src/components/MemoReactionListView.tsx
@@ -1,4 +1,5 @@
import { uniq } from "lodash-es";
+import { observer } from "mobx-react-lite";
import { memo, useEffect, useState } from "react";
import useCurrentUser from "@/hooks/useCurrentUser";
import { userStore } from "@/store/v2";
@@ -14,7 +15,7 @@ interface Props {
reactions: Reaction[];
}
-const MemoReactionListView = (props: Props) => {
+const MemoReactionListView = observer((props: Props) => {
const { memo, reactions } = props;
const currentUser = useCurrentUser();
const [reactionGroup, setReactionGroup] = useState