summaryrefslogtreecommitdiff
path: root/packages/frontend/src/components
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-01-05 13:59:48 +0900
committerGitHub <noreply@github.com>2023-01-05 13:59:48 +0900
commitebe340d5105595abe2406e8f386c3ab69703b73b (patch)
tree36eb93333667353fb71a430b7d5e1a700d0e904e /packages/frontend/src/components
parentUpdate CHANGELOG.md (diff)
downloadmisskey-ebe340d5105595abe2406e8f386c3ab69703b73b.tar.gz
misskey-ebe340d5105595abe2406e8f386c3ab69703b73b.tar.bz2
misskey-ebe340d5105595abe2406e8f386c3ab69703b73b.zip
MisskeyPlay (#9467)
* wip * wip * wip * wip * wip * Update ui.ts * wip * wip * wip * wip * wip * wip * wip * wip * Update CHANGELOG.md * wip * wip * wip * wip * :art: * wip * :v:
Diffstat (limited to 'packages/frontend/src/components')
-rw-r--r--packages/frontend/src/components/MkAsUi.vue107
-rw-r--r--packages/frontend/src/components/MkButton.vue40
-rw-r--r--packages/frontend/src/components/MkChartLegend.vue2
-rw-r--r--packages/frontend/src/components/MkFlashPreview.vue112
-rw-r--r--packages/frontend/src/components/MkLaunchPad.vue2
-rw-r--r--packages/frontend/src/components/MkPagePreview.vue19
-rw-r--r--packages/frontend/src/components/form/select.vue2
7 files changed, 267 insertions, 17 deletions
diff --git a/packages/frontend/src/components/MkAsUi.vue b/packages/frontend/src/components/MkAsUi.vue
new file mode 100644
index 0000000000..bc1e25957b
--- /dev/null
+++ b/packages/frontend/src/components/MkAsUi.vue
@@ -0,0 +1,107 @@
+<template>
+<div>
+ <div v-if="c.type === 'root'" :class="$style.root">
+ <template v-for="child in c.children" :key="child">
+ <MkAsUi v-if="!g(child).hidden" :component="g(child)" :components="props.components" :size="size"/>
+ </template>
+ </div>
+ <span v-else-if="c.type === 'text'" :class="{ [$style.fontSerif]: c.font === 'serif', [$style.fontMonospace]: c.font === 'monospace' }" :style="{ fontSize: c.size ? `${c.size * 100}%` : null, fontWeight: c.bold ? 'bold' : null, color: c.color ?? null }">{{ c.text }}</span>
+ <Mfm v-else-if="c.type === 'mfm'" :class="{ [$style.fontSerif]: c.font === 'serif', [$style.fontMonospace]: c.font === 'monospace' }" :style="{ fontSize: c.size ? `${c.size * 100}%` : null, color: c.color ?? null }" :text="c.text"/>
+ <MkButton v-else-if="c.type === 'button'" :primary="c.primary" :rounded="c.rounded" :small="size === 'small'" @click="c.onClick">{{ c.text }}</MkButton>
+ <div v-else-if="c.type === 'buttons'" style="display: flex; gap: 8px; flex-wrap: wrap;">
+ <MkButton v-for="button in c.buttons" :primary="button.primary" :rounded="button.rounded" :small="size === 'small'" @click="button.onClick">{{ button.text }}</MkButton>
+ </div>
+ <MkSwitch v-else-if="c.type === 'switch'" :model-value="valueForSwitch" @update:model-value="onSwitchUpdate">
+ <template v-if="c.label" #label>{{ c.label }}</template>
+ <template v-if="c.caption" #caption>{{ c.caption }}</template>
+ </MkSwitch>
+ <MkTextarea v-else-if="c.type === 'textarea'" :model-value="c.default" @update:model-value="c.onInput">
+ <template v-if="c.label" #label>{{ c.label }}</template>
+ <template v-if="c.caption" #caption>{{ c.caption }}</template>
+ </MkTextarea>
+ <MkInput v-else-if="c.type === 'textInput'" :small="size === 'small'" :model-value="c.default" @update:model-value="c.onInput">
+ <template v-if="c.label" #label>{{ c.label }}</template>
+ <template v-if="c.caption" #caption>{{ c.caption }}</template>
+ </MkInput>
+ <MkInput v-else-if="c.type === 'numberInput'" :small="size === 'small'" :model-value="c.default" type="number" @update:model-value="c.onInput">
+ <template v-if="c.label" #label>{{ c.label }}</template>
+ <template v-if="c.caption" #caption>{{ c.caption }}</template>
+ </MkInput>
+ <MkSelect v-else-if="c.type === 'select'" :small="size === 'small'" :model-value="c.default" @update:model-value="c.onChange">
+ <template v-if="c.label" #label>{{ c.label }}</template>
+ <template v-if="c.caption" #caption>{{ c.caption }}</template>
+ <option v-for="item in c.items" :key="item.value" :value="item.value">{{ item.text }}</option>
+ </MkSelect>
+ <MkButton v-else-if="c.type === 'postFormButton'" :primary="c.primary" :rounded="c.rounded" :small="size === 'small'" @click="openPostForm">{{ c.text }}</MkButton>
+ <div v-else-if="c.type === 'container'" :class="[$style.container, { [$style.fontSerif]: c.font === 'serif', [$style.fontMonospace]: c.font === 'monospace', [$style.containerCenter]: c.align === 'center' }]" :style="{ backgroundColor: c.bgColor ?? null, color: c.fgColor ?? null, borderWidth: c.borderWidth ? `${c.borderWidth}px` : 0, borderColor: c.borderColor ?? 'var(--divider)', padding: c.padding ? `${c.padding}px` : 0, borderRadius: c.rounded ? '8px' : 0 }">
+ <template v-for="child in c.children" :key="child">
+ <MkAsUi v-if="!g(child).hidden" :component="g(child)" :components="props.components" :size="size"/>
+ </template>
+ </div>
+</div>
+</template>
+
+<script lang="ts" setup>
+import { computed, defineAsyncComponent, onMounted, onUnmounted, Ref } from 'vue';
+import * as os from '@/os';
+import MkButton from '@/components/MkButton.vue';
+import MkInput from '@/components/form/input.vue';
+import MkSwitch from '@/components/form/switch.vue';
+import MkTextarea from '@/components/form/textarea.vue';
+import MkSelect from '@/components/form/select.vue';
+import { AsUiComponent } from '@/scripts/aiscript/ui';
+
+const props = withDefaults(defineProps<{
+ component: AsUiComponent;
+ components: Ref<AsUiComponent>[];
+ size: 'small' | 'medium' | 'large';
+}>(), {
+ size: 'medium',
+});
+
+const c = props.component;
+
+function g(id) {
+ return props.components.find(x => x.value.id === id).value;
+}
+
+let valueForSwitch = $ref(c.default ?? false);
+
+function onSwitchUpdate(v) {
+ valueForSwitch = v;
+ if (c.onChange) c.onChange(v);
+}
+
+function openPostForm() {
+ os.post({
+ initialText: c.form.text,
+ instant: true,
+ });
+}
+</script>
+
+<style lang="scss" module>
+.root {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.container {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.containerCenter {
+ text-align: center;
+}
+
+.fontSerif {
+ font-family: serif;
+}
+
+.fontMonospace {
+ font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
+}
+</style>
diff --git a/packages/frontend/src/components/MkButton.vue b/packages/frontend/src/components/MkButton.vue
index daf47e12d4..f9602de787 100644
--- a/packages/frontend/src/components/MkButton.vue
+++ b/packages/frontend/src/components/MkButton.vue
@@ -2,7 +2,7 @@
<button
v-if="!link"
ref="el" class="bghgjjyj _button"
- :class="{ inline, primary, gradate, danger, rounded, full, small }"
+ :class="{ inline, primary, gradate, danger, rounded, full, small, large, asLike }"
:type="type"
@click="emit('click', $event)"
@mousedown="onMousedown"
@@ -41,6 +41,8 @@ const props = defineProps<{
danger?: boolean;
full?: boolean;
small?: boolean;
+ large?: boolean;
+ asLike?: boolean;
}>();
const emit = defineEmits<{
@@ -131,6 +133,11 @@ function onMousedown(evt: MouseEvent): void {
padding: 6px 12px;
}
+ &.large {
+ font-size: 100%;
+ padding: 8px 16px;
+ }
+
&.full {
width: 100%;
}
@@ -153,6 +160,37 @@ function onMousedown(evt: MouseEvent): void {
}
}
+ &.asLike {
+ background: rgba(255, 86, 125, 0.07);
+ color: #ff002f;
+
+ &:not(:disabled):hover {
+ background: rgba(255, 74, 116, 0.11);
+ }
+
+ &:not(:disabled):active {
+ background: rgba(224, 57, 96, 0.125);
+ }
+
+ > .ripples {
+ ::v-deep(div) {
+ background: rgba(255, 60, 106, 0.15);
+ }
+ }
+
+ &.primary {
+ background: rgb(241 97 132);
+
+ &:not(:disabled):hover {
+ background: rgb(241 92 128);
+ }
+
+ &:not(:disabled):active {
+ background: rgb(241 92 128);
+ }
+ }
+ }
+
&.gradate {
font-weight: bold;
color: var(--fgOnAccent) !important;
diff --git a/packages/frontend/src/components/MkChartLegend.vue b/packages/frontend/src/components/MkChartLegend.vue
index f33f753723..8d2a2be8e8 100644
--- a/packages/frontend/src/components/MkChartLegend.vue
+++ b/packages/frontend/src/components/MkChartLegend.vue
@@ -59,7 +59,7 @@ defineExpose({
&.disabled {
text-decoration: line-through;
- opacity: 0.6;
+ opacity: 0.5;
}
> .box {
diff --git a/packages/frontend/src/components/MkFlashPreview.vue b/packages/frontend/src/components/MkFlashPreview.vue
new file mode 100644
index 0000000000..1a82ffe5ab
--- /dev/null
+++ b/packages/frontend/src/components/MkFlashPreview.vue
@@ -0,0 +1,112 @@
+<template>
+<MkA :to="`/play/${flash.id}`" class="vhpxefrk _block" tabindex="-1">
+ <article>
+ <header>
+ <h1 :title="flash.title">{{ flash.title }}</h1>
+ </header>
+ <p v-if="flash.summary" :title="flash.summary">{{ flash.summary.length > 85 ? flash.summary.slice(0, 85) + '…' : flash.summary }}</p>
+ <footer>
+ <img class="icon" :src="flash.user.avatarUrl"/>
+ <p>{{ userName(flash.user) }}</p>
+ </footer>
+ </article>
+</MkA>
+</template>
+
+<script lang="ts" setup>
+import { } from 'vue';
+import * as misskey from 'misskey-js';
+import { userName } from '@/filters/user';
+import * as os from '@/os';
+
+const props = defineProps<{
+ //flash: misskey.entities.Flash;
+ flash: any;
+}>();
+</script>
+
+<style lang="scss" scoped>
+.vhpxefrk {
+ display: block;
+
+ &:hover {
+ text-decoration: none;
+ color: var(--accent);
+ }
+
+ > article {
+ padding: 16px;
+
+ > header {
+ margin-bottom: 8px;
+
+ > h1 {
+ margin: 0;
+ font-size: 1em;
+ color: var(--urlPreviewTitle);
+ }
+ }
+
+ > p {
+ margin: 0;
+ color: var(--urlPreviewText);
+ font-size: 0.8em;
+ }
+
+ > footer {
+ margin-top: 8px;
+ height: 16px;
+
+ > img {
+ display: inline-block;
+ width: 16px;
+ height: 16px;
+ margin-right: 4px;
+ vertical-align: top;
+ }
+
+ > p {
+ display: inline-block;
+ margin: 0;
+ color: var(--urlPreviewInfo);
+ font-size: 0.8em;
+ line-height: 16px;
+ vertical-align: top;
+ }
+ }
+ }
+
+ @media (max-width: 700px) {
+ }
+
+ @media (max-width: 550px) {
+ font-size: 12px;
+
+ > article {
+ padding: 12px;
+ }
+ }
+
+ @media (max-width: 500px) {
+ font-size: 10px;
+
+ > article {
+ padding: 8px;
+
+ > header {
+ margin-bottom: 4px;
+ }
+
+ > footer {
+ margin-top: 4px;
+
+ > img {
+ width: 12px;
+ height: 12px;
+ }
+ }
+ }
+ }
+}
+
+</style>
diff --git a/packages/frontend/src/components/MkLaunchPad.vue b/packages/frontend/src/components/MkLaunchPad.vue
index 3ea90712a0..aab7631e36 100644
--- a/packages/frontend/src/components/MkLaunchPad.vue
+++ b/packages/frontend/src/components/MkLaunchPad.vue
@@ -50,7 +50,7 @@ const menu = defaultStore.state.menu;
const items = Object.keys(navbarItemDef).filter(k => !menu.includes(k)).map(k => navbarItemDef[k]).filter(def => def.show == null ? true : def.show).map(def => ({
type: def.to ? 'link' : 'button',
- text: i18n.ts[def.title],
+ text: def.title,
icon: def.icon,
to: def.to,
action: def.action,
diff --git a/packages/frontend/src/components/MkPagePreview.vue b/packages/frontend/src/components/MkPagePreview.vue
index 009582e540..1eb61d4344 100644
--- a/packages/frontend/src/components/MkPagePreview.vue
+++ b/packages/frontend/src/components/MkPagePreview.vue
@@ -14,22 +14,15 @@
</MkA>
</template>
-<script lang="ts">
-import { defineComponent } from 'vue';
+<script lang="ts" setup>
+import { } from 'vue';
+import * as misskey from 'misskey-js';
import { userName } from '@/filters/user';
import * as os from '@/os';
-export default defineComponent({
- props: {
- page: {
- type: Object,
- required: true,
- },
- },
- methods: {
- userName,
- },
-});
+const props = defineProps<{
+ page: misskey.entities.Page;
+}>();
</script>
<style lang="scss" scoped>
diff --git a/packages/frontend/src/components/form/select.vue b/packages/frontend/src/components/form/select.vue
index c8cdd9e508..068ca2ebc6 100644
--- a/packages/frontend/src/components/form/select.vue
+++ b/packages/frontend/src/components/form/select.vue
@@ -126,7 +126,7 @@ const onClick = (ev: MouseEvent) => {
const pushOption = (option: VNode) => {
menu.push({
text: option.children,
- active: v.value === option.props.value,
+ active: computed(() => v.value === option.props.value),
action: () => {
v.value = option.props.value;
},