memo 结构

.
├── index.html
├── package.json
├── pnpm-lock.yaml
├── postcss.config.js
├── public
│   └── site.webmanifest #?
├── src
│   ├── App.tsx
│   ├── components
│   │   ├── ActivityCalendar.tsx
│   │   ├── AppearanceSelect.tsx
│   │   ├── BetaBadge.tsx
│   │   ├── ChangeMemberPasswordDialog.tsx
│   │   ├── ChangeMemoCreatedTsDialog.tsx
│   │   ├── ChangePasswordDialog.tsx
│   │   ├── CreateAccessTokenDialog.tsx
│   │   ├── CreateIdentityProviderDialog.tsx
│   │   ├── CreateMemoRelationDialog.tsx
│   │   ├── CreateResourceDialog.tsx
│   │   ├── CreateStorageServiceDialog.tsx
│   │   ├── CreateTagDialog.tsx
│   │   ├── CreateWebhookDialog.tsx
│   │   ├── Dialog
│   │   │   ├── BaseDialog.tsx
│   │   │   ├── CommonDialog.tsx
│   │   │   └── index.ts
│   │   ├── DisablePasswordLoginDialog.tsx
│   │   ├── Empty.tsx
│   │   ├── HomeSidebar.tsx
│   │   ├── HomeSidebarDrawer.tsx
│   │   ├── Icon.ts
│   │   ├── Inbox
│   │   │   ├── MemoCommentMessage.tsx
│   │   │   └── VersionUpdateMessage.tsx
│   │   ├── LearnMore.tsx
│   │   ├── LocaleSelect.tsx
│   │   ├── MemoContent
│   │   │   ├── Blockquote.tsx
│   │   │   ├── Bold.tsx
│   │   │   ├── BoldItalic.tsx
│   │   │   ├── Code.tsx
│   │   │   ├── CodeBlock.tsx
│   │   │   ├── EmbeddedContent
│   │   │   │   ├── EmbeddedMemo.tsx
│   │   │   │   ├── EmbeddedResource.tsx
│   │   │   │   ├── Error.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── EscapingCharacter.tsx
│   │   │   ├── Heading.tsx
│   │   │   ├── Highlight.tsx
│   │   │   ├── HorizontalRule.tsx
│   │   │   ├── Image.tsx
│   │   │   ├── Italic.tsx
│   │   │   ├── LineBreak.tsx
│   │   │   ├── Link.tsx
│   │   │   ├── Math.tsx
│   │   │   ├── OrderedList.tsx
│   │   │   ├── Paragraph.tsx
│   │   │   ├── Renderer.tsx
│   │   │   ├── Strikethrough.tsx
│   │   │   ├── Subscript.tsx
│   │   │   ├── Superscript.tsx
│   │   │   ├── Table.tsx
│   │   │   ├── Tag.tsx
│   │   │   ├── TaskList.tsx
│   │   │   ├── Text.tsx
│   │   │   ├── UnorderedList.tsx
│   │   │   ├── index.tsx
│   │   │   └── types
│   │   │   ├── context.ts
│   │   │   └── index.ts
│   │   ├── MemoEditor
│   │   │   ├── ActionButton
│   │   │   │   ├── MarkdownMenu.tsx
│   │   │   │   └── TagSelector.tsx
│   │   │   ├── Editor
│   │   │   │   ├── TagSuggestions.tsx
│   │   │   │   └── index.tsx
│   │   │   ├── MemoEditorDialog.tsx
│   │   │   ├── RelationListView.tsx
│   │   │   ├── ResourceListView.tsx
│   │   │   ├── handlers.tsx
│   │   │   └── index.tsx
│   │   ├── MemoFilter.tsx
│   │   ├── MemoRelationListView.tsx
│   │   ├── MemoResource.tsx
│   │   ├── MemoResourceListView.tsx
│   │   ├── MemoView.tsx
│   │   ├── MobileHeader.tsx
│   │   ├── Navigation.tsx
│   │   ├── NavigationDrawer.tsx
│   │   ├── PersonalStatistics.tsx
│   │   ├── PreviewImageDialog.tsx
│   │   ├── PreviewMarkdownDialog.tsx
│   │   ├── RequiredBadge.tsx
│   │   ├── ResourceIcon.tsx
│   │   ├── SearchBar.tsx
│   │   ├── Settings
│   │   │   ├── AccessTokenSection.tsx
│   │   │   ├── MemberSection.tsx
│   │   │   ├── MyAccountSection.tsx
│   │   │   ├── PreferencesSection.tsx
│   │   │   ├── SSOSection.tsx
│   │   │   ├── StorageSection.tsx
│   │   │   ├── SystemSection.tsx
│   │   │   └── WebhookSection.tsx
│   │   ├── ShareMemoDialog.tsx
│   │   ├── TagList.tsx
│   │   ├── UpdateAccountDialog.tsx
│   │   ├── UpdateCustomizedProfileDialog.tsx
│   │   ├── UpdateLocalStorageDialog.tsx
│   │   ├── UserAvatar.tsx
│   │   ├── UserBanner.tsx
│   │   ├── VisibilityIcon.tsx
│   │   └── kit
│   │   ├── DatePicker.tsx
│   │   ├── Dropdown.tsx
│   │   ├── OverflowTip.tsx
│   │   ├── README.md
│   │   └── SquareDiv.tsx
│   ├── css
│   │   ├── global.css
│   │   └── tailwind.css
│   ├── grpcweb.ts # grpc?
│   ├── helpers # util
│   │   ├── api.ts
│   │   ├── consts.ts
│   │   ├── datetime.ts
│   │   ├── polyfill.ts
│   │   ├── storage.ts
│   │   └── utils.ts
│   ├── hooks # usestate 打包
│   │   ├── index.ts
│   │   ├── useCurrentUser.ts
│   │   ├── useLoading.ts
│   │   ├── useNavigateTo.ts
│   │   └── useResponsiveWidth.ts
│   ├── i18n.ts # language
│   ├── labs
│   │   └── html2image
│   │   ├── convertResourceToDataURL.ts
│   │   ├── getCloneStyledElement.ts
│   │   ├── index.ts
│   │   └── waitImageLoaded.ts
│   ├── layouts
│   │   ├── Root.tsx
│   │   └── SuspenseWrapper.tsx
│   ├── less
│   │   ├── base-dialog.less
│   │   ├── common
│   │   │   └── date-picker.less
│   │   ├── common-dialog.less
│   │   ├── highlight.less
│   │   ├── memo.less
│   │   ├── preview-image-dialog.less
│   │   └── share-memo-dialog.less
│   ├── locales # language
│   │   ├── ar.json
│   │   ├── de.json
│   │   ├── en.json
│   │   ├── locale_updater.py
│   ├── main.tsx # mainview
│   ├── pages
│   │   ├── About.tsx
│   │   ├── Archived.tsx
│   │   ├── AuthCallback.tsx
│   │   ├── Explore.tsx
│   │   ├── Home.tsx
│   │   ├── Inboxes.tsx
│   │   ├── Loading.tsx
│   │   ├── MemoDetail.tsx
│   │   ├── NotFound.tsx
│   │   ├── PermissionDenied.tsx
│   │   ├── Resources.tsx
│   │   ├── Setting.tsx
│   │   ├── SignIn.tsx
│   │   ├── SignUp.tsx
│   │   ├── Timeline.tsx
│   │   └── UserProfile.tsx
│   ├── router
│   │   ├── AuthStatusProvider.tsx
│   │   └── index.tsx
│   ├── store
│   │   ├── index.ts
│   │   ├── module#return:{some_useselector,some_get_set_state,some_dispatch}
│   │   │   ├── dialog.ts
│   │   │   ├── filter.ts
│   │   │   ├── global.ts
│   │   │   ├── index.ts
│   │   │   ├── resource.ts
│   │   │   └── tag.ts
│   │   ├── reducer#create_slice
│   │   │   ├── dialog.ts
│   │   │   ├── filter.ts
│   │   │   ├── global.ts
│   │   │   ├── resource.ts
│   │   │   └── tag.ts
│   │   └── v1
│   │   ├── inbox.ts
│   │   ├── index.ts
│   │   ├── memo.ts
│   │   ├── resource.ts
│   │   ├── resourceName.ts
│   │   └── user.ts
│   ├── theme
│   │   └── index.ts
│   ├── types
│   │   ├── common.d.ts
│   │   ├── i18n.d.ts
│   │   ├── modules
│   │   │   ├── common.d.ts
│   │   │   ├── idp.d.ts
│   │   │   ├── resource.d.ts
│   │   │   ├── setting.d.ts
│   │   │   ├── storage.d.ts
│   │   │   ├── system.d.ts
│   │   │   └── user.d.ts
│   │   ├── utils
│   │   │   └── nestedKeyOf.types.ts
│   │   └── view.d.ts
│   └── utils
│   ├── i18n.ts
│   ├── memo.ts
│   ├── resource.ts
│   ├── tag.ts
│   └── uuid.ts
├── tailwind.config.js
├── tsconfig.json
└── vite.config.ts
// how to use
const dialogStore = useDialogStore();
dialogStore.pushDialogStack(dialogName);

// xxx store
export const useDialogStore = () => {
const state = useAppSelector((state) => state.dialog);
return {
state,
getState: () => {
return store.getState().dialog;
},
pushDialogStack: (dialogName: string) => {
store.dispatch(pushDialogStack(dialogName));
},
popDialogStack: () => {
store.dispatch(popDialogStack());
},
removeDialog: (dialogName: string) => {
store.dispatch(removeDialog(dialogName));
},
topDialogStack: () => {
return last(store.getState().dialog.dialogStack);
},
};
};

// xxx reducer
const dialogSlice = createSlice({
name: "dialog",
initialState: {
dialogStack: [],
} as State,
reducers: {
removeDialog: (state, action: PayloadAction<string>) => {
const filterDialogStack = state.dialogStack.filter((dialogName) => dialogName !== action.payload);
return {
...state,
dialogStack: filterDialogStack,
};
},// end action
},// end reducers
});
export const { pushDialogStack, popDialogStack, removeDialog } = dialogSlice.actions;
export default dialogSlice.reducer;