@waline/client 2.14.1 → 2.14.3
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.
- package/dist/api.cjs +1 -1
- package/dist/api.cjs.map +1 -1
- package/dist/api.d.cts +22 -20
- package/dist/api.d.mts +22 -20
- package/dist/api.d.ts +22 -20
- package/dist/api.mjs +1 -1
- package/dist/api.mjs.map +1 -1
- package/dist/comment.cjs +1 -1
- package/dist/comment.cjs.map +1 -1
- package/dist/comment.d.cts +1 -1
- package/dist/comment.d.mts +1 -1
- package/dist/comment.d.ts +1 -1
- package/dist/comment.js +1 -68
- package/dist/comment.js.map +1 -1
- package/dist/comment.mjs +1 -1
- package/dist/comment.mjs.map +1 -1
- package/dist/component.mjs +1 -1
- package/dist/component.mjs.map +1 -1
- package/dist/legacy.umd.d.ts +15 -6
- package/dist/legacy.umd.js +1 -1
- package/dist/legacy.umd.js.map +1 -1
- package/dist/pageview.cjs +1 -1
- package/dist/pageview.cjs.map +1 -1
- package/dist/pageview.d.cts +1 -1
- package/dist/pageview.d.mts +1 -1
- package/dist/pageview.d.ts +1 -1
- package/dist/pageview.js +1 -121
- package/dist/pageview.js.map +1 -1
- package/dist/pageview.mjs +1 -1
- package/dist/pageview.mjs.map +1 -1
- package/dist/shim.cjs +1 -1
- package/dist/shim.cjs.map +1 -1
- package/dist/shim.d.cts +20 -11
- package/dist/shim.d.mts +20 -11
- package/dist/shim.mjs +1 -1
- package/dist/shim.mjs.map +1 -1
- package/dist/waline.cjs +1 -1
- package/dist/waline.cjs.map +1 -1
- package/dist/waline.css +1 -1
- package/dist/waline.css.map +1 -1
- package/dist/waline.d.cts +20 -11
- package/dist/waline.d.mts +20 -11
- package/dist/waline.d.ts +20 -11
- package/dist/waline.js +1 -6787
- package/dist/waline.js.map +1 -1
- package/dist/waline.mjs +1 -1
- package/dist/waline.mjs.map +1 -1
- package/package.json +28 -27
- package/src/api/comment.ts +25 -24
- package/src/comment.ts +3 -4
- package/src/components/ArticleReaction.vue +120 -117
- package/src/components/CommentBox.vue +451 -488
- package/src/components/CommentCard.vue +109 -98
- package/src/components/ImageWall.vue +132 -131
- package/src/components/WalineComment.vue +683 -0
- package/src/composables/index.ts +1 -2
- package/src/composables/reaction.ts +16 -0
- package/src/composables/recaptchaV3.ts +4 -6
- package/src/config/default.ts +6 -1
- package/src/config/i18n/index.ts +1 -0
- package/src/{entrys → entries}/api.ts +0 -0
- package/src/{entrys → entries}/comment.ts +0 -0
- package/src/entries/components.ts +2 -0
- package/src/{entrys → entries}/full.ts +0 -0
- package/src/{entrys → entries}/init.ts +0 -0
- package/src/{entrys → entries}/legacy.ts +0 -0
- package/src/{entrys → entries}/pageview.ts +0 -0
- package/src/init.ts +1 -1
- package/src/pageview.ts +2 -2
- package/src/styles/reaction.scss +27 -16
- package/src/typings/base.ts +5 -0
- package/src/typings/waline.ts +15 -6
- package/src/utils/config.ts +28 -6
- package/src/utils/image.ts +1 -1
- package/src/widgets/recentComments.ts +2 -2
- package/src/widgets/userList.ts +2 -2
- package/LICENSE +0 -339
- package/src/components/Waline.vue +0 -509
- package/src/composables/timeAgo.ts +0 -15
- package/src/composables/vote.ts +0 -20
- package/src/entrys/components.ts +0 -2
|
@@ -1,150 +1,153 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div v-if="
|
|
2
|
+
<div v-if="reactionsInfo.length" class="wl-reaction">
|
|
3
3
|
<h4 v-text="locale.reactionTitle" />
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
<ul class="wl-reaction-list">
|
|
5
6
|
<li
|
|
6
|
-
v-for="(
|
|
7
|
+
v-for="({ active, icon, desc }, index) in reactionsInfo"
|
|
7
8
|
:key="index"
|
|
8
|
-
|
|
9
|
+
class="wl-reaction-item"
|
|
10
|
+
:class="{ active }"
|
|
9
11
|
@click="vote(index)"
|
|
10
12
|
>
|
|
11
13
|
<div class="wl-reaction-img">
|
|
12
|
-
<img :src="
|
|
13
|
-
|
|
14
|
+
<img :src="icon" :alt="desc" />
|
|
15
|
+
|
|
16
|
+
<LoadingIcon
|
|
17
|
+
v-if="votingIndex === index"
|
|
18
|
+
class="wl-reaction-loading"
|
|
19
|
+
/>
|
|
20
|
+
|
|
21
|
+
<div
|
|
22
|
+
v-else
|
|
23
|
+
class="wl-reaction-votes"
|
|
24
|
+
v-text="voteNumbers[index] || 0"
|
|
25
|
+
/>
|
|
14
26
|
</div>
|
|
15
|
-
|
|
27
|
+
|
|
28
|
+
<div class="wl-reaction-text" v-text="desc" />
|
|
16
29
|
</li>
|
|
17
30
|
</ul>
|
|
18
31
|
</div>
|
|
19
32
|
</template>
|
|
20
33
|
|
|
21
|
-
<script lang="ts">
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
import { VOTE_IDENTIFIER, VOTE_INDEX, useVoteStorage } from '../composables';
|
|
34
|
-
import type { WalineConfig } from '../utils';
|
|
35
|
-
import type { WalineLocale } from '../typings';
|
|
34
|
+
<script setup lang="ts">
|
|
35
|
+
import { computed, inject, onMounted, onUnmounted, ref, watch } from 'vue';
|
|
36
|
+
|
|
37
|
+
import { LoadingIcon } from './Icons.js';
|
|
38
|
+
import { getArticleCounter, updateArticleCounter } from '../api/index.js';
|
|
39
|
+
import { useReactionStorage } from '../composables/index.js';
|
|
40
|
+
|
|
41
|
+
import type { ComputedRef } from 'vue';
|
|
42
|
+
import type { WalineConfig } from '../utils/index.js';
|
|
43
|
+
import type { WalineReactionLocale } from '../typings';
|
|
44
|
+
|
|
45
|
+
defineExpose();
|
|
36
46
|
|
|
37
47
|
interface ReactionItem {
|
|
38
48
|
icon: string;
|
|
39
|
-
vote: number;
|
|
40
49
|
desc: string;
|
|
41
50
|
active?: boolean;
|
|
42
51
|
}
|
|
43
52
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
53
|
+
const reactionStorage = useReactionStorage();
|
|
54
|
+
const config = inject<ComputedRef<WalineConfig>>('config')!;
|
|
55
|
+
|
|
56
|
+
const votingIndex = ref(-1);
|
|
57
|
+
const voteNumbers = ref<number[]>([]);
|
|
58
|
+
|
|
59
|
+
const locale = computed(() => config.value.locale);
|
|
60
|
+
const isReactionEnabled = computed(() => config.value.reaction.length > 0);
|
|
61
|
+
|
|
62
|
+
const reactionsInfo = computed<ReactionItem[]>(() => {
|
|
63
|
+
const { reaction, path } = config.value;
|
|
64
|
+
|
|
65
|
+
return reaction.map((icon, index) => ({
|
|
66
|
+
icon,
|
|
67
|
+
desc: locale.value[`reaction${index}` as keyof WalineReactionLocale],
|
|
68
|
+
active: reactionStorage.value[path] === index,
|
|
69
|
+
}));
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
let abort: () => void;
|
|
73
|
+
|
|
74
|
+
const fetchReaction = async (): Promise<void> => {
|
|
75
|
+
if (isReactionEnabled.value) {
|
|
76
|
+
const { serverURL, lang, path, reaction } = config.value;
|
|
77
|
+
const controller = new AbortController();
|
|
78
|
+
|
|
79
|
+
abort = controller.abort.bind(controller);
|
|
80
|
+
|
|
81
|
+
const resp = await getArticleCounter({
|
|
82
|
+
serverURL,
|
|
83
|
+
lang,
|
|
84
|
+
paths: [path],
|
|
85
|
+
type: reaction.map((_reaction, index) => `reaction${index}`),
|
|
86
|
+
signal: controller.signal,
|
|
64
87
|
});
|
|
65
88
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}).then((resp) => {
|
|
81
|
-
if (Array.isArray(resp) || typeof resp === 'number') return;
|
|
82
|
-
votes.value = reaction.map((_, k) => resp[`reaction${k}`]);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
abort = controller.abort.bind(controller);
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const vote = async (index: number): Promise<void> => {
|
|
90
|
-
const { serverURL, lang, path } = config.value;
|
|
91
|
-
const hasVoted = voteStorage.value.find(
|
|
92
|
-
({ [VOTE_IDENTIFIER]: voteIdentifier }) => voteIdentifier === path
|
|
93
|
-
);
|
|
94
|
-
const hasVotedTheReaction = hasVoted && hasVoted[VOTE_INDEX] === index;
|
|
89
|
+
// TODO: Remove this compact code
|
|
90
|
+
if (Array.isArray(resp) || typeof resp === 'number') return;
|
|
91
|
+
|
|
92
|
+
voteNumbers.value = reaction.map(
|
|
93
|
+
(_reaction, index) => resp[`reaction${index}`]
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const vote = async (index: number): Promise<void> => {
|
|
99
|
+
// we should ensure that only one vote request is sent at a time
|
|
100
|
+
if (votingIndex.value === -1) {
|
|
101
|
+
const { serverURL, lang, path } = config.value;
|
|
102
|
+
const currentVoteItemIndex = reactionStorage.value[path];
|
|
95
103
|
|
|
96
|
-
|
|
104
|
+
// mark voting status
|
|
105
|
+
votingIndex.value = index;
|
|
97
106
|
|
|
107
|
+
// if user already vote current article, decrease the voted item number
|
|
108
|
+
if (currentVoteItemIndex !== undefined) {
|
|
98
109
|
await updateArticleCounter({
|
|
99
110
|
serverURL,
|
|
100
111
|
lang,
|
|
101
112
|
path,
|
|
102
|
-
type: `reaction${
|
|
113
|
+
type: `reaction${currentVoteItemIndex}`,
|
|
114
|
+
action: 'desc',
|
|
103
115
|
});
|
|
104
116
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
votes.value[hasVoted[VOTE_INDEX]] - 1,
|
|
109
|
-
0
|
|
110
|
-
);
|
|
111
|
-
updateArticleCounter({
|
|
112
|
-
serverURL,
|
|
113
|
-
lang,
|
|
114
|
-
path,
|
|
115
|
-
type: `reaction${hasVoted.i}`,
|
|
116
|
-
action: 'desc',
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
hasVoted.i = index;
|
|
120
|
-
voteStorage.value = Array.from(voteStorage.value);
|
|
121
|
-
} else {
|
|
122
|
-
voteStorage.value = [
|
|
123
|
-
...voteStorage.value,
|
|
124
|
-
{ [VOTE_IDENTIFIER]: path, [VOTE_INDEX]: index },
|
|
125
|
-
];
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (voteStorage.value.length > 50)
|
|
129
|
-
voteStorage.value = voteStorage.value.slice(-50);
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
onMounted(() => {
|
|
133
|
-
watch(
|
|
134
|
-
() => [config.value.serverURL, config.value.path],
|
|
135
|
-
() => {
|
|
136
|
-
fetchCounter();
|
|
137
|
-
},
|
|
138
|
-
{ immediate: true }
|
|
117
|
+
voteNumbers.value[currentVoteItemIndex] = Math.max(
|
|
118
|
+
voteNumbers.value[currentVoteItemIndex] - 1,
|
|
119
|
+
0
|
|
139
120
|
);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// increase voting number if current reaction item is not been voted
|
|
124
|
+
if (currentVoteItemIndex !== index) {
|
|
125
|
+
await updateArticleCounter({
|
|
126
|
+
serverURL,
|
|
127
|
+
lang,
|
|
128
|
+
path,
|
|
129
|
+
type: `reaction${index}`,
|
|
130
|
+
});
|
|
131
|
+
voteNumbers.value[index] = (voteNumbers.value[index] || 0) + 1;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// update vote info in local storage
|
|
135
|
+
if (currentVoteItemIndex === index) delete reactionStorage.value[path];
|
|
136
|
+
else reactionStorage.value[path] = index;
|
|
137
|
+
|
|
138
|
+
// voting is completed
|
|
139
|
+
votingIndex.value = -1;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
onMounted(() => {
|
|
144
|
+
watch(
|
|
145
|
+
() => [config.value.serverURL, config.value.path],
|
|
146
|
+
() => {
|
|
147
|
+
void fetchReaction();
|
|
148
|
+
},
|
|
149
|
+
{ immediate: true }
|
|
150
|
+
);
|
|
149
151
|
});
|
|
152
|
+
onUnmounted(() => abort?.());
|
|
150
153
|
</script>
|