artalk 2.6.2 → 2.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,6 +31,8 @@ export default class Editor extends Component {
31
31
  private submitManager?;
32
32
  setSubmitManager(m: SubmitManager): void;
33
33
  getSubmitManager(): SubmitManager | undefined;
34
+ /** 已加载功能的 unmount 函数 */
35
+ private unmountFuncs;
34
36
  constructor(ctx: Context);
35
37
  getHeaderInputEls(): {
36
38
  nick: HTMLInputElement;
@@ -1,2 +1,2 @@
1
1
  import Editor from './editor';
2
- export default function initEditorFuncs(editor: Editor): void;
2
+ export default function initEditorFuncs(editor: Editor): (() => void)[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "artalk",
3
- "version": "2.6.2",
3
+ "version": "2.6.4",
4
4
  "license": "MIT",
5
5
  "description": "A Selfhosted Comment System",
6
6
  "keywords": [
@@ -82,7 +82,9 @@ function cancelEdit(m: EditModeManager) {
82
82
  }
83
83
 
84
84
  function initEditModeSubmit(m: EditModeManager) {
85
- m.editor.getSubmitManager()!.registerCustom({
85
+ const submitManger = m.editor.getSubmitManager()
86
+ if (!submitManger) throw Error("submitManager not initialized")
87
+ submitManger.registerCustom({
86
88
  activeCond: () => !!m.comment, // active this custom submit when edit mode
87
89
  req: async () => {
88
90
  const saveData = {
@@ -43,6 +43,9 @@ export default class Editor extends Component {
43
43
  public setSubmitManager(m: SubmitManager) { this.submitManager = m }
44
44
  public getSubmitManager() { return this.submitManager }
45
45
 
46
+ /** 已加载功能的 unmount 函数 */
47
+ private unmountFuncs: (() => void)[] = []
48
+
46
49
  public constructor(ctx: Context) {
47
50
  super(ctx)
48
51
 
@@ -52,7 +55,12 @@ export default class Editor extends Component {
52
55
 
53
56
  // event listen
54
57
  this.ctx.on('conf-loaded', () => {
55
- initEditorFuncs(this) // init editor funcs
58
+ // call unmount funcs
59
+ // (this will only be called while conf reloaded, not be called at first time)
60
+ this.unmountFuncs?.forEach((unmount) => !!unmount && unmount())
61
+
62
+ // call init will return unmount funcs and save it
63
+ this.unmountFuncs = initEditorFuncs(this) // init editor funcs
56
64
  })
57
65
  }
58
66
 
@@ -170,7 +178,7 @@ export default class Editor extends Component {
170
178
 
171
179
  /** 点击评论提交按钮事件 */
172
180
  public async submit() {
173
- if (!this.submitManager) return
181
+ if (!this.submitManager) throw Error('submitManger not initialized')
174
182
  await this.submitManager.do()
175
183
  }
176
184
 
@@ -6,77 +6,134 @@ import { createReplyManager } from './reply'
6
6
  import { createEditModeManager } from './edit-mode'
7
7
  import { createSubmitManager } from './submit'
8
8
 
9
+ /** Editor Enabled Functions */
9
10
  const EditorFuncs = {
10
- localStorage, header, textarea, submitBtn, submitManager,
11
- plugs, mover, replyManager, editModeManager,
11
+ localStorage, header, textarea,
12
+ submitBtn, submitManager,
13
+ mover, reply,
14
+ plugs,
12
15
  }
13
16
 
14
17
  export default function initEditorFuncs(editor: Editor) {
18
+ // storage the unmount funcs
19
+ const unmountFuncs: (() => void)[] = []
20
+
15
21
  Object.entries(EditorFuncs).forEach(([k, init]) => {
16
- init(editor)
22
+ const unmountFunc = init(editor)
23
+ if (unmountFunc) unmountFuncs.push(unmountFunc)
17
24
  })
25
+
26
+ return unmountFuncs
18
27
  }
19
28
 
20
29
  // ================== Editor Functions ======================
21
30
 
22
31
  function localStorage(editor: Editor) {
32
+ // load editor content from localStorage when init
23
33
  const localContent = window.localStorage.getItem('ArtalkContent') || ''
24
34
  if (localContent.trim() !== '') {
25
35
  editor.showNotify(editor.$t('restoredMsg'), 'i')
26
36
  editor.setContent(localContent)
27
37
  }
28
38
 
29
- editor.getUI().$textarea.addEventListener('input', () => (editor.saveToLocalStorage()))
39
+ // save editor content to localStorage when input
40
+ const onEditorInput = () => {
41
+ editor.saveToLocalStorage()
42
+ }
43
+
44
+ // bind the event
45
+ editor.getUI().$textarea.addEventListener('input', onEditorInput)
46
+
47
+ return () => {
48
+ // unmount the event
49
+ editor.getUI().$textarea.removeEventListener('input', onEditorInput)
50
+ }
30
51
  }
31
52
 
32
53
  function header(editor: Editor) {
33
54
  const $inputs = editor.getHeaderInputEls()
34
- Object.entries($inputs).forEach(([key, $input]) => {
35
- $input.value = User.data[key] || ''
36
- $input.addEventListener('input', () => onHeaderInput(editor, key, $input))
55
+ const inputFuncs: {[name: string]: () => void} = {}
56
+
57
+ // the input event
58
+ const onInput = ($input: HTMLInputElement, key: string) => () => {
59
+ if (editor.isEditMode) return // 评论编辑模式,不修改个人信息
60
+
61
+ User.update({ [key]: $input.value.trim() })
62
+ editor.getPlugs()?.triggerHeaderInputEvt(key, $input)
63
+ }
37
64
 
38
- // 设置 Placeholder
65
+ // set placeholder and sync header input value
66
+ Object.entries($inputs).forEach(([key, $input]) => {
39
67
  $input.placeholder = `${editor.$t(key as any)}`
68
+ $input.value = User.data[key] || ''
40
69
  })
41
- }
42
70
 
43
- function onHeaderInput(editor: Editor, field: string, $input: HTMLInputElement) {
44
- if (editor.isEditMode) return // 评论编辑模式,不修改个人信息
45
-
46
- User.update({
47
- [field]: $input.value.trim()
71
+ // bind the event
72
+ Object.entries($inputs).forEach(([key, $input]) => {
73
+ $input.addEventListener('input', inputFuncs[key] = onInput($input, key))
48
74
  })
49
75
 
50
- editor.getPlugs()?.triggerHeaderInputEvt(field, $input)
76
+ return () => {
77
+ // unmount the event
78
+ Object.entries($inputs).forEach(([key, $input]) => {
79
+ $input.removeEventListener('input', inputFuncs[key])
80
+ })
81
+ }
51
82
  }
52
83
 
53
84
  function textarea(editor: Editor) {
54
85
  // 占位符
55
86
  editor.getUI().$textarea.placeholder = editor.ctx.conf.placeholder || editor.$t('placeholder')
56
87
 
57
- // 修复按下 Tab 输入的内容
58
- editor.getUI().$textarea.addEventListener('keydown', (e) => {
88
+ // 按下 Tab 输入内容,而不是失去焦距
89
+ const onKeydown = (e: KeyboardEvent) => {
59
90
  const keyCode = e.keyCode || e.which
60
91
 
61
92
  if (keyCode === 9) {
62
93
  e.preventDefault()
63
94
  editor.insertContent('\t')
64
95
  }
65
- })
96
+ }
66
97
 
67
98
  // 输入框高度随内容而变化
68
- editor.getUI().$textarea.addEventListener('input', () => {
99
+ const onInput = () => {
69
100
  editor.adjustTextareaHeight()
70
- })
101
+ }
102
+
103
+ // bind the event
104
+ editor.getUI().$textarea.addEventListener('keydown', onKeydown)
105
+ editor.getUI().$textarea.addEventListener('input', onInput)
106
+
107
+ return () => {
108
+ // unmount the event
109
+ editor.getUI().$textarea.removeEventListener('keydown', onKeydown)
110
+ editor.getUI().$textarea.removeEventListener('input', onInput)
111
+ }
71
112
  }
72
113
 
73
114
  function submitBtn(editor: Editor) {
74
115
  editor.refreshSendBtnText()
75
- editor.getUI().$submitBtn.addEventListener('click', () => (editor.submit()))
116
+
117
+ const onClick = () => {
118
+ editor.submit()
119
+ }
120
+
121
+ editor.getUI().$submitBtn.addEventListener('click', onClick)
122
+
123
+ return () => {
124
+ editor.getUI().$submitBtn.removeEventListener('click', onClick)
125
+ }
76
126
  }
77
127
 
78
- function plugs(editor: Editor) {
79
- editor.setPlugs(createPlugManager(editor))
128
+ function submitManager(editor: Editor) {
129
+ editor.setSubmitManager(createSubmitManager(editor))
130
+
131
+ // Note:
132
+ // the EditModeManger depends on the submitManager,
133
+ // so must init the submitManager first.
134
+ // createEditModeManager will make a side-effect on submitManager (call `submitManger.registerCustom`)
135
+ // side-effect is not a good practice, to be improved.
136
+ editor.setEditModeManager(createEditModeManager(editor))
80
137
  }
81
138
 
82
139
  function mover(editor: Editor) {
@@ -84,14 +141,10 @@ function mover(editor: Editor) {
84
141
  editor.setMover(createMover(editor))
85
142
  }
86
143
 
87
- function replyManager(editor: Editor) {
144
+ function reply(editor: Editor) {
88
145
  editor.setReplyManager(createReplyManager(editor))
89
146
  }
90
147
 
91
- function editModeManager(editor: Editor) {
92
- editor.setEditModeManager(createEditModeManager(editor))
93
- }
94
-
95
- function submitManager(editor: Editor) {
96
- editor.setSubmitManager(createSubmitManager(editor))
148
+ function plugs(editor: Editor) {
149
+ editor.setPlugs(createPlugManager(editor))
97
150
  }
@@ -37,7 +37,7 @@ export function createPlugManager(editor: Editor): PlugManager {
37
37
  getTransformedContent: (r) => getTransformedContent(ctx, r),
38
38
  }
39
39
 
40
- // handle ui
40
+ // handle ui, clear and reset the plug btns and plug panels
41
41
  editor.getUI().$plugPanelWrap.innerHTML = ''
42
42
  editor.getUI().$plugPanelWrap.style.display = 'none'
43
43
  editor.getUI().$plugBtnWrap.innerHTML = ''
@@ -132,14 +132,10 @@
132
132
  }
133
133
 
134
134
  & > .atk-list-footer {
135
- z-index: 1;
136
- position: absolute;
137
- bottom: 5px;
138
- right: 0;
135
+ float: right;
139
136
 
140
137
  @media only screen and (max-width: 768px) {
141
- position: relative;
142
- margin-top: 10px;
138
+ float: initial;
143
139
  text-align: center;
144
140
  }
145
141
 
@@ -148,7 +144,6 @@
148
144
  font-size: 12px;
149
145
  color: var(--at-color-meta);
150
146
  padding-right: 15px;
151
- margin-top: 5px;
152
147
 
153
148
  a {
154
149
  color: var(--at-color-main);