Skip to content

Commit 1684ca2

Browse files
committed
create MkExtensionInstaller.vue
1 parent 57effa9 commit 1684ca2

File tree

2 files changed

+162
-101
lines changed

2 files changed

+162
-101
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
<!--
2+
SPDX-FileCopyrightText: syuilo and misskey-project
3+
SPDX-License-Identifier: AGPL-3.0-only
4+
-->
5+
6+
<template>
7+
<div class="_gaps_m" :class="$style.extInstallerRoot">
8+
<div :class="$style.extInstallerIconWrapper">
9+
<i v-if="extension.type === 'plugin'" class="ti ti-plug"></i>
10+
<i v-else-if="extension.type === 'theme'" class="ti ti-palette"></i>
11+
<i v-else class="ti ti-download"></i>
12+
</div>
13+
<h2 :class="$style.extInstallerTitle">{{ i18n.ts._externalResourceInstaller[`_${extension.type}`].title }}</h2>
14+
<div :class="$style.extInstallerNormDesc">{{ i18n.ts._externalResourceInstaller.checkVendorBeforeInstall }}</div>
15+
<MkInfo v-if="extension.type === 'plugin'" :warn="true">{{ i18n.ts._plugin.installWarn }}</MkInfo>
16+
<FormSection>
17+
<template #label>{{ i18n.ts._externalResourceInstaller[`_${extension.type}`].metaTitle }}</template>
18+
<div class="_gaps_s">
19+
<FormSplit>
20+
<MkKeyValue>
21+
<template #key>{{ i18n.ts.name }}</template>
22+
<template #value>{{ extension.meta.name }}</template>
23+
</MkKeyValue>
24+
<MkKeyValue>
25+
<template #key>{{ i18n.ts.author }}</template>
26+
<template #value>{{ extension.meta.author }}</template>
27+
</MkKeyValue>
28+
</FormSplit>
29+
<MkKeyValue v-if="extension.type === 'plugin'">
30+
<template #key>{{ i18n.ts.description }}</template>
31+
<template #value>{{ extension.meta.description }}</template>
32+
</MkKeyValue>
33+
<MkKeyValue v-if="extension.type === 'plugin'">
34+
<template #key>{{ i18n.ts.version }}</template>
35+
<template #value>{{ extension.meta.version }}</template>
36+
</MkKeyValue>
37+
<MkKeyValue v-if="extension.type === 'plugin'">
38+
<template #key>{{ i18n.ts.permission }}</template>
39+
<template #value>
40+
<ul :class="$style.extInstallerKVList">
41+
<li v-for="permission in extension.meta.permissions" :key="permission">{{ i18n.ts._permissions[permission] }}</li>
42+
</ul>
43+
</template>
44+
</MkKeyValue>
45+
<MkKeyValue v-if="extension.type === 'theme' && extension.meta.base">
46+
<template #key>{{ i18n.ts._externalResourceInstaller._meta.base }}</template>
47+
<template #value>{{ i18n.ts[extension.meta.base] }}</template>
48+
</MkKeyValue>
49+
<MkFolder>
50+
<template #icon><i class="ti ti-code"></i></template>
51+
<template #label>{{ i18n.ts._plugin.viewSource }}</template>
52+
53+
<MkCode :code="extension.raw"/>
54+
</MkFolder>
55+
</div>
56+
</FormSection>
57+
<FormSection>
58+
<template #label>{{ i18n.ts._externalResourceInstaller._vendorInfo.title }}</template>
59+
<div class="_gaps_s">
60+
<MkKeyValue v-if="url">
61+
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.endpoint }}</template>
62+
<template #value><MkUrl :url="url" :showUrlPreview="false"></MkUrl></template>
63+
</MkKeyValue>
64+
<MkKeyValue v-if="hashVerified">
65+
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.hashVerify }}</template>
66+
<template #value>
67+
<i class="ti ti-check" style="color: var(--accent)"></i>
68+
</template>
69+
</MkKeyValue>
70+
</div>
71+
</FormSection>
72+
<div class="_buttonsCenter">
73+
<MkButton primary @click="emits('confirm')"><i class="ti ti-check"></i> {{ i18n.ts.install }}</MkButton>
74+
</div>
75+
</div>
76+
</template>
77+
78+
<script lang="ts">
79+
export type Extension = {
80+
type: 'plugin';
81+
raw: string;
82+
meta: {
83+
name: string;
84+
author: string;
85+
description?: string;
86+
version?: string;
87+
permissions?: string[];
88+
config?: Record<string, any>;
89+
};
90+
} | {
91+
type: 'theme';
92+
raw: string;
93+
meta: {
94+
name: string;
95+
author: string;
96+
base?: 'light' | 'dark';
97+
};
98+
};
99+
</script>
100+
<script lang="ts" setup>
101+
import MkButton from '@/components/MkButton.vue';
102+
import FormSection from '@/components/form/section.vue';
103+
import FormSplit from '@/components/form/split.vue';
104+
import MkCode from '@/components/MkCode.vue';
105+
import MkUrl from '@/components/global/MkUrl.vue';
106+
import MkInfo from '@/components/MkInfo.vue';
107+
import MkFolder from '@/components/MkFolder.vue';
108+
import MkKeyValue from '@/components/MkKeyValue.vue';
109+
import { i18n } from '@/i18n.js';
110+
111+
const props = defineProps<{
112+
extension: Extension;
113+
url?: string;
114+
hashVerified?: boolean;
115+
}>();
116+
117+
const emits = defineEmits<{
118+
(ev: 'confirm'): void;
119+
}>();
120+
</script>
121+
122+
<style lang="scss" module>
123+
.extInstallerRoot {
124+
border-radius: var(--radius);
125+
background: var(--panel);
126+
padding: 1.5rem;
127+
}
128+
129+
.extInstallerIconWrapper {
130+
width: 48px;
131+
height: 48px;
132+
font-size: 24px;
133+
line-height: 48px;
134+
text-align: center;
135+
border-radius: 50%;
136+
margin-left: auto;
137+
margin-right: auto;
138+
139+
background-color: var(--accentedBg);
140+
color: var(--accent);
141+
}
142+
143+
.extInstallerTitle {
144+
font-size: 1.2rem;
145+
text-align: center;
146+
margin: 0;
147+
}
148+
149+
.extInstallerNormDesc {
150+
text-align: center;
151+
}
152+
153+
.extInstallerKVList {
154+
margin-top: 0;
155+
margin-bottom: 0;
156+
}
157+
</style>

