Skip to content

Commit

Permalink
create MkExtensionInstaller.vue
Browse files Browse the repository at this point in the history
  • Loading branch information
FineArchs committed Sep 30, 2024
1 parent 57effa9 commit 1684ca2
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 101 deletions.
157 changes: 157 additions & 0 deletions packages/frontend/src/components/MkExtensionInstaller.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
<!--
SPDX-FileCopyrightText: syuilo and misskey-project
SPDX-License-Identifier: AGPL-3.0-only
-->

<template>
<div class="_gaps_m" :class="$style.extInstallerRoot">
<div :class="$style.extInstallerIconWrapper">
<i v-if="extension.type === 'plugin'" class="ti ti-plug"></i>
<i v-else-if="extension.type === 'theme'" class="ti ti-palette"></i>
<i v-else class="ti ti-download"></i>
</div>
<h2 :class="$style.extInstallerTitle">{{ i18n.ts._externalResourceInstaller[`_${extension.type}`].title }}</h2>
<div :class="$style.extInstallerNormDesc">{{ i18n.ts._externalResourceInstaller.checkVendorBeforeInstall }}</div>
<MkInfo v-if="extension.type === 'plugin'" :warn="true">{{ i18n.ts._plugin.installWarn }}</MkInfo>
<FormSection>
<template #label>{{ i18n.ts._externalResourceInstaller[`_${extension.type}`].metaTitle }}</template>
<div class="_gaps_s">
<FormSplit>
<MkKeyValue>
<template #key>{{ i18n.ts.name }}</template>
<template #value>{{ extension.meta.name }}</template>
</MkKeyValue>
<MkKeyValue>
<template #key>{{ i18n.ts.author }}</template>
<template #value>{{ extension.meta.author }}</template>
</MkKeyValue>
</FormSplit>
<MkKeyValue v-if="extension.type === 'plugin'">
<template #key>{{ i18n.ts.description }}</template>
<template #value>{{ extension.meta.description }}</template>
</MkKeyValue>
<MkKeyValue v-if="extension.type === 'plugin'">
<template #key>{{ i18n.ts.version }}</template>
<template #value>{{ extension.meta.version }}</template>
</MkKeyValue>
<MkKeyValue v-if="extension.type === 'plugin'">
<template #key>{{ i18n.ts.permission }}</template>
<template #value>
<ul :class="$style.extInstallerKVList">
<li v-for="permission in extension.meta.permissions" :key="permission">{{ i18n.ts._permissions[permission] }}</li>
</ul>
</template>
</MkKeyValue>
<MkKeyValue v-if="extension.type === 'theme' && extension.meta.base">
<template #key>{{ i18n.ts._externalResourceInstaller._meta.base }}</template>
<template #value>{{ i18n.ts[extension.meta.base] }}</template>
</MkKeyValue>
<MkFolder>
<template #icon><i class="ti ti-code"></i></template>
<template #label>{{ i18n.ts._plugin.viewSource }}</template>

<MkCode :code="extension.raw"/>
</MkFolder>
</div>
</FormSection>
<FormSection>
<template #label>{{ i18n.ts._externalResourceInstaller._vendorInfo.title }}</template>
<div class="_gaps_s">
<MkKeyValue v-if="url">
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.endpoint }}</template>
<template #value><MkUrl :url="url" :showUrlPreview="false"></MkUrl></template>
</MkKeyValue>
<MkKeyValue v-if="hashVerified">
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.hashVerify }}</template>
<template #value>
<i class="ti ti-check" style="color: var(--accent)"></i>
</template>
</MkKeyValue>
</div>
</FormSection>
<div class="_buttonsCenter">
<MkButton primary @click="emits('confirm')"><i class="ti ti-check"></i> {{ i18n.ts.install }}</MkButton>
</div>
</div>
</template>

<script lang="ts">
export type Extension = {
type: 'plugin';
raw: string;
meta: {
name: string;
author: string;
description?: string;
version?: string;
permissions?: string[];
config?: Record<string, any>;
};
} | {
type: 'theme';
raw: string;
meta: {
name: string;
author: string;
base?: 'light' | 'dark';
};
};
</script>
<script lang="ts" setup>
import MkButton from '@/components/MkButton.vue';
import FormSection from '@/components/form/section.vue';
import FormSplit from '@/components/form/split.vue';
import MkCode from '@/components/MkCode.vue';
import MkUrl from '@/components/global/MkUrl.vue';
import MkInfo from '@/components/MkInfo.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkKeyValue from '@/components/MkKeyValue.vue';
import { i18n } from '@/i18n.js';

const props = defineProps<{
extension: Extension;
url?: string;
hashVerified?: boolean;
}>();

const emits = defineEmits<{
(ev: 'confirm'): void;
}>();
</script>

<style lang="scss" module>
.extInstallerRoot {
border-radius: var(--radius);
background: var(--panel);
padding: 1.5rem;
}

.extInstallerIconWrapper {
width: 48px;
height: 48px;
font-size: 24px;
line-height: 48px;
text-align: center;
border-radius: 50%;
margin-left: auto;
margin-right: auto;

background-color: var(--accentedBg);
color: var(--accent);
}

.extInstallerTitle {
font-size: 1.2rem;
text-align: center;
margin: 0;
}

.extInstallerNormDesc {
text-align: center;
}

