@waline/client 2.4.2 → 2.5.0
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/component.esm.js +1 -1
- package/dist/component.esm.js.map +1 -1
- package/dist/component.js +1 -1
- package/dist/component.js.map +1 -1
- package/dist/legacy.d.ts +2 -0
- package/dist/legacy.js +1 -1
- package/dist/legacy.js.map +1 -1
- package/dist/pageview.cjs.js +1 -1
- package/dist/pageview.esm.js +1 -1
- package/dist/pageview.js +1 -1
- package/dist/shim.d.ts +2 -0
- package/dist/shim.esm.d.ts +2 -0
- package/dist/shim.esm.js +1 -1
- package/dist/shim.esm.js.map +1 -1
- package/dist/shim.js +1 -1
- package/dist/shim.js.map +1 -1
- package/dist/waline.cjs.d.ts +2 -0
- package/dist/waline.cjs.js +1 -1
- package/dist/waline.cjs.js.map +1 -1
- package/dist/waline.css +1 -1
- package/dist/waline.css.map +1 -1
- package/dist/waline.d.ts +2 -0
- package/dist/waline.esm.d.ts +2 -0
- package/dist/waline.esm.js +1 -1
- package/dist/waline.esm.js.map +1 -1
- package/dist/waline.js +1 -1
- package/dist/waline.js.map +1 -1
- package/package.json +16 -15
- package/src/components/CommentBox.vue +123 -0
- package/src/components/Icons.ts +20 -0
- package/src/config/i18n/en.ts +2 -0
- package/src/config/i18n/generate.ts +2 -0
- package/src/config/i18n/jp.ts +8 -0
- package/src/config/i18n/pt-BR.ts +8 -0
- package/src/config/i18n/ru.ts +8 -0
- package/src/config/i18n/vi-VN.ts +8 -0
- package/src/config/i18n/zh-CN.ts +2 -0
- package/src/config/i18n/zh-TW.ts +2 -0
- package/src/init.ts +7 -2
- package/src/styles/card.scss +1 -0
- package/src/styles/gif.scss +151 -0
- package/src/styles/panel.scss +2 -0
- package/src/typings/locale.ts +2 -0
- package/src/utils/fetchGif.ts +62 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/throttle.ts +16 -0
- package/LICENSE +0 -339
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@waline/client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "client for waline comment system",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"valine",
|
|
@@ -56,6 +56,15 @@
|
|
|
56
56
|
"dist",
|
|
57
57
|
"src"
|
|
58
58
|
],
|
|
59
|
+
"scripts": {
|
|
60
|
+
"build": "pnpm rollup && pnpm style",
|
|
61
|
+
"clean": "rimraf ./dist",
|
|
62
|
+
"dev": "vite -c config/vite.config.js",
|
|
63
|
+
"lint": "eslint --ext .ts,.vue .",
|
|
64
|
+
"prepublish": "pnpm clean && pnpm build",
|
|
65
|
+
"rollup": "rollup -c ./config/rollup.config.js",
|
|
66
|
+
"style": "sass ./src/styles/index.scss ./dist/waline.css --style=compressed"
|
|
67
|
+
},
|
|
59
68
|
"browserslist": {
|
|
60
69
|
"production": [
|
|
61
70
|
">0.5%",
|
|
@@ -85,27 +94,19 @@
|
|
|
85
94
|
"@rollup/plugin-replace": "^4.0.0",
|
|
86
95
|
"@types/autosize": "^4.0.1",
|
|
87
96
|
"@types/marked": "^4.0.3",
|
|
88
|
-
"@types/node": "^17.0.
|
|
89
|
-
"@vitejs/plugin-vue": "^2.3.
|
|
97
|
+
"@types/node": "^17.0.33",
|
|
98
|
+
"@vitejs/plugin-vue": "^2.3.3",
|
|
90
99
|
"@vue/compiler-sfc": "^3.2.33",
|
|
100
|
+
"@yeger/vue-masonry-wall": "^3.0.31",
|
|
91
101
|
"rimraf": "^3.0.2",
|
|
92
|
-
"rollup": "^2.
|
|
102
|
+
"rollup": "^2.73.0",
|
|
93
103
|
"rollup-plugin-dts": "^4.2.1",
|
|
94
104
|
"rollup-plugin-terser": "^7.0.2",
|
|
95
105
|
"rollup-plugin-ts": "^2.0.7",
|
|
96
106
|
"typescript": "^4.6.4",
|
|
97
|
-
"vite": "^2.9.
|
|
107
|
+
"vite": "^2.9.9"
|
|
98
108
|
},
|
|
99
109
|
"engines": {
|
|
100
110
|
"node": ">=14"
|
|
101
|
-
},
|
|
102
|
-
"scripts": {
|
|
103
|
-
"build": "pnpm rollup && pnpm style",
|
|
104
|
-
"clean": "rimraf ./dist",
|
|
105
|
-
"dev": "vite -c config/vite.config.js",
|
|
106
|
-
"lint": "eslint --ext .ts,.vue .",
|
|
107
|
-
"prepublish": "pnpm clean && pnpm build",
|
|
108
|
-
"rollup": "rollup -c ./config/rollup.config.js",
|
|
109
|
-
"style": "sass ./src/styles/index.scss ./dist/waline.css --style=compressed"
|
|
110
111
|
}
|
|
111
|
-
}
|
|
112
|
+
}
|
|
@@ -88,6 +88,16 @@
|
|
|
88
88
|
<EmojiIcon />
|
|
89
89
|
</button>
|
|
90
90
|
|
|
91
|
+
<button
|
|
92
|
+
ref="gifButtonRef"
|
|
93
|
+
class="wl-action"
|
|
94
|
+
:class="{ actived: showGif }"
|
|
95
|
+
:title="locale.gif"
|
|
96
|
+
@click="showGif = !showGif"
|
|
97
|
+
>
|
|
98
|
+
<GifIcon />
|
|
99
|
+
</button>
|
|
100
|
+
|
|
91
101
|
<input
|
|
92
102
|
ref="imageUploadRef"
|
|
93
103
|
class="upload"
|
|
@@ -152,6 +162,47 @@
|
|
|
152
162
|
</button>
|
|
153
163
|
</div>
|
|
154
164
|
|
|
165
|
+
<div
|
|
166
|
+
ref="gifPopupRef"
|
|
167
|
+
class="wl-gif-popup"
|
|
168
|
+
:class="{ display: showGif }"
|
|
169
|
+
>
|
|
170
|
+
<input
|
|
171
|
+
type="text"
|
|
172
|
+
:placeholder="locale.gifSearchPlaceholder"
|
|
173
|
+
ref="gifSearchInputRef"
|
|
174
|
+
@input="onGifSearch"
|
|
175
|
+
/>
|
|
176
|
+
|
|
177
|
+
<masonry-wall
|
|
178
|
+
class="wl-gif-waterfall"
|
|
179
|
+
:items="gifData.list"
|
|
180
|
+
:ssr-columns="2"
|
|
181
|
+
:column-width="200"
|
|
182
|
+
:gap="6"
|
|
183
|
+
@scroll="onGifMasonryScroll"
|
|
184
|
+
>
|
|
185
|
+
<template #default="{ item }">
|
|
186
|
+
<img
|
|
187
|
+
@click="insert(``)"
|
|
188
|
+
:src="item.media[0].tinygif.url"
|
|
189
|
+
:title="item.title"
|
|
190
|
+
loading="lazy"
|
|
191
|
+
:style="{
|
|
192
|
+
width: '200px',
|
|
193
|
+
height:
|
|
194
|
+
(200 * item.media[0].tinygif.dims[1]) /
|
|
195
|
+
item.media[0].tinygif.dims[0] +
|
|
196
|
+
'px',
|
|
197
|
+
}"
|
|
198
|
+
/>
|
|
199
|
+
</template>
|
|
200
|
+
</masonry-wall>
|
|
201
|
+
|
|
202
|
+
<div v-if="gifData.loading" class="wl-loading">
|
|
203
|
+
<LoadingIcon :size="30" />
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
155
206
|
<div
|
|
156
207
|
ref="emojiPopupRef"
|
|
157
208
|
class="wl-emoji-popup"
|
|
@@ -228,6 +279,7 @@ import {
|
|
|
228
279
|
MarkdownIcon,
|
|
229
280
|
PreviewIcon,
|
|
230
281
|
LoadingIcon,
|
|
282
|
+
GifIcon,
|
|
231
283
|
} from './Icons';
|
|
232
284
|
import { useEditor, useUserMeta, useUserInfo } from '../composables';
|
|
233
285
|
import {
|
|
@@ -237,6 +289,9 @@ import {
|
|
|
237
289
|
parseEmoji,
|
|
238
290
|
postComment,
|
|
239
291
|
getEmojis,
|
|
292
|
+
fetchGif,
|
|
293
|
+
FetchGifResponse,
|
|
294
|
+
throttle,
|
|
240
295
|
} from '../utils';
|
|
241
296
|
|
|
242
297
|
import type { ComputedRef, DeepReadonly } from 'vue';
|
|
@@ -253,6 +308,7 @@ export default defineComponent({
|
|
|
253
308
|
MarkdownIcon,
|
|
254
309
|
PreviewIcon,
|
|
255
310
|
LoadingIcon,
|
|
311
|
+
GifIcon,
|
|
256
312
|
},
|
|
257
313
|
|
|
258
314
|
props: {
|
|
@@ -286,13 +342,22 @@ export default defineComponent({
|
|
|
286
342
|
const imageUploadRef = ref<HTMLInputElement | null>(null);
|
|
287
343
|
const emojiButtonRef = ref<HTMLDivElement | null>(null);
|
|
288
344
|
const emojiPopupRef = ref<HTMLDivElement | null>(null);
|
|
345
|
+
const gifButtonRef = ref<HTMLDivElement | null>(null);
|
|
346
|
+
const gifPopupRef = ref<HTMLDivElement | null>(null);
|
|
347
|
+
const gifSearchInputRef = ref<HTMLInputElement | null>(null);
|
|
289
348
|
|
|
290
349
|
const emoji = ref<DeepReadonly<WalineEmojiConfig>>({ tabs: [], map: {} });
|
|
291
350
|
const emojiTabIndex = ref(0);
|
|
292
351
|
const showEmoji = ref(false);
|
|
352
|
+
const showGif = ref(false);
|
|
293
353
|
const showPreview = ref(false);
|
|
294
354
|
const previewText = ref('');
|
|
295
355
|
const wordNumber = ref(0);
|
|
356
|
+
const gifData = ref<{
|
|
357
|
+
cursor: string;
|
|
358
|
+
loading: boolean;
|
|
359
|
+
list: FetchGifResponse['results'];
|
|
360
|
+
}>({ cursor: '', loading: true, list: [] });
|
|
296
361
|
|
|
297
362
|
const wordLimit = ref(0);
|
|
298
363
|
const isWordNumberLegal = ref(false);
|
|
@@ -548,6 +613,41 @@ export default defineComponent({
|
|
|
548
613
|
!(emojiPopupRef.value as HTMLElement).contains(event.target as Node)
|
|
549
614
|
)
|
|
550
615
|
showEmoji.value = false;
|
|
616
|
+
|
|
617
|
+
if (
|
|
618
|
+
!(gifButtonRef.value as HTMLElement).contains(event.target as Node) &&
|
|
619
|
+
!(gifPopupRef.value as HTMLElement).contains(event.target as Node)
|
|
620
|
+
)
|
|
621
|
+
showGif.value = false;
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
const onGifSearch = throttle(async (event: Event) => {
|
|
625
|
+
gifData.value.cursor = '';
|
|
626
|
+
gifData.value.list = [];
|
|
627
|
+
onGifMasonryScroll(event);
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
const onGifMasonryScroll = async (event: Event): Promise<void> => {
|
|
631
|
+
const { scrollTop, clientHeight, scrollHeight } =
|
|
632
|
+
event.target as HTMLDivElement;
|
|
633
|
+
const percent = (clientHeight + scrollTop) / scrollHeight;
|
|
634
|
+
if (percent < 0.9 || gifData.value.loading) {
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
gifData.value.loading = true;
|
|
639
|
+
const data = await fetchGif({
|
|
640
|
+
keyword: gifSearchInputRef.value?.value || '',
|
|
641
|
+
pos: gifData.value.cursor,
|
|
642
|
+
}).finally(() => {
|
|
643
|
+
gifData.value.loading = false;
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
gifData.value.cursor = data.next;
|
|
647
|
+
gifData.value.list = gifData.value.list.concat(data.results);
|
|
648
|
+
setTimeout(() => {
|
|
649
|
+
(event.target as HTMLDivElement).scrollTop = scrollTop;
|
|
650
|
+
}, 50);
|
|
551
651
|
};
|
|
552
652
|
|
|
553
653
|
// update wordNumber
|
|
@@ -575,6 +675,20 @@ export default defineComponent({
|
|
|
575
675
|
{ immediate: true }
|
|
576
676
|
);
|
|
577
677
|
|
|
678
|
+
watch([showGif], async ([showGif]) => {
|
|
679
|
+
if (!showGif) {
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
gifData.value.loading = true;
|
|
684
|
+
const data = await fetchGif({ keyword: '' }).finally(() => {
|
|
685
|
+
gifData.value.loading = false;
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
gifData.value.cursor = data.next;
|
|
689
|
+
gifData.value.list = gifData.value.list.concat(data.results);
|
|
690
|
+
});
|
|
691
|
+
|
|
578
692
|
onMounted(() => {
|
|
579
693
|
document.body.addEventListener('click', popupHandler);
|
|
580
694
|
|
|
@@ -632,6 +746,8 @@ export default defineComponent({
|
|
|
632
746
|
onLogout,
|
|
633
747
|
onProfile,
|
|
634
748
|
submitComment,
|
|
749
|
+
onGifMasonryScroll,
|
|
750
|
+
onGifSearch,
|
|
635
751
|
|
|
636
752
|
isLogin,
|
|
637
753
|
userInfo,
|
|
@@ -651,6 +767,9 @@ export default defineComponent({
|
|
|
651
767
|
emojiTabIndex,
|
|
652
768
|
showEmoji,
|
|
653
769
|
|
|
770
|
+
// gif
|
|
771
|
+
showGif,
|
|
772
|
+
|
|
654
773
|
// image
|
|
655
774
|
canUploadImage,
|
|
656
775
|
|
|
@@ -663,7 +782,11 @@ export default defineComponent({
|
|
|
663
782
|
editorRef,
|
|
664
783
|
emojiButtonRef,
|
|
665
784
|
emojiPopupRef,
|
|
785
|
+
gifButtonRef,
|
|
786
|
+
gifPopupRef,
|
|
666
787
|
imageUploadRef,
|
|
788
|
+
gifSearchInputRef,
|
|
789
|
+
gifData,
|
|
667
790
|
};
|
|
668
791
|
},
|
|
669
792
|
});
|
package/src/components/Icons.ts
CHANGED
|
@@ -148,3 +148,23 @@ export const LoadingIcon: FunctionalComponent<{ size: number }> = ({ size }) =>
|
|
|
148
148
|
})
|
|
149
149
|
)
|
|
150
150
|
);
|
|
151
|
+
|
|
152
|
+
export const GifIcon: FunctionalComponent = () =>
|
|
153
|
+
h(
|
|
154
|
+
'svg',
|
|
155
|
+
{
|
|
156
|
+
width: 24,
|
|
157
|
+
height: 24,
|
|
158
|
+
fill: 'currentcolor',
|
|
159
|
+
viewBox: '0 0 24 24',
|
|
160
|
+
},
|
|
161
|
+
[
|
|
162
|
+
h('path', {
|
|
163
|
+
style: 'transform: translateY(0.5px)',
|
|
164
|
+
d: 'M18.968 10.5H15.968V11.484H17.984V12.984H15.968V15H14.468V9H18.968V10.5V10.5ZM8.984 9C9.26533 9 9.49967 9.09367 9.687 9.281C9.87433 9.46833 9.968 9.70267 9.968 9.984V10.5H6.499V13.5H8.468V12H9.968V14.016C9.968 14.2973 9.87433 14.5317 9.687 14.719C9.49967 14.9063 9.26533 15 8.984 15H5.984C5.70267 15 5.46833 14.9063 5.281 14.719C5.09367 14.5317 5 14.2973 5 14.016V9.985C5 9.70367 5.09367 9.46933 5.281 9.282C5.46833 9.09467 5.70267 9.001 5.984 9.001H8.984V9ZM11.468 9H12.968V15H11.468V9V9Z',
|
|
165
|
+
}),
|
|
166
|
+
h('path', {
|
|
167
|
+
d: 'M18.5 3H5.75C3.6875 3 2 4.6875 2 6.75V18C2 20.0625 3.6875 21.75 5.75 21.75H18.5C20.5625 21.75 22.25 20.0625 22.25 18V6.75C22.25 4.6875 20.5625 3 18.5 3ZM20.75 18C20.75 19.2375 19.7375 20.25 18.5 20.25H5.75C4.5125 20.25 3.5 19.2375 3.5 18V6.75C3.5 5.5125 4.5125 4.5 5.75 4.5H18.5C19.7375 4.5 20.75 5.5125 20.75 6.75V18Z',
|
|
168
|
+
}),
|
|
169
|
+
]
|
|
170
|
+
);
|
package/src/config/i18n/en.ts
CHANGED
package/src/config/i18n/jp.ts
CHANGED
package/src/config/i18n/pt-BR.ts
CHANGED
|
@@ -33,4 +33,12 @@ export default generateLocale([
|
|
|
33
33
|
'Palavras',
|
|
34
34
|
'Favor enviar comentário com $0 a $1 palavras!\n Número de palavras atuais: $2',
|
|
35
35
|
'Anônimo',
|
|
36
|
+
'Dwarves',
|
|
37
|
+
'Hobbits',
|
|
38
|
+
'Ents',
|
|
39
|
+
'Wizards',
|
|
40
|
+
'Elves',
|
|
41
|
+
'Maiar',
|
|
42
|
+
'GIF',
|
|
43
|
+
'Pesquisar GIF',
|
|
36
44
|
]);
|
package/src/config/i18n/ru.ts
CHANGED
package/src/config/i18n/vi-VN.ts
CHANGED
package/src/config/i18n/zh-CN.ts
CHANGED
package/src/config/i18n/zh-TW.ts
CHANGED
package/src/init.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createApp, h, reactive, watchEffect } from 'vue';
|
|
2
|
+
import MasonryWall from '@yeger/vue-masonry-wall';
|
|
2
3
|
|
|
3
4
|
import Waline from './components/Waline.vue';
|
|
4
5
|
import { commentCount } from './comment';
|
|
@@ -80,8 +81,12 @@ export const init = ({
|
|
|
80
81
|
? createApp(() => h(Waline, { path: state.path, ...props }))
|
|
81
82
|
: null;
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
if (app) {
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
86
|
+
app.use(MasonryWall);
|
|
87
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
88
|
+
app.mount(root!);
|
|
89
|
+
}
|
|
85
90
|
|
|
86
91
|
updateCommentCount();
|
|
87
92
|
updatePageviewCount();
|
package/src/styles/card.scss
CHANGED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
@mixin gif() {
|
|
2
|
+
.wl-gif-popup {
|
|
3
|
+
position: absolute;
|
|
4
|
+
top: 100%;
|
|
5
|
+
left: 1.25em;
|
|
6
|
+
z-index: 10;
|
|
7
|
+
|
|
8
|
+
width: 436px;
|
|
9
|
+
padding: 12px 12px 4px;
|
|
10
|
+
border: var(--waline-border);
|
|
11
|
+
border-radius: 6px;
|
|
12
|
+
|
|
13
|
+
background: var(--waline-bgcolor);
|
|
14
|
+
box-shadow: var(--waline-box-shadow);
|
|
15
|
+
|
|
16
|
+
opacity: 0;
|
|
17
|
+
visibility: hidden;
|
|
18
|
+
|
|
19
|
+
transition: transform 0.2s ease-out, opacity 0.2s ease-out;
|
|
20
|
+
transform: scale(0.9, 0.9);
|
|
21
|
+
transform-origin: 0 0;
|
|
22
|
+
|
|
23
|
+
&.display {
|
|
24
|
+
opacity: 1;
|
|
25
|
+
visibility: visible;
|
|
26
|
+
transform: none;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
input {
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
|
|
32
|
+
width: 100%;
|
|
33
|
+
margin-bottom: 10px;
|
|
34
|
+
padding: 3px 5px;
|
|
35
|
+
border: var(--waline-border);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
img {
|
|
39
|
+
display: block;
|
|
40
|
+
|
|
41
|
+
box-sizing: border-box;
|
|
42
|
+
|
|
43
|
+
width: 100%;
|
|
44
|
+
border-width: 2px;
|
|
45
|
+
border-style: solid;
|
|
46
|
+
border-color: #fff;
|
|
47
|
+
|
|
48
|
+
cursor: pointer;
|
|
49
|
+
|
|
50
|
+
&:hover {
|
|
51
|
+
border-color: var(--waline-theme-color);
|
|
52
|
+
border-radius: 2px;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.wl-gif-waterfall {
|
|
57
|
+
overflow-y: auto;
|
|
58
|
+
max-height: 800px;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
button {
|
|
62
|
+
display: inline-block;
|
|
63
|
+
vertical-align: middle;
|
|
64
|
+
|
|
65
|
+
width: 2em;
|
|
66
|
+
margin: 0.125em;
|
|
67
|
+
padding: 0;
|
|
68
|
+
border-width: 0;
|
|
69
|
+
|
|
70
|
+
background: transparent;
|
|
71
|
+
|
|
72
|
+
font-size: inherit;
|
|
73
|
+
line-height: 2;
|
|
74
|
+
text-align: center;
|
|
75
|
+
|
|
76
|
+
cursor: pointer;
|
|
77
|
+
|
|
78
|
+
&:hover {
|
|
79
|
+
background: var(--waline-bgcolor-hover);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.wl-gif {
|
|
84
|
+
display: inline-block;
|
|
85
|
+
vertical-align: middle;
|
|
86
|
+
max-width: 1.5em;
|
|
87
|
+
max-height: 1.5em;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.wl-tab-wrapper {
|
|
91
|
+
overflow-y: auto;
|
|
92
|
+
max-height: 145px;
|
|
93
|
+
padding: 0.5em;
|
|
94
|
+
|
|
95
|
+
&::-webkit-scrollbar {
|
|
96
|
+
width: 6px;
|
|
97
|
+
height: 6px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
&::-webkit-scrollbar-track-piece:vertical {
|
|
101
|
+
-webkit-border-radius: 6px;
|
|
102
|
+
border-radius: 6px;
|
|
103
|
+
background: rgb(0 0 0 / 10%);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&::-webkit-scrollbar-thumb:vertical {
|
|
107
|
+
width: 6px;
|
|
108
|
+
-webkit-border-radius: 6px;
|
|
109
|
+
border-radius: 6px;
|
|
110
|
+
background: var(--waline-theme-color);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.wl-tabs {
|
|
115
|
+
position: relative;
|
|
116
|
+
height: 2em;
|
|
117
|
+
padding: 0 6px 1px;
|
|
118
|
+
|
|
119
|
+
&::before {
|
|
120
|
+
content: ' ';
|
|
121
|
+
|
|
122
|
+
position: absolute;
|
|
123
|
+
top: 0;
|
|
124
|
+
right: 0;
|
|
125
|
+
left: 0;
|
|
126
|
+
z-index: 2;
|
|
127
|
+
|
|
128
|
+
height: 1px;
|
|
129
|
+
|
|
130
|
+
background: var(--waline-border-color);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.wl-tab {
|
|
135
|
+
position: relative;
|
|
136
|
+
margin: 0;
|
|
137
|
+
padding: 0 0.5em;
|
|
138
|
+
|
|
139
|
+
&.active {
|
|
140
|
+
z-index: 3;
|
|
141
|
+
|
|
142
|
+
border: 1px solid var(--waline-border-color);
|
|
143
|
+
border-top-width: 0;
|
|
144
|
+
border-bottom-right-radius: 6px;
|
|
145
|
+
border-bottom-left-radius: 6px;
|
|
146
|
+
|
|
147
|
+
background: var(--waline-bgcolor);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
package/src/styles/panel.scss
CHANGED
package/src/typings/locale.ts
CHANGED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export type GifFormat =
|
|
2
|
+
| 'gif'
|
|
3
|
+
| 'mediumgif'
|
|
4
|
+
| 'tinygif'
|
|
5
|
+
| 'nanogif'
|
|
6
|
+
| 'mp4'
|
|
7
|
+
| 'loopedmp4'
|
|
8
|
+
| 'tinymp4'
|
|
9
|
+
| 'nanomp4'
|
|
10
|
+
| 'webm'
|
|
11
|
+
| 'tinywebm'
|
|
12
|
+
| 'nanowebm';
|
|
13
|
+
export interface MediaObject {
|
|
14
|
+
preview: string;
|
|
15
|
+
url: string;
|
|
16
|
+
dims: number[];
|
|
17
|
+
size: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface FetchGifRequest {
|
|
21
|
+
key?: string;
|
|
22
|
+
keyword: string;
|
|
23
|
+
pos?: string;
|
|
24
|
+
limit?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface GifObject {
|
|
28
|
+
created: number;
|
|
29
|
+
hasaudio: boolean;
|
|
30
|
+
id: string;
|
|
31
|
+
media: Record<GifFormat, MediaObject>[];
|
|
32
|
+
tags: string[];
|
|
33
|
+
title: string;
|
|
34
|
+
itemurl: string;
|
|
35
|
+
hascaption: boolean;
|
|
36
|
+
url: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface FetchGifResponse {
|
|
40
|
+
next: string;
|
|
41
|
+
results: GifObject[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const fetchGif = ({
|
|
45
|
+
key,
|
|
46
|
+
keyword,
|
|
47
|
+
pos,
|
|
48
|
+
limit,
|
|
49
|
+
}: FetchGifRequest): Promise<FetchGifResponse> => {
|
|
50
|
+
const baseUrl = `https://g.tenor.com/v1/search`;
|
|
51
|
+
const query = new URLSearchParams('media_filter=minimal');
|
|
52
|
+
query.set('key', key || 'PAY5JLFIH6V6');
|
|
53
|
+
query.set('limit', (limit || 20).toString());
|
|
54
|
+
query.set('pos', pos || '');
|
|
55
|
+
query.set('q', keyword);
|
|
56
|
+
|
|
57
|
+
return fetch(`${baseUrl}?${query.toString()}`, {
|
|
58
|
+
headers: {
|
|
59
|
+
'Content-Type': 'application/json',
|
|
60
|
+
},
|
|
61
|
+
}).then((resp) => resp.json() as Promise<FetchGifResponse>);
|
|
62
|
+
};
|
package/src/utils/index.ts
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function throttle(
|
|
2
|
+
func: (...args: any[]) => void,
|
|
3
|
+
timeout = 300
|
|
4
|
+
): (...args: []) => void {
|
|
5
|
+
let timer: number | null;
|
|
6
|
+
return (...args: []): void => {
|
|
7
|
+
if (timer) {
|
|
8
|
+
clearTimeout(timer);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
timer = window.setTimeout(() => {
|
|
12
|
+
func(...args);
|
|
13
|
+
timer = null;
|
|
14
|
+
}, timeout);
|
|
15
|
+
};
|
|
16
|
+
}
|