packages/frontend/src/pages/install-extensions.vue

+5-101
Original file line numberDiff line numberDiff line change
@@ -8,76 +8,8 @@ SPDX-License-Identifier: AGPL-3.0-only
88
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
99
<MkSpacer :contentMax="500">
1010
<MkLoading v-if="uiPhase === 'fetching'"/>
11-
<div v-else-if="uiPhase === 'confirm' && data" class="_gaps_m" :class="$style.extInstallerRoot">
12-
<div :class="$style.extInstallerIconWrapper">
13-
<i v-if="data.type === 'plugin'" class="ti ti-plug"></i>
14-
<i v-else-if="data.type === 'theme'" class="ti ti-palette"></i>
15-
<i v-else class="ti ti-download"></i>
16-
</div>
17-
<h2 :class="$style.extInstallerTitle">{{ i18n.ts._externalResourceInstaller[`_${data.type}`].title }}</h2>
18-
<div :class="$style.extInstallerNormDesc">{{ i18n.ts._externalResourceInstaller.checkVendorBeforeInstall }}</div>
19-
<MkInfo v-if="data.type === 'plugin'" :warn="true">{{ i18n.ts._plugin.installWarn }}</MkInfo>
20-
<FormSection>
21-
<template #label>{{ i18n.ts._externalResourceInstaller[`_${data.type}`].metaTitle }}</template>
22-
<div class="_gaps_s">
23-
<FormSplit>
24-
<MkKeyValue>
25-
<template #key>{{ i18n.ts.name }}</template>
26-
<template #value>{{ data.meta?.name }}</template>
27-
</MkKeyValue>
28-
<MkKeyValue>
29-
<template #key>{{ i18n.ts.author }}</template>
30-
<template #value>{{ data.meta?.author }}</template>
31-
</MkKeyValue>
32-
</FormSplit>
33-
<MkKeyValue v-if="data.type === 'plugin'">
34-
<template #key>{{ i18n.ts.description }}</template>
35-
<template #value>{{ data.meta?.description }}</template>
36-
</MkKeyValue>
37-
<MkKeyValue v-if="data.type === 'plugin'">
38-
<template #key>{{ i18n.ts.version }}</template>
39-
<template #value>{{ data.meta?.version }}</template>
40-
</MkKeyValue>
41-
<MkKeyValue v-if="data.type === 'plugin'">
42-
<template #key>{{ i18n.ts.permission }}</template>
43-
<template #value>
44-
<ul :class="$style.extInstallerKVList">
45-
<li v-for="permission in data.meta?.permissions" :key="permission">{{ i18n.ts._permissions[permission] }}</li>
46-
</ul>
47-
</template>
48-
</MkKeyValue>
49-
<MkKeyValue v-if="data.type === 'theme' && data.meta?.base">
50-
<template #key>{{ i18n.ts._externalResourceInstaller._meta.base }}</template>
51-
<template #value>{{ i18n.ts[data.meta.base] }}</template>
52-
</MkKeyValue>
53-
<MkFolder>
54-
<template #icon><i class="ti ti-code"></i></template>
55-
<template #label>{{ i18n.ts._plugin.viewSource }}</template>
56-
57-
<MkCode :code="data.raw ?? ''"/>
58-
</MkFolder>
59-
</div>
60-
</FormSection>
61-
<FormSection>
62-
<template #label>{{ i18n.ts._externalResourceInstaller._vendorInfo.title }}</template>
63-
<div class="_gaps_s">
64-
<MkKeyValue>
65-
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.endpoint }}</template>
66-
<template #value><MkUrl :url="url ?? ''" :showUrlPreview="false"></MkUrl></template>
67-
</MkKeyValue>
68-
<MkKeyValue>
69-
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.hashVerify }}</template>
70-
<template #value>
71-
<!--この画面が出ている時点でハッシュの検証には成功している-->
72-
<i class="ti ti-check" style="color: var(--accent)"></i>
73-
</template>
74-
</MkKeyValue>
75-
</div>
76-
</FormSection>
77-
<div class="_buttonsCenter">
78-
<MkButton primary @click="install()"><i class="ti ti-check"></i> {{ i18n.ts.install }}</MkButton>
79-
</div>
80-
</div>
11+
<!-- この画面が表示されている時点でハッシュの検証には成功している -->
12+
<MkExtensionInstaller v-else-if="uiPhase === 'confirm' && data" :extension="data" :url="url" hashVerified @confirm="install()"/>
8113
<div v-else-if="uiPhase === 'error'" class="_gaps_m" :class="[$style.extInstallerRoot, $style.error]">
8214
<div :class="$style.extInstallerIconWrapper">
8315
<i class="ti ti-circle-x"></i>
@@ -96,14 +28,8 @@ SPDX-License-Identifier: AGPL-3.0-only
9628
<script lang="ts" setup>
9729
import { ref, computed, onActivated, onDeactivated, nextTick } from 'vue';
9830
import MkLoading from '@/components/global/MkLoading.vue';
31+
import MkExtensionInstaller, { type Extension } from '@/components/MkExtensionInstaller.vue';
9932
import MkButton from '@/components/MkButton.vue';
100-
import FormSection from '@/components/form/section.vue';
101-
import FormSplit from '@/components/form/split.vue';
102-
import MkCode from '@/components/MkCode.vue';
103-
import MkUrl from '@/components/global/MkUrl.vue';
104-
import MkInfo from '@/components/MkInfo.vue';
105-
import MkFolder from '@/components/MkFolder.vue';
106-
import MkKeyValue from '@/components/MkKeyValue.vue';
10733
import * as os from '@/os.js';
10834
import { misskeyApi } from '@/scripts/misskey-api.js';
10935
import { AiScriptPluginMeta, parsePluginMeta, installPlugin } from '@/scripts/install-plugin.js';
@@ -124,24 +50,7 @@ const errorKV = ref<{
12450
const url = ref<string | null>(null);
12551
const hash = ref<string | null>(null);
12652

127-
const data = ref<{
128-
type: 'plugin' | 'theme';
129-
raw: string;
130-
meta?: {
131-
// Plugin & Theme Common
132-
name: string;
133-
author: string;
134-
135-
// Plugin
136-
description?: string;
137-
version?: string;
138-
permissions?: string[];
139-
config?: Record<string, any>;
140-
141-
// Theme
142-
base?: 'light' | 'dark';
143-
};
144-
} | null>(null);
53+
const data = ref<Extension | null>(null);
14554

14655
function goBack(): void {
14756
history.back();
@@ -227,7 +136,7 @@ async function fetch() {
227136
data.value = {
228137
type: 'theme',
229138
meta: {
230-
description,
139+
// description, // 使用されていない
231140
...meta,
232141
},
233142
raw: res.data,
@@ -353,9 +262,4 @@ definePageMetadata(() => ({
353262
.extInstallerNormDesc {
354263
text-align: center;
355264
}
356-
357-
.extInstallerKVList {
358-
margin-top: 0;
359-
margin-bottom: 0;
360-
}
361265
</style>

0 commit comments

Comments
 (0)