forked from mxx1111/mdlook
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathui.ts
More file actions
274 lines (228 loc) · 8.77 KB
/
Copy pathui.ts
File metadata and controls
274 lines (228 loc) · 8.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
import { addPrefix } from '@/utils'
import { store } from '@/utils/storage'
/**
* UI 状态 Store
* 负责管理全局 UI 状态,包括深色模式、侧边栏、对话框等
*/
export const useUIStore = defineStore(`ui`, () => {
// ==================== 全局 UI 状态 ====================
// 是否开启深色模式
const isDark = useDark()
const toggleDark = useToggle(isDark)
// 是否在左侧编辑
const isEditOnLeft = store.reactive(`isEditOnLeft`, true)
const toggleEditOnLeft = useToggle(isEditOnLeft)
// 是否开启 AI 工具箱
const showAIToolbox = store.reactive(`showAIToolbox`, true)
const toggleAIToolbox = useToggle(showAIToolbox)
// 是否已经显示过 AI 工具箱选中文本提示
const hasShownAIToolboxHint = store.reactive(`hasShownAIToolboxHint`, false)
// 是否打开右侧滑块
const isOpenRightSlider = store.reactive(addPrefix(`is_open_right_slider`), false)
// 是否打开文章列表滑块
const isOpenPostSlider = store.reactive(addPrefix(`is_open_post_slider`), false)
// 是否打开本地文件夹面板
const isOpenFolderPanel = store.reactive(addPrefix(`is_open_folder_panel`), false)
// 是否为移动端
const isMobile = store.reactive(`isMobile`, false)
// 视图模式:edit(纯编辑)| split(双屏)| preview(纯预览)
const viewMode = store.reactive<'edit' | 'split' | 'preview'>(`viewMode`, `split`)
function setViewMode(mode: 'edit' | 'split' | 'preview') {
viewMode.value = mode
}
// 编辑器类型:source(源码 + 预览)| wysiwyg(所见即所得,Typora 式)
const editorType = store.reactive<'source' | 'wysiwyg'>(`editorType`, `source`)
function setEditorType(type: 'source' | 'wysiwyg') {
editorType.value = type
// 所见即所得是 Typora 式整屏编辑,切到它时强制纯编辑视图;
// 源码模式则进入双屏(移动端无双屏,退化为纯编辑),左源码右预览、边写边看。
if (type === `wysiwyg`)
viewMode.value = `edit`
else
viewMode.value = isMobile.value ? `edit` : `split`
}
// 预览设备:desktop(电脑端)| mobile(移动端模拟)
const previewDevice = store.reactive<'desktop' | 'mobile'>(`previewDevice`, `mobile`)
function setPreviewDevice(device: 'desktop' | 'mobile') {
previewDevice.value = device
}
function togglePreviewDevice() {
previewDevice.value = previewDevice.value === `desktop` ? `mobile` : `desktop`
}
// 是否启用图片转存(默认关闭)
const enableImageReupload = store.reactive(addPrefix(`enableImageReupload`), false)
const toggleImageReupload = useToggle(enableImageReupload)
// 是否开启同步滚动(编辑器与预览区联动)
const enableScrollSync = store.reactive(addPrefix(`enableScrollSync`), true)
const toggleScrollSync = useToggle(enableScrollSync)
// ==================== 对话框状态 ====================
// 是否展示 CSS 编辑器
const isShowCssEditor = store.reactive(`isShowCssEditor`, false)
const toggleShowCssEditor = useToggle(isShowCssEditor)
// 是否展示插入表格对话框
const isShowInsertFormDialog = ref(false)
const toggleShowInsertFormDialog = useToggle(isShowInsertFormDialog)
// 是否展示上传图片对话框
const isShowUploadImgDialog = ref(false)
const toggleShowUploadImgDialog = useToggle(isShowUploadImgDialog)
// 是否展示公式编辑对话框
const isShowFormulaEditorDialog = ref(false)
const formulaEditorValue = ref(``)
const formulaEditorDisplayMode = ref(true)
const formulaEditorSourceRaw = ref<string | null>(null)
function openFormulaEditor(options: {
value?: string
displayMode?: boolean
sourceRaw?: string | null
} = {}) {
formulaEditorValue.value = options.value ?? ``
formulaEditorDisplayMode.value = options.displayMode ?? true
formulaEditorSourceRaw.value = options.sourceRaw ?? null
isShowFormulaEditorDialog.value = true
}
function closeFormulaEditor() {
isShowFormulaEditorDialog.value = false
formulaEditorValue.value = ``
formulaEditorDisplayMode.value = true
formulaEditorSourceRaw.value = null
}
// 是否展示导入 Markdown 对话框
const isShowImportMdDialog = ref(false)
const toggleShowImportMdDialog = useToggle(isShowImportMdDialog)
/** 通过 URL 参数 open 打开时传入的待导入链接,对话框打开后会据此自动执行导入 */
const importMdOpenUrl = ref<string | null>(null)
// 是否展示本地图片上传对话框
const isShowLocalImageUpload = ref(false)
const toggleShowLocalImageUpload = useToggle(isShowLocalImageUpload)
/** 待处理的本地图片上传数据 */
const localImageUploadData = ref<{
markdownContent: string
detectedPaths: string[]
processed?: boolean
skipUpload?: boolean
successCount?: number
failCount?: number
} | null>(null)
// 是否展示模板管理对话框
const isShowTemplateDialog = ref(false)
const toggleShowTemplateDialog = useToggle(isShowTemplateDialog)
// 是否展示组件对话框
const isShowComponentDialog = ref(false)
const toggleShowComponentDialog = useToggle(isShowComponentDialog)
// 是否展示云同步对话框
const isShowSyncDialog = ref(false)
const toggleShowSyncDialog = useToggle(isShowSyncDialog)
// 是否展示账户对话框
const isShowAccountDialog = ref(false)
const toggleShowAccountDialog = useToggle(isShowAccountDialog)
// 组件对话框 — 打开时预展开的组件名(如 'MpProfile')
const componentDialogTarget = ref<string | null>(null)
function openComponentDialogWithTarget(target: string) {
componentDialogTarget.value = target
isShowComponentDialog.value = true
}
// AI 对话框
const aiDialogVisible = ref(false)
const aiImageDialogVisible = ref(false)
function toggleAIDialog(value?: boolean) {
aiDialogVisible.value = value ?? !aiDialogVisible.value
}
function toggleAIImageDialog(value?: boolean) {
aiImageDialogVisible.value = value ?? !aiImageDialogVisible.value
}
// 搜索面板状态
const searchTabRequest = ref<{ word: string, showReplace: boolean } | null>(null)
function openSearchTab(searchWord: string = '', showReplace: boolean = false) {
searchTabRequest.value = { word: searchWord, showReplace }
}
function clearSearchTabRequest() {
searchTabRequest.value = null
}
// ==================== 工具函数 ====================
// 处理窗口大小变化
let splitCollapsedByResize = false
function handleResize() {
const wasMobile = isMobile.value
isMobile.value = window.innerWidth <= 768
if (!wasMobile && isMobile.value && viewMode.value === `split`) {
// 从桌面端变为移动端且当前是双屏:切换为编辑模式并记录
viewMode.value = `edit`
splitCollapsedByResize = true
}
else if (wasMobile && !isMobile.value && splitCollapsedByResize) {
// 从移动端变回桌面端且是由 resize 触发的折叠:还原为双屏
viewMode.value = `split`
splitCollapsedByResize = false
}
}
onMounted(() => {
handleResize()
window.addEventListener(`resize`, handleResize)
})
onBeforeUnmount(() => {
window.removeEventListener(`resize`, handleResize)
})
return {
// ==================== 全局 UI 状态 ====================
isDark,
isEditOnLeft,
showAIToolbox,
hasShownAIToolboxHint,
isOpenRightSlider,
isOpenPostSlider,
isMobile,
viewMode,
editorType,
previewDevice,
isOpenFolderPanel,
enableImageReupload,
enableScrollSync,
// ==================== 对话框状态 ====================
isShowCssEditor,
toggleShowCssEditor,
isShowInsertFormDialog,
toggleShowInsertFormDialog,
isShowUploadImgDialog,
toggleShowUploadImgDialog,
isShowFormulaEditorDialog,
formulaEditorValue,
formulaEditorDisplayMode,
formulaEditorSourceRaw,
openFormulaEditor,
closeFormulaEditor,
isShowImportMdDialog,
toggleShowImportMdDialog,
importMdOpenUrl,
isShowLocalImageUpload,
toggleShowLocalImageUpload,
localImageUploadData,
isShowTemplateDialog,
toggleShowTemplateDialog,
isShowComponentDialog,
toggleShowComponentDialog,
isShowSyncDialog,
toggleShowSyncDialog,
isShowAccountDialog,
toggleShowAccountDialog,
componentDialogTarget,
openComponentDialogWithTarget,
aiDialogVisible,
toggleAIDialog,
aiImageDialogVisible,
toggleAIImageDialog,
// ==================== 搜索面板 ====================
searchTabRequest,
openSearchTab,
clearSearchTabRequest,
// ==================== Actions ====================
toggleDark,
toggleEditOnLeft,
toggleAIToolbox,
toggleImageReupload,
toggleScrollSync,
setViewMode,
setEditorType,
setPreviewDevice,
togglePreviewDevice,
}
})