Skip to content

Commit 43c62c4

Browse files
committed
add input methods
1 parent 8cc6cbd commit 43c62c4

File tree

1 file changed

+125
-7
lines changed

1 file changed

+125
-7
lines changed

src/InputMethodConfig.vue

Lines changed: 125 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
<script setup lang="ts">
2-
import { computed, h, ref } from 'vue'
1+
<script lang="ts">
2+
import { computed, h, ref, watchEffect } from 'vue'
33
import type { MenuOption } from 'naive-ui'
4-
import { NLayout, NLayoutSider, NMenu } from 'naive-ui'
4+
import { NButton, NCheckbox, NCheckboxGroup, NFlex, NLayout, NLayoutFooter, NLayoutSider, NMenu } from 'naive-ui'
55
import MinusButton from './MinusButton.vue'
66
import PlusButton from './PlusButton.vue'
77
8+
const languageName = new Intl.DisplayNames(navigator.language, { type: 'language' })
9+
</script>
10+
11+
<script setup lang="ts">
812
const props = defineProps<{
913
inputMethod: string
1014
inputMethods: {
@@ -47,6 +51,73 @@ function labelWithMinus(option: MenuOption) {
4751
}
4852
4953
const collapsed = ref(false)
54+
const adding = ref(false)
55+
56+
const selectedLanguage = ref<string | null>(null)
57+
58+
const availableInputMethodOptions = ref<{
59+
label: string
60+
key: string
61+
}[]>([])
62+
63+
let map: { [key: string]: {
64+
name: string
65+
displayName: string
66+
}[] } = {}
67+
68+
watchEffect(() => {
69+
if (!adding.value) {
70+
return
71+
}
72+
map = {}
73+
for (const im of window.fcitx.getAllInputMethods()) {
74+
const code = im.languageCode.replace('_', '-');
75+
(map[code] = map[code] || []).push({
76+
name: im.name,
77+
displayName: im.displayName,
78+
})
79+
}
80+
availableInputMethodOptions.value = []
81+
const sortedLanguageCodes = Object.keys(map).sort((a: string, b: string) => {
82+
if (!a) {
83+
return 1
84+
}
85+
if (!b) {
86+
return -1
87+
}
88+
const la = languageName.of(a) ?? a
89+
const lb = languageName.of(b) ?? b
90+
if (a === la && b !== lb) {
91+
return 1
92+
}
93+
if (a !== la && b === lb) {
94+
return -1
95+
}
96+
return la.localeCompare(lb)
97+
})
98+
for (const languageCode of sortedLanguageCodes) {
99+
availableInputMethodOptions.value.push({
100+
label: languageCode ? (languageName.of(languageCode) ?? languageCode) : languageCode,
101+
key: languageCode,
102+
})
103+
}
104+
})
105+
106+
const inputMethodsForLanguage = computed(() => {
107+
if (!selectedLanguage.value) {
108+
return []
109+
}
110+
const enabledIMs = props.inputMethods.map(({ name }) => name)
111+
return map[selectedLanguage.value].filter(({ name }) => !enabledIMs.includes(name))
112+
})
113+
114+
const imsToAdd = ref<string[]>([])
115+
116+
function add() {
117+
window.fcitx.setInputMethods(props.inputMethods.map(({ name }) => name).concat(imsToAdd.value))
118+
window.fcitx.updateStatusArea()
119+
imsToAdd.value = []
120+
}
50121
</script>
51122

52123
<template>
@@ -56,22 +127,69 @@ const collapsed = ref(false)
56127
collapse-mode="width"
57128
:collapsed="collapsed"
58129
show-trigger
130+
style="max-height: calc(100vh - 100px)"
59131
@collapse="collapsed = true"
60132
@expand="collapsed = false"
61133
>
62-
<div style="display: flex; flex-direction: column; justify-content: space-between; height: 100%">
134+
<div v-if="adding">
135+
<NMenu
136+
v-model:value="selectedLanguage"
137+
:options="availableInputMethodOptions"
138+
/>
139+
</div>
140+
<div
141+
v-else
142+
style="display: flex; flex-direction: column; justify-content: space-between; height: 100%"
143+
>
63144
<NMenu
64145
v-model:value="selectedInputMethod"
65146
:collapsed="collapsed"
66147
:collapsed-width="0"
67148
:options="options"
68149
:render-label="labelWithMinus"
69150
/>
70-
<PlusButton style="align-self: flex-end" />
151+
<PlusButton
152+
style="align-self: flex-end"
153+
@click="adding = true"
154+
/>
71155
</div>
72156
</NLayoutSider>
73-
<NLayout style="min-height: 480px">
74-
{{ selectedInputMethod }}
157+
<NLayout style="min-height: 480px; max-height: calc(100vh - 100px)">
158+
<template v-if="adding">
159+
<NLayout position="absolute" style="bottom: 50px; padding: 16px 0 16px 16px">
160+
<NCheckboxGroup v-model:value="imsToAdd">
161+
<NFlex vertical>
162+
<NCheckbox
163+
v-for="im of inputMethodsForLanguage"
164+
:key="im.name"
165+
:value="im.name"
166+
:label="im.displayName"
167+
/>
168+
</NFlex>
169+
</NCheckboxGroup>
170+
</NLayout>
171+
<NLayoutFooter position="absolute">
172+
<NFlex
173+
justify="end"
174+
style="padding: 8px"
175+
>
176+
<NButton secondary @click="adding = false">
177+
Cancel
178+
</NButton>
179+
<NButton
180+
secondary
181+
type="info"
182+
:disabled="imsToAdd.length === 0"
183+
@click="add"
184+
>
185+
Add
186+
</NButton>
187+
</NFlex>
188+
</NLayoutFooter>
189+
</template>
190+
<div v-else>
191+
{{ selectedInputMethod }}
192+
</div>
75193
</NLayout>
76194
</NLayout>
77195
</template>

0 commit comments

Comments
 (0)