11<script setup lang="ts">
2- import type { UploadFileInfo } from ' naive-ui'
3- import { NA , NFlex , NList , NListItem , NText , NUpload , NUploadDragger , useMessage } from ' naive-ui'
4- import { computed , ref } from ' vue'
2+ import type { MenuOption , UploadFileInfo } from ' naive-ui'
3+ import { NA , NFlex , NMenu , NScrollbar , NText , NUpload , NUploadDragger , useMessage } from ' naive-ui'
4+ import { computed , h , ref } from ' vue'
55import { t } from ' ./i18n'
66import MustInstall from ' ./MustInstall.vue'
7+ import { isMobile } from ' ./util'
78
89defineProps <{
910 disabled: boolean
@@ -15,9 +16,53 @@ function getInstalledPlugins() {
1516 return window .fcitx .getInstalledPlugins ().sort ()
1617}
1718
18- const allPlugins = [' anthy' , ' chewing' , ' chinese-addons' , ' hallelujah' , ' hangul' , ' jyutping' , ' lua' , ' m17n' , ' mozc' , ' rime' , ' sayura' , ' skk' , ' thai' , ' unikey' ]
19+ const plugins: [string , string ][] = [
20+ [' anthy' , ' Japanese' ],
21+ [' chewing' , ' Chinese' ],
22+ [' chinese-addons' , ' Chinese' ],
23+ [' hallelujah' , ' English' ],
24+ [' hangul' , ' Korean' ],
25+ [' jyutping' , ' Chinese' ],
26+ [' lua' , ' Other' ],
27+ [' m17n' , ' Generic' ],
28+ [' mozc' , ' Japanese' ],
29+ [' rime' , ' Generic' ],
30+ [' sayura' , ' Sinhala' ],
31+ [' skk' , ' Japanese' ],
32+ [' thai' , ' Thai' ],
33+ [' unikey' , ' Vietnamese' ],
34+ ]
35+
36+ function tLanguage(language : string ) {
37+ return t (` language.${language } ` )
38+ }
39+
40+ function toOptions(plugins : [string , string ][]) {
41+ const pluginMap: Record <string , string []> = {}
42+ for (const [plugin, language] of plugins ) {
43+ (pluginMap [language ] = pluginMap [language ] || []).push (plugin )
44+ }
45+ return Object .entries (pluginMap ).sort (([la ], [lb ]) => {
46+ for (const key of [' Other' , ' Generic' ]) {
47+ if (la === key ) {
48+ return 1
49+ }
50+ if (lb === key ) {
51+ return - 1
52+ }
53+ }
54+ return tLanguage (la ).localeCompare (tLanguage (lb ))
55+ }).map (([language , plugins ]) => ({
56+ type: ' group' ,
57+ key: language ,
58+ label: tLanguage (language ),
59+ children: plugins .map (plugin => ({ key: plugin , label: plugin })),
60+ }))
61+ }
62+
1963const installedPlugins = ref <string []>(getInstalledPlugins ())
20- const availablePlugins = computed (() => allPlugins .filter (plugin => ! installedPlugins .value .includes (plugin )))
64+ const installedOptions = computed (() => toOptions (plugins .filter (([plugin , _ ]) => installedPlugins .value .includes (plugin ))))
65+ const availableOptions = computed (() => toOptions (plugins .filter (([plugin , _ ]) => ! installedPlugins .value .includes (plugin ))))
2166
2267const fileList = ref <UploadFileInfo []>([])
2368
@@ -39,44 +84,44 @@ async function onUpload(files: UploadFileInfo[]) {
3984 message .success (t (' Installed {plugin}' , { plugin: name }))
4085 }
4186}
87+
88+ function installedItem(option : MenuOption ) {
89+ if (option .key === ' jyutping' && ! installedPlugins .value .includes (' chinese-addons' )) {
90+ return h (MustInstall , { plugin: ' chinese-addons' }, { default : () => h (NText , {
91+ delete: true ,
92+ }, { default: option .label }) })
93+ }
94+ return option .label as string
95+ }
96+
97+ function availableItem(option : MenuOption ) {
98+ return h (MustInstall , { plugin: option .key === ' jyutping' ? ' chinese-addons' : undefined }, { default : () => h (NA , {
99+ href: ` https://github.com/fcitx-contrib/fcitx5-plugins/releases/download/js/${option .key }.zip ` ,
100+ }, { default: option .label }) })
101+ }
42102 </script >
43103
44104<template >
45- <NFlex size =" large" >
46- <NUpload v-model:file-list =" fileList" :disabled =" disabled" multiple accept =" .zip" @update:file-list =" onUpload" >
47- <NUploadDragger style =" height : 200 px " >
48- <p >{{ t('Download plugin zip by clicking links below ') }}</p >
49- <p >{{ t('then click ( or drag them to) this area') }}</p >
105+ <NFlex size =" large" :vertical = " isMobile " :style = " { height: isMobile ? '100%' : 'calc(100vh - 100px)' } " >
106+ <NUpload v-model:file-list =" fileList" :style = " isMobile ? {} : { width: 'auto', flex: '1' } " : disabled =" disabled" multiple accept =" .zip" @update:file-list =" onUpload" >
107+ <NUploadDragger : style =" isMobile ? {} : { height: '300px' } " >
108+ <p >{{ t('Download plugin zip by clicking buttons under "Available" ') }}</p >
109+ <p >{{ isMobile ? t('then click this area to load zip') : t('then click ( or drag them to) this area to load zip ') }}</p >
50110 </NUploadDragger >
51111 </NUpload >
52- <NFlex >
53- <NList style =" min-width : 100px " >
54- <template #header >
55- {{ t('Installed') }}
56- </template >
57- <NListItem v-for =" plugin in installedPlugins" :key =" plugin" >
58- <MustInstall v-if =" plugin === 'jyutping' && !installedPlugins.includes('chinese-addons')" plugin =" chinese-addons" >
59- <NText delete >
60- {{ plugin }}
61- </NText >
62- </MustInstall >
63- <template v-else >
64- {{ plugin }}
65- </template >
66- </NListItem >
67- </NList >
68- <NList style =" min-width : 100px " >
69- <template #header >
70- {{ t('Available') }}
71- </template >
72- <NListItem v-for =" plugin in availablePlugins" :key =" plugin" >
73- <MustInstall :plugin =" plugin === 'jyutping' ? 'chinese-addons' : undefined" >
74- <NA :href =" `https://github.com/fcitx-contrib/fcitx5-plugins/releases/download/js/${plugin}.zip`" >
75- {{ plugin }}
76- </NA >
77- </MustInstall >
78- </NListItem >
79- </NList >
112+ <NFlex :style =" isMobile ? { 'min-height': '0' } : { height: '100%', flex: '1' }" >
113+ <NFlex vertical style =" flex : 1 ; height : 100% " >
114+ {{ t('Installed') }}
115+ <NScrollbar >
116+ <NMenu :root-indent =" 0" :indent =" 24" :options =" installedOptions" :render-label =" installedItem" />
117+ </NScrollbar >
118+ </NFlex >
119+ <NFlex vertical style =" flex : 1 ; height : 100% " >
120+ {{ t('Available') }}
121+ <NScrollbar >
122+ <NMenu :root-indent =" 0" :indent =" 24" :options =" availableOptions" :render-label =" availableItem" />
123+ </NScrollbar >
124+ </NFlex >
80125 </NFlex >
81126 </NFlex >
82127</template >
0 commit comments