@@ -13,13 +13,23 @@ const store = mainStore()
13
13
const text = ref <any >(null )
14
14
const settings = ref (false )
15
15
const themeColor = ref (0 )
16
- const toolbar = ref <any >(null )
17
16
const shortcutModal = ref (false )
18
17
const exportModal_1 = ref (false )
19
18
const exportModal_2 = ref (false )
19
+ const spellcheck = ref (true )
20
20
const exitModal = ref (false )
21
+ const showOptions = ref (false )
21
22
const message = useMessage ()
22
23
24
+ const checkContent = () => {
25
+ if (store .content .ops .ops ) {
26
+ if (store .content .ops .ops [0 ].insert !== (' \n ' || ' ' )) {
27
+ return true
28
+ }
29
+ }
30
+ return false
31
+ }
32
+
23
33
const shortcutRegister = async () => {
24
34
if (! (await isRegistered (' ctrl+shift+s' ))) {
25
35
await register (' ctrl+shift+s' , () => {
@@ -33,12 +43,6 @@ const shortcutUnregister = async () => {
33
43
shortcutModal .value = false
34
44
}
35
45
36
- const themeOverrides = {
37
- common: {
38
- primaryColor: ' #8a8a8a'
39
- }
40
- }
41
-
42
46
const changeTheme = () => {
43
47
themeColor .value = store .theme === ' dark' ? 255 : 0
44
48
store .theme = store .theme === ' dark' ? ' light' : ' dark'
@@ -51,26 +55,31 @@ const changeAlwaysTop = () => {
51
55
52
56
const export2PDF = async () => {
53
57
try {
54
- const pdfBlob = await pdfExporter .generatePdf (store .content .ops )
55
- saveAs (pdfBlob , ` ${store .exportName }.pdf ` )
56
- exportModal_1 .value = false
58
+ if (checkContent ()) {
59
+ const pdfBlob = await pdfExporter .generatePdf (store .content .ops )
60
+ saveAs (pdfBlob , ` ${store .exportName }.pdf ` )
61
+ } else {
62
+ message .error (' PDF export failed, file is empty' )
63
+ }
57
64
} catch (e ) {
58
- message .error (' PDF export failed, file is empty ' )
65
+ message .error (' PDF export failed, unknown error ' )
59
66
}
60
67
}
61
68
62
69
const export2Word = async () => {
63
70
try {
64
- const wordBlob: any = await wordExporter .generateWord (store .content .ops , {exportAs: ' blob' })
65
- saveAs (wordBlob , ` ${store .exportName }.docx ` )
66
- exportModal_2 .value = false
71
+ if (checkContent ()) {
72
+ const wordBlob: any = await wordExporter .generateWord (store .content .ops , {exportAs: ' blob' })
73
+ saveAs (wordBlob , ` ${store .exportName }.docx ` )
74
+ } else {
75
+ message .error (' Word export failed, file is empty' )
76
+ }
67
77
} catch (e ) {
68
- message .error (' Word export failed, file is empty ' )
78
+ message .error (' Word export failed, unknown error ' )
69
79
}
70
80
}
71
81
72
82
onMounted (() => {
73
- toolbar .value .style .backgroundColor = ` rgba(255, 255, 255, 0.95) `
74
83
text .value .style .backgroundColor = store .theme === ' dark' ? ` rgba(0, 0, 0, ${store .opacity / 100 }) ` : ` rgba(255, 255, 255, ${store .opacity / 100 }) `
75
84
appWindow .setAlwaysOnTop (store .alwaysTop )
76
85
})
@@ -88,107 +97,67 @@ appWindow.listen("tauri://focus", () => {
88
97
})
89
98
90
99
appWindow .listen (" tauri://close-requested" , async () => {
91
- if (store .content .ops .ops ) {
92
- if (store .content .ops .ops [0 ].insert !== (' \n ' || ' ' )) {
93
- exitModal .value = true
94
- return
95
- }
100
+ if (checkContent ()) {
101
+ exitModal .value = true
102
+ } else {
103
+ await appWindow .close ()
96
104
}
97
- await appWindow .close ()
98
- })
99
-
100
- watch (() => store .content .ops , () => {
101
- console .log (store .content .ops )
102
- console .log (store .content .ops .ops .length )
103
- console .log (store .content .ops .ops [0 ].insert .toString ())
104
105
})
105
106
106
107
await shortcutRegister ()
107
108
</script >
108
109
109
110
<template >
110
- <div id =" toolbar" ref =" toolbar" @click =" settings = false" >
111
- <select class =" ql-font" ></select >
112
- <select class =" ql-size" >
113
- <option value =" small" ></option >
114
- <option selected ></option >
115
- <option value =" large" ></option >
116
- <option value =" huge" ></option >
117
- </select >
118
- <button class =" ql-bold" ></button >
119
- <button class =" ql-italic" ></button >
120
- <button class =" ql-underline" ></button >
121
- <button class =" ql-strike" ></button >
122
- <button class =" ql-blockquote" ></button >
123
- <select class =" ql-color" ></select >
124
- <select class =" ql-background" ></select >
125
- <button class =" ql-code-block" ></button >
126
- <select class =" ql-header" >
127
- <option value =" 1" ></option >
128
- <option value =" 2" ></option >
129
- <option value =" 3" ></option >
130
- <option value =" 4" ></option >
131
- <option value =" 5" ></option >
132
- </select >
133
- <button class =" ql-list" value =" ordered" ></button >
134
- <button class =" ql-list" value =" bullet" ></button >
135
- <button class =" ql-script" value =" sub" ></button >
136
- <button class =" ql-script" value =" super" ></button >
137
- <button class =" ql-indent" value =" -1" ></button >
138
- <button class =" ql-indent" value =" +1" ></button >
139
- <button class =" ql-direction" value =" rtl" ></button >
140
- <select class =" ql-align" >
141
- <option selected ></option >
142
- <option value =" center" ></option >
143
- <option value =" right" ></option >
144
- <option value =" justify" ></option >
145
- </select >
146
- <button class =" ql-image" ></button >
147
- <button class =" ql-video" ></button >
148
- <button class =" ql-link" ></button >
149
- <button class =" ql-clean" ></button >
150
- <button ><i-mdi:file-pdf @click =" exportModal_1 = true" ></i-mdi:file-pdf ></button >
151
- <button ><i-grommet-icons:document-word @click =" exportModal_2 = true" ></i-grommet-icons:document-word ></button >
152
- </div >
153
- <div
154
- :class =" {
155
- 'dark': store.theme === 'dark',
156
- }"
157
- >
111
+ <Toolbar
112
+ @settingsClicked =" settings = false"
113
+ @exportPDF =" exportModal_1 = true"
114
+ @exportWord =" exportModal_2 = true"
115
+ @changeSpellcheck =" spellcheck = !spellcheck"
116
+ />
117
+ <div :class =" { 'dark': store.theme === 'dark' }" >
158
118
<div v-show =" settings" class =" absolute z-10 w-8/10 h-20px bottom-100px transform translate-x-5vh" >
159
119
<n-h2 class =" text-dark-900 dark:text-light-50" >Opacity</n-h2 >
160
- <n-slider :theme-overrides =" themeOverrides" v-model:value =" store.opacity" :step =" 1" ></n-slider >
120
+ <n-slider :theme-overrides =" store. themeOverrides" v-model:value =" store.opacity" :step =" 1" ></n-slider >
161
121
</div >
162
- <n-tooltip placement =" top-start" trigger =" hover" >
163
- <template #trigger >
164
- <i-mdi:arrow-top-left-thin-circle-outline
165
- class =" fixed z-10 right-10px bottom-135px text-size-35px transition-colors duration-150 ease-linear"
166
- :class =" {
167
- 'text-green-500': store.alwaysTop,
168
- 'text-dark-900': !store.alwaysTop,
169
- 'dark:text-light-50': !store.alwaysTop,
170
- 'dark:text-green-500': store.alwaysTop
171
- }"
172
- @click =" changeAlwaysTop()"
122
+ <div
123
+ :class =" {
124
+ 'opacity-100': showOptions,
125
+ 'opacity-0': !showOptions
126
+ }"
127
+ class =" fixed bottom-0 right-0 z-10 w-[64px] h-[185px]"
128
+ @mouseleave =" showOptions = false"
129
+ >
130
+ <Transition name =" option" >
131
+ <Options
132
+ v-if =" showOptions"
133
+ @change-settings =" settings = !settings"
134
+ @change-theme =" changeTheme()"
135
+ @change-alwaystop =" changeAlwaysTop()"
173
136
/>
174
- </template >
175
- Always-on-top
176
- </n-tooltip >
177
- <n-tooltip placement =" top-start" trigger =" hover" >
178
- <template #trigger >
179
- <i-mdi:theme-light-dark class =" fixed z-10 right-10px bottom-75px text-size-35px text-dark-900 dark:text-light-50 transition-colors duration-150 ease-linear" @click =" changeTheme()" />
180
- </template >
181
- Theme
182
- </n-tooltip >
183
- <n-tooltip placement =" top-start" trigger =" hover" >
184
- <template #trigger >
185
- <i-ri:settings-3-line class =" fixed z-10 right-10px bottom-15px text-size-35px text-dark-900 dark:text-light-50 transition-colors duration-150 ease-linear" @click =" settings = !settings" />
186
- </template >
187
- Settings
188
- </n-tooltip >
137
+ </Transition >
138
+ </div >
139
+ <HoverCorner v-if =" !showOptions" color =" #10b981" class =" fixed z-15 right-0 bottom-0" @mouseenter =" showOptions = true" />
189
140
<div ref =" text" class =" relative h-100vh text-dark-900 dark:text-light-50 transition-colors duration-150 ease-linear" @click =" settings = false" >
190
- <QuillEditor toolbar =" #toolbar" spellcheck =" false" v-model:content =" store.content.ops" ></QuillEditor >
141
+ <QuillEditor
142
+ name =" content"
143
+ id =" content"
144
+ toolbar =" #toolbar"
145
+ :spellcheck =" spellcheck"
146
+ v-model:content =" store.content.ops"
147
+ />
191
148
</div >
149
+ <exportModal
150
+ type =" pdf"
151
+ :func =" export2PDF"
152
+ :show =" exportModal_1"
153
+ @close =" exportModal_1 = false"
154
+ />
155
+ <exportModal
156
+ type =" word"
157
+ :func =" export2Word"
158
+ :show =" exportModal_2"
159
+ @close =" exportModal_2 = false"
160
+ />
192
161
<n-modal
193
162
class =" mx-30vw"
194
163
v-model:show =" shortcutModal"
@@ -198,32 +167,8 @@ await shortcutRegister()
198
167
>
199
168
<n-input type =" text" v-model:value =" store.exportName" ></n-input >
200
169
<div class =" text-size-[30px] flex justify-end p-2" >
201
- <button :theme-overridess =" themeOverrides" ><i-mdi:file-pdf class =" m-[0.7rem]" @click =" export2PDF()" ></i-mdi:file-pdf ></button >
202
- <button :theme-overridess =" themeOverrides" ><i-mdi:file-word class =" m-[0.7rem]" @click =" export2Word()" ></i-mdi:file-word ></button >
203
- </div >
204
- </n-modal >
205
- <n-modal
206
- class =" mx-30vw"
207
- v-model:show =" exportModal_1"
208
- :mask-closable =" false"
209
- preset =" card"
210
- title =" Save as"
211
- >
212
- <n-input type =" text" v-model:value =" store.exportName" ></n-input >
213
- <div class =" text-size-[30px] flex justify-end p-2" >
214
- <button :theme-overridess =" themeOverrides" ><i-mdi:file-pdf class =" m-[0.7rem]" @click =" export2PDF()" ></i-mdi:file-pdf ></button >
215
- </div >
216
- </n-modal >
217
- <n-modal
218
- class =" mx-30vw"
219
- v-model:show =" exportModal_2"
220
- :mask-closable =" false"
221
- preset =" card"
222
- title =" Save as"
223
- >
224
- <n-input type =" text" v-model:value =" store.exportName" ></n-input >
225
- <div class =" text-size-[30px] flex justify-end p-2" >
226
- <button :theme-overridess =" themeOverrides" ><i-mdi:file-word class =" m-[0.7rem]" @click =" export2Word()" ></i-mdi:file-word ></button >
170
+ <button :theme-overridess =" store.themeOverrides" ><i-mdi:file-pdf class =" m-[0.7rem]" @click =" export2PDF()" ></i-mdi:file-pdf ></button >
171
+ <button :theme-overridess =" store.themeOverrides" ><i-mdi:file-word class =" m-[0.7rem]" @click =" export2Word()" ></i-mdi:file-word ></button >
227
172
</div >
228
173
</n-modal >
229
174
<n-modal
@@ -252,4 +197,14 @@ html {
252
197
width : 0 ; /* Remove scrollbar space */
253
198
background : transparent ; /* Optional: just make scrollbar invisible */
254
199
}
200
+
201
+ .option-enter-active ,
202
+ .option-leave-active {
203
+ transition : all .3s ease ;
204
+ }
205
+
206
+ .option-enter-from ,
207
+ .option-leave-to {
208
+ opacity : 0 ;
209
+ }
255
210
</style >
0 commit comments