.extInstallerKVList {
margin-top: 0;
margin-bottom: 0;
}
</style>
106 changes: 5 additions & 101 deletions packages/frontend/src/pages/install-extensions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,76 +8,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template>
<MkSpacer :contentMax="500">
<MkLoading v-if="uiPhase === 'fetching'"/>
<div v-else-if="uiPhase === 'confirm' && data" class="_gaps_m" :class="$style.extInstallerRoot">
<div :class="$style.extInstallerIconWrapper">
<i v-if="data.type === 'plugin'" class="ti ti-plug"></i>
<i v-else-if="data.type === 'theme'" class="ti ti-palette"></i>
<i v-else class="ti ti-download"></i>
</div>
<h2 :class="$style.extInstallerTitle">{{ i18n.ts._externalResourceInstaller[`_${data.type}`].title }}</h2>
<div :class="$style.extInstallerNormDesc">{{ i18n.ts._externalResourceInstaller.checkVendorBeforeInstall }}</div>
<MkInfo v-if="data.type === 'plugin'" :warn="true">{{ i18n.ts._plugin.installWarn }}</MkInfo>
<FormSection>
<template #label>{{ i18n.ts._externalResourceInstaller[`_${data.type}`].metaTitle }}</template>
<div class="_gaps_s">
<FormSplit>
<MkKeyValue>
<template #key>{{ i18n.ts.name }}</template>
<template #value>{{ data.meta?.name }}</template>
</MkKeyValue>
<MkKeyValue>
<template #key>{{ i18n.ts.author }}</template>
<template #value>{{ data.meta?.author }}</template>
</MkKeyValue>
</FormSplit>
<MkKeyValue v-if="data.type === 'plugin'">
<template #key>{{ i18n.ts.description }}</template>
<template #value>{{ data.meta?.description }}</template>
</MkKeyValue>
<MkKeyValue v-if="data.type === 'plugin'">
<template #key>{{ i18n.ts.version }}</template>
<template #value>{{ data.meta?.version }}</template>
</MkKeyValue>
<MkKeyValue v-if="data.type === 'plugin'">
<template #key>{{ i18n.ts.permission }}</template>
<template #value>
<ul :class="$style.extInstallerKVList">
<li v-for="permission in data.meta?.permissions" :key="permission">{{ i18n.ts._permissions[permission] }}</li>
</ul>
</template>
</MkKeyValue>
<MkKeyValue v-if="data.type === 'theme' && data.meta?.base">
<template #key>{{ i18n.ts._externalResourceInstaller._meta.base }}</template>
<template #value>{{ i18n.ts[data.meta.base] }}</template>
</MkKeyValue>
<MkFolder>
<template #icon><i class="ti ti-code"></i></template>
<template #label>{{ i18n.ts._plugin.viewSource }}</template>

<MkCode :code="data.raw ?? ''"/>
</MkFolder>
</div>
</FormSection>
<FormSection>
<template #label>{{ i18n.ts._externalResourceInstaller._vendorInfo.title }}</template>
<div class="_gaps_s">
<MkKeyValue>
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.endpoint }}</template>
<template #value><MkUrl :url="url ?? ''" :showUrlPreview="false"></MkUrl></template>
</MkKeyValue>
<MkKeyValue>
<template #key>{{ i18n.ts._externalResourceInstaller._vendorInfo.hashVerify }}</template>
<template #value>
<!--この画面が出ている時点でハッシュの検証には成功している-->
<i class="ti ti-check" style="color: var(--accent)"></i>
</template>
</MkKeyValue>
</div>
</FormSection>
<div class="_buttonsCenter">
<MkButton primary @click="install()"><i class="ti ti-check"></i> {{ i18n.ts.install }}</MkButton>
</div>
</div>
<!-- この画面が表示されている時点でハッシュの検証には成功している -->
<MkExtensionInstaller v-else-if="uiPhase === 'confirm' && data" :extension="data" :url="url" hashVerified @confirm="install()"/>
<div v-else-if="uiPhase === 'error'" class="_gaps_m" :class="[$style.extInstallerRoot, $style.error]">
<div :class="$style.extInstallerIconWrapper">
<i class="ti ti-circle-x"></i>
Expand All @@ -96,14 +28,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { ref, computed, onActivated, onDeactivated, nextTick } from 'vue';
import MkLoading from '@/components/global/MkLoading.vue';
import MkExtensionInstaller, { type Extension } from '@/components/MkExtensionInstaller.vue';
import MkButton from '@/components/MkButton.vue';
import FormSection from '@/components/form/section.vue';
import FormSplit from '@/components/form/split.vue';
import MkCode from '@/components/MkCode.vue';
import MkUrl from '@/components/global/MkUrl.vue';
import MkInfo from '@/components/MkInfo.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkKeyValue from '@/components/MkKeyValue.vue';
import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { AiScriptPluginMeta, parsePluginMeta, installPlugin } from '@/scripts/install-plugin.js';
Expand All @@ -124,24 +50,7 @@ const errorKV = ref<{
const url = ref<string | null>(null);
const hash = ref<string | null>(null);

const data = ref<{
type: 'plugin' | 'theme';
raw: string;
meta?: {
// Plugin & Theme Common
name: string;
author: string;

// Plugin
description?: string;
version?: string;
permissions?: string[];
config?: Record<string, any>;

// Theme
base?: 'light' | 'dark';
};
} | null>(null);
const data = ref<Extension | null>(null);

function goBack(): void {
history.back();
Expand Down Expand Up @@ -227,7 +136,7 @@ async function fetch() {
data.value = {
type: 'theme',
meta: {
description,
// description, // 使用されていない
...meta,
},
raw: res.data,
Expand Down Expand Up @@ -353,9 +262,4 @@ definePageMetadata(() => ({
.extInstallerNormDesc {
text-align: center;
}

.extInstallerKVList {
margin-top: 0;
margin-bottom: 0;
}
</style>

0 comments on commit 1684ca2

Please sign in to comment.