Compare commits
12 Commits
Author | SHA1 | Date | |
---|---|---|---|
f0c4df1cc5 | |||
839784bc8c | |||
b758ec96ef | |||
2f8ceb9d22 | |||
e05ae5ebc2 | |||
ebc43be4b3 | |||
8543278ce3 | |||
9a98de7bd8 | |||
e1d69fb4ad | |||
946f9b4a2b | |||
9a270e59a4 | |||
2112fb3896 |
@ -974,6 +974,7 @@ _widgets:
|
||||
digitalClock: "Digitaluhr"
|
||||
federation: "Föderation"
|
||||
postForm: "Neue Notiz anfertigen"
|
||||
slideshow: "Diashow"
|
||||
_cw:
|
||||
hide: "Ausblenden"
|
||||
show: "Mehr anzeigen"
|
||||
|
@ -974,6 +974,7 @@ _widgets:
|
||||
digitalClock: "Digital clock"
|
||||
federation: "Federation"
|
||||
postForm: "Compose a note"
|
||||
slideshow: "Slideshow"
|
||||
_cw:
|
||||
hide: "Hide"
|
||||
show: "Load more"
|
||||
|
@ -995,6 +995,7 @@ _widgets:
|
||||
digitalClock: "デジタル時計"
|
||||
federation: "連合"
|
||||
postForm: "投稿フォーム"
|
||||
slideshow: "スライドショー"
|
||||
|
||||
_cw:
|
||||
hide: "隠す"
|
||||
|
@ -95,6 +95,7 @@ sensitive: "Содержимое не для всех"
|
||||
add: "Добавить"
|
||||
reaction: "Реакции"
|
||||
reactionSettingDescription: "Подберите, что будет у вас в палитре реакций"
|
||||
reactionSettingDescription2: "Расставляйте перетаскиванием, удаляйте нажатием, добавляйте кнопкой «+»."
|
||||
rememberNoteVisibility: "Запоминать видимость заметок"
|
||||
attachCancel: "Удалить вложение"
|
||||
markAsSensitive: "Отметить как «не для всех»"
|
||||
@ -319,6 +320,7 @@ pinnedUsers: "Прикреплённый пользователь"
|
||||
pinnedUsersDescription: "Перечислите по одному имени пользователя в строке. Пользователи, перечисленные здесь, будут привязаны к закладке \"Изучение\"."
|
||||
pinnedPages: "Закрепленные страницы"
|
||||
pinnedPagesDescription: "Если хотите закрепить страницы на главной сайта, сюда можно добавить пути к ним, каждый в отдельной строке."
|
||||
pinnedClipId: "Идентификатор закреплённой памятки"
|
||||
pinnedNotes: "Закреплённая заметка"
|
||||
hcaptcha: "hCaptcha"
|
||||
enableHcaptcha: "Включить hCaptcha"
|
||||
@ -972,6 +974,7 @@ _widgets:
|
||||
digitalClock: "Цифровые часы"
|
||||
federation: "Федерация"
|
||||
postForm: "Форма отправки"
|
||||
slideshow: "Показ слайдов"
|
||||
_cw:
|
||||
hide: "Спрятать"
|
||||
show: "Показать еще"
|
||||
|
@ -819,32 +819,62 @@ _pages:
|
||||
arg2: "Списки"
|
||||
_pick:
|
||||
arg1: "Списки"
|
||||
arg2: "Позиція"
|
||||
listLen: "Отримати довжину списку"
|
||||
_listLen:
|
||||
arg1: "Списки"
|
||||
number: "Число"
|
||||
stringToNumber: "Текст на число"
|
||||
_stringToNumber:
|
||||
arg1: "Текст"
|
||||
numberToString: "Число на текст"
|
||||
_numberToString:
|
||||
arg1: "Число"
|
||||
splitStrByLine: "Розбиття тексту на рядки"
|
||||
_splitStrByLine:
|
||||
arg1: "Текст"
|
||||
ref: "Змінні"
|
||||
aiScriptVar: "Змінна AiScript"
|
||||
fn: "Функції"
|
||||
_fn:
|
||||
arg1: "Вихід"
|
||||
arg1: "Вивід"
|
||||
for: "Повторення"
|
||||
_for:
|
||||
arg1: "Кількість повторень"
|
||||
arg2: "Дія"
|
||||
types:
|
||||
string: "Текст"
|
||||
number: "Число"
|
||||
boolean: "Прапорець"
|
||||
array: "Списки"
|
||||
_relayStatus:
|
||||
requesting: "Очікує затвердження"
|
||||
accepted: "Затверджено"
|
||||
rejected: "Відхилено"
|
||||
_notification:
|
||||
fileUploaded: "Файл успішно завантажено"
|
||||
youGotMention: "{name} згадує вас"
|
||||
youGotReply: "{name} відповідає"
|
||||
youGotQuote: "{name} цитує вас"
|
||||
youRenoted: "{name} поширює"
|
||||
youGotPoll: "{name} бере участь в опитуванні"
|
||||
youGotMessagingMessageFromUser: "Повідомлення від {name}"
|
||||
youGotMessagingMessageFromGroup: "Нове повідомлення в групі {name}"
|
||||
youWereFollowed: "Новий підписник"
|
||||
youReceivedFollowRequest: "Ви отримали запит на підписку"
|
||||
yourFollowRequestAccepted: "Запит на підписку прийнято"
|
||||
youWereInvitedToGroup: "Запрошення до групи"
|
||||
_types:
|
||||
all: "Все"
|
||||
follow: "Підписки"
|
||||
mention: "Згадка"
|
||||
renote: "Поширити"
|
||||
quote: "Цитата"
|
||||
reply: "Відповіді"
|
||||
renote: "Поширення"
|
||||
quote: "Цитування"
|
||||
reaction: "Реакції"
|
||||
pollVote: "Опитування"
|
||||
receiveFollowRequest: "Запит на підписку"
|
||||
followRequestAccepted: "Прийнята підписка"
|
||||
receiveFollowRequest: "Запити на підписку"
|
||||
followRequestAccepted: "Прийняті підписки"
|
||||
groupInvited: "Запрошення до груп"
|
||||
app: "Сповіщення від додатків"
|
||||
_deck:
|
||||
|
@ -974,6 +974,7 @@ _widgets:
|
||||
digitalClock: "数字时钟"
|
||||
federation: "联邦宇宙"
|
||||
postForm: "投稿窗口"
|
||||
slideshow: "幻灯片展示"
|
||||
_cw:
|
||||
hide: "隐藏"
|
||||
show: "查看更多"
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "misskey",
|
||||
"author": "syuilo <syuilotan@yahoo.co.jp>",
|
||||
"version": "12.62.0",
|
||||
"version": "12.62.2",
|
||||
"codename": "indigo",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -74,6 +74,7 @@
|
||||
"@types/koa__multer": "2.0.2",
|
||||
"@types/koa__router": "8.0.2",
|
||||
"@types/markdown-it": "10.0.3",
|
||||
"@types/matter-js": "0.14.7",
|
||||
"@types/mocha": "7.0.2",
|
||||
"@types/node": "14.0.22",
|
||||
"@types/node-fetch": "2.5.7",
|
||||
@ -175,6 +176,7 @@
|
||||
"lookup-dns-cache": "2.1.0",
|
||||
"markdown-it": "11.0.1",
|
||||
"markdown-it-anchor": "6.0.1",
|
||||
"matter-js": "0.14.2",
|
||||
"mocha": "8.2.1",
|
||||
"moji": "0.5.1",
|
||||
"ms": "2.1.2",
|
||||
|
@ -1,50 +1,54 @@
|
||||
<template>
|
||||
<FormBase class="znqjceqz">
|
||||
<section class="_formItem">
|
||||
<div class="_formPanel" style="text-align: center; padding: 16px;">
|
||||
<img src="/assets/icons/512.png" alt="" style="display: block; width: 100px; margin: 0 auto; border-radius: 16px;" ref="icon"/>
|
||||
<div style="margin-top: 0.75em;">Misskey</div>
|
||||
<div style="opacity: 0.5;">v{{ version }}</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="_formItem" style="text-align: center; padding: 0 16px;">
|
||||
{{ $t('_aboutMisskey.about') }}
|
||||
</section>
|
||||
<FormGroup>
|
||||
<FormLink to="https://github.com/syuilo/misskey" external>
|
||||
<template #icon><Fa :icon="faCode"/></template>
|
||||
{{ $t('_aboutMisskey.source') }}
|
||||
<template #suffix>GitHub</template>
|
||||
</FormLink>
|
||||
<FormLink to="https://crowdin.com/project/misskey" external>
|
||||
<template #icon><Fa :icon="faLanguage"/></template>
|
||||
{{ $t('_aboutMisskey.translation') }}
|
||||
<template #suffix>Crowdin</template>
|
||||
</FormLink>
|
||||
<FormLink to="https://www.patreon.com/syuilo" external>
|
||||
<template #icon><Fa :icon="faHandHoldingMedical"/></template>
|
||||
{{ $t('_aboutMisskey.donate') }}
|
||||
<template #suffix>Patreon</template>
|
||||
</FormLink>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<template #label>{{ $t('_aboutMisskey.contributors') }}</template>
|
||||
<FormLink to="https://github.com/syuilo" external>@syuilo</FormLink>
|
||||
<FormLink to="https://github.com/AyaMorisawa" external>@AyaMorisawa</FormLink>
|
||||
<FormLink to="https://github.com/mei23" external>@mei23</FormLink>
|
||||
<FormLink to="https://github.com/acid-chicken" external>@acid-chicken</FormLink>
|
||||
<FormLink to="https://github.com/tamaina" external>@tamaina</FormLink>
|
||||
<FormLink to="https://github.com/rinsuki" external>@rinsuki</FormLink>
|
||||
<FormLink to="https://github.com/Xeltica" external>@Xeltica</FormLink>
|
||||
<FormLink to="https://github.com/u1-liquid" external>@u1-liquid</FormLink>
|
||||
<template #caption><MkLink url="https://github.com/syuilo/misskey/graphs/contributors">{{ $t('_aboutMisskey.allContributors') }}</MkLink></template>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<template #label><Mfm text="[jelly ❤]"/> {{ $t('_aboutMisskey.patrons') }}</template>
|
||||
<FormKeyValueView v-for="patron in patrons" :key="patron"><template #key>{{ patron }}</template></FormKeyValueView>
|
||||
<template #caption>{{ $t('_aboutMisskey.morePatrons') }}</template>
|
||||
</FormGroup>
|
||||
</FormBase>
|
||||
<div style="overflow: hidden;">
|
||||
<FormBase class="znqjceqz">
|
||||
<div id="debug"></div>
|
||||
<section class="_formItem">
|
||||
<div class="_formPanel" style="text-align: center; padding: 16px;" ref="about">
|
||||
<img src="/assets/icons/512.png" alt="" style="display: block; width: 100px; margin: 0 auto; border-radius: 16px;" ref="icon" @load="iconLoaded" draggable="false"/>
|
||||
<div style="margin: 0.75em auto 0 auto; width: max-content;">Misskey</div>
|
||||
<div style="margin: 0 auto; opacity: 0.5; width: max-content;">v{{ version }}</div>
|
||||
<span v-for="emoji in easterEggEmojis" :key="emoji.emoji" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }" :style="{ position: 'absolute', top: emoji.top, left: emoji.left, userSelect: 'none' }"><MkEmoji style="pointer-events: none; font-size: 24px; width: 24px;" :emoji="emoji.emoji" :custom-emojis="$store.state.instance.meta.emojis" :is-reaction="false" :normal="true" :no-style="true"/></span>
|
||||
</div>
|
||||
</section>
|
||||
<section class="_formItem" style="text-align: center; padding: 0 16px;" @click="gravity">
|
||||
{{ $t('_aboutMisskey.about') }}
|
||||
</section>
|
||||
<FormGroup>
|
||||
<FormLink to="https://github.com/syuilo/misskey" external>
|
||||
<template #icon><Fa :icon="faCode"/></template>
|
||||
{{ $t('_aboutMisskey.source') }}
|
||||
<template #suffix>GitHub</template>
|
||||
</FormLink>
|
||||
<FormLink to="https://crowdin.com/project/misskey" external>
|
||||
<template #icon><Fa :icon="faLanguage"/></template>
|
||||
{{ $t('_aboutMisskey.translation') }}
|
||||
<template #suffix>Crowdin</template>
|
||||
</FormLink>
|
||||
<FormLink to="https://www.patreon.com/syuilo" external>
|
||||
<template #icon><Fa :icon="faHandHoldingMedical"/></template>
|
||||
{{ $t('_aboutMisskey.donate') }}
|
||||
<template #suffix>Patreon</template>
|
||||
</FormLink>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<template #label>{{ $t('_aboutMisskey.contributors') }}</template>
|
||||
<FormLink to="https://github.com/syuilo" external>@syuilo</FormLink>
|
||||
<FormLink to="https://github.com/AyaMorisawa" external>@AyaMorisawa</FormLink>
|
||||
<FormLink to="https://github.com/mei23" external>@mei23</FormLink>
|
||||
<FormLink to="https://github.com/acid-chicken" external>@acid-chicken</FormLink>
|
||||
<FormLink to="https://github.com/tamaina" external>@tamaina</FormLink>
|
||||
<FormLink to="https://github.com/rinsuki" external>@rinsuki</FormLink>
|
||||
<FormLink to="https://github.com/Xeltica" external>@Xeltica</FormLink>
|
||||
<FormLink to="https://github.com/u1-liquid" external>@u1-liquid</FormLink>
|
||||
<template #caption><MkLink url="https://github.com/syuilo/misskey/graphs/contributors">{{ $t('_aboutMisskey.allContributors') }}</MkLink></template>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<template #label><Mfm text="[jelly ❤]"/> {{ $t('_aboutMisskey.patrons') }}</template>
|
||||
<FormKeyValueView v-for="patron in patrons" :key="patron"><template #key>{{ patron }}</template></FormKeyValueView>
|
||||
<template #caption>{{ $t('_aboutMisskey.morePatrons') }}</template>
|
||||
</FormGroup>
|
||||
</FormBase>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
@ -57,6 +61,7 @@ import FormBase from '@/components/form/base.vue';
|
||||
import FormGroup from '@/components/form/group.vue';
|
||||
import FormKeyValueView from '@/components/form/key-value-view.vue';
|
||||
import MkLink from '@/components/link.vue';
|
||||
import { physics } from '@/scripts/physics.ts';
|
||||
import * as os from '@/os';
|
||||
|
||||
const patrons = [
|
||||
@ -115,10 +120,24 @@ export default defineComponent({
|
||||
},
|
||||
version,
|
||||
patrons,
|
||||
easterEggReady: false,
|
||||
easterEggEmojis: [],
|
||||
easterEggEngine: null,
|
||||
faInfoCircle, faCode, faLanguage, faHandHoldingMedical,
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
const emojis = this.$store.state.settings.reactions;
|
||||
for (let i = 0; i < 32; i++) {
|
||||
this.easterEggEmojis.push({
|
||||
top: -(32 + (Math.random() * 256)) + 'px',
|
||||
left: (Math.random() * 99) + '%',
|
||||
emoji: emojis[Math.floor(Math.random() * emojis.length)],
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
VanillaTilt.init(this.$refs.icon, {
|
||||
max: 30,
|
||||
@ -127,6 +146,27 @@ export default defineComponent({
|
||||
speed: 1000,
|
||||
});
|
||||
},
|
||||
|
||||
beforeUnmount() {
|
||||
if (this.easterEggEngine) {
|
||||
this.easterEggEngine.stop();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
iconLoaded() {
|
||||
this.$nextTick(() => {
|
||||
this.easterEggReady = true;
|
||||
});
|
||||
},
|
||||
|
||||
gravity() {
|
||||
if (!this.easterEggReady) return;
|
||||
this.easterEggReady = false;
|
||||
this.$refs.icon.vanillaTilt.destroy();
|
||||
this.easterEggEngine = physics(this.$refs.about);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -24,7 +24,7 @@
|
||||
</div>
|
||||
<div class="_section">
|
||||
<div class="_content">
|
||||
<MkSwitch v-if="user.host == null && $store.state.i.isAdmin && (this.moderator || !user.isAdmin)" @update:value="toggleModerator" v-model:value="moderator">{{ $t('moderator') }}</MkSwitch>
|
||||
<MkSwitch v-if="user.host == null && $store.state.i.isAdmin && (moderator || !user.isAdmin)" @update:value="toggleModerator" v-model:value="moderator">{{ $t('moderator') }}</MkSwitch>
|
||||
<MkSwitch @update:value="toggleSilence" v-model:value="silenced">{{ $t('silence') }}</MkSwitch>
|
||||
<MkSwitch @update:value="toggleSuspend" v-model:value="suspended">{{ $t('suspend') }}</MkSwitch>
|
||||
</div>
|
||||
|
148
src/client/scripts/physics.ts
Normal file
148
src/client/scripts/physics.ts
Normal file
@ -0,0 +1,148 @@
|
||||
import * as Matter from 'matter-js';
|
||||
|
||||
export function physics(container: HTMLElement) {
|
||||
const containerWidth = container.offsetWidth;
|
||||
const containerHeight = container.offsetHeight;
|
||||
const containerCenterX = containerWidth / 2;
|
||||
|
||||
// サイズ固定化(要らないかも?)
|
||||
container.style.position = 'relative';
|
||||
container.style.boxSizing = 'border-box';
|
||||
container.style.width = `${containerWidth}px`;
|
||||
container.style.height = `${containerHeight}px`;
|
||||
|
||||
// create engine
|
||||
const engine = Matter.Engine.create({
|
||||
constraintIterations: 4,
|
||||
positionIterations: 8,
|
||||
velocityIterations: 8,
|
||||
});
|
||||
|
||||
const world = engine.world;
|
||||
|
||||
// create renderer
|
||||
const render = Matter.Render.create({
|
||||
engine: engine,
|
||||
//element: document.getElementById('debug'),
|
||||
options: {
|
||||
width: containerWidth,
|
||||
height: containerHeight,
|
||||
background: 'transparent', // transparent to hide
|
||||
wireframeBackground: 'transparent', // transparent to hide
|
||||
}
|
||||
});
|
||||
|
||||
// Disable to hide debug
|
||||
Matter.Render.run(render);
|
||||
|
||||
// create runner
|
||||
const runner = Matter.Runner.create();
|
||||
Matter.Runner.run(runner, engine);
|
||||
|
||||
const groundThickness = 1024;
|
||||
const ground = Matter.Bodies.rectangle(containerCenterX, containerHeight + (groundThickness / 2), containerWidth, groundThickness, {
|
||||
isStatic: true,
|
||||
restitution: 0.1,
|
||||
friction: 2
|
||||
});
|
||||
|
||||
//const wallRight = Matter.Bodies.rectangle(window.innerWidth+50, window.innerHeight/2, 100, window.innerHeight, wallopts);
|
||||
//const wallLeft = Matter.Bodies.rectangle(-50, window.innerHeight/2, 100, window.innerHeight, wallopts);
|
||||
|
||||
Matter.World.add(world, [
|
||||
ground,
|
||||
//wallRight,
|
||||
//wallLeft,
|
||||
]);
|
||||
|
||||
const objEls = Array.from(container.children);
|
||||
const objs = [];
|
||||
for (const objEl of objEls) {
|
||||
let obj;
|
||||
if (objEl.classList.contains('_physics_circle_')) {
|
||||
obj = Matter.Bodies.circle(
|
||||
objEl.offsetLeft + (objEl.offsetWidth / 2),
|
||||
objEl.offsetTop + (objEl.offsetHeight / 2),
|
||||
Math.max(objEl.offsetWidth, objEl.offsetHeight) / 2,
|
||||
);
|
||||
} else {
|
||||
const style = window.getComputedStyle(objEl);
|
||||
obj = Matter.Bodies.rectangle(
|
||||
objEl.offsetLeft + (objEl.offsetWidth / 2),
|
||||
objEl.offsetTop + (objEl.offsetHeight / 2),
|
||||
objEl.offsetWidth,
|
||||
objEl.offsetHeight,
|
||||
{
|
||||
chamfer: { radius: parseInt(style.borderRadius, 10) },
|
||||
}
|
||||
);
|
||||
}
|
||||
objEl.id = obj.id;
|
||||
objs.push(obj);
|
||||
}
|
||||
|
||||
Matter.World.add(engine.world, objs);
|
||||
|
||||
// Add mouse control
|
||||
|
||||
const mouse = Matter.Mouse.create(container);
|
||||
const mouseConstraint = Matter.MouseConstraint.create(engine, {
|
||||
mouse: mouse,
|
||||
constraint: {
|
||||
stiffness: 0.05,
|
||||
render: {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Matter.World.add(engine.world, mouseConstraint);
|
||||
|
||||
// keep the mouse in sync with rendering
|
||||
render.mouse = mouse;
|
||||
|
||||
for (const objEl of objEls) {
|
||||
objEl.style.position = `absolute`;
|
||||
objEl.style.top = 0;
|
||||
objEl.style.left = 0;
|
||||
objEl.style.margin = 0;
|
||||
objEl.style.userSelect = 'none';
|
||||
objEl.style.willChange = 'transform';
|
||||
}
|
||||
|
||||
window.requestAnimationFrame(update);
|
||||
|
||||
let stop = false;
|
||||
|
||||
function update() {
|
||||
for (const objEl of objEls) {
|
||||
const obj = objs.find(obj => obj.id.toString() === objEl.id.toString());
|
||||
if (obj == null) continue;
|
||||
|
||||
const x = (obj.position.x - objEl.offsetWidth / 2);
|
||||
const y = (obj.position.y - objEl.offsetHeight / 2);
|
||||
const angle = obj.angle;
|
||||
|
||||
objEl.style.transform = `translate(${x}px, ${y}px) rotate(${angle}rad)`;
|
||||
}
|
||||
|
||||
if (!stop) {
|
||||
window.requestAnimationFrame(update);
|
||||
}
|
||||
}
|
||||
|
||||
// 奈落に落ちたオブジェクトは消す
|
||||
const intervalId = setInterval(() => {
|
||||
for (const obj of objs) {
|
||||
if (obj.position.y > (containerHeight + 1024)) Matter.World.remove(world, obj);
|
||||
}
|
||||
}, 1000 * 10);
|
||||
|
||||
return {
|
||||
stop: () => {
|
||||
stop = true;
|
||||
Matter.Runner.stop(runner);
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
};
|
||||
}
|
@ -228,6 +228,12 @@ export default defineComponent({
|
||||
> .title {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
> .content {
|
||||
> img {
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ export default function(app: App) {
|
||||
app.component('MkwDigitalClock', defineAsyncComponent(() => import('./digital-clock.vue')));
|
||||
app.component('MkwFederation', defineAsyncComponent(() => import('./federation.vue')));
|
||||
app.component('MkwPostForm', defineAsyncComponent(() => import('./post-form.vue')));
|
||||
app.component('MkwSlideshow', defineAsyncComponent(() => import('./slideshow.vue')));
|
||||
}
|
||||
|
||||
export const widgets = [
|
||||
@ -28,4 +29,5 @@ export const widgets = [
|
||||
'digitalClock',
|
||||
'federation',
|
||||
'postForm',
|
||||
'slideshow',
|
||||
];
|
||||
|
168
src/client/widgets/slideshow.vue
Normal file
168
src/client/widgets/slideshow.vue
Normal file
@ -0,0 +1,168 @@
|
||||
<template>
|
||||
<div class="kvausudm _panel">
|
||||
<div @click="choose">
|
||||
<p v-if="props.folderId == null">
|
||||
<template v-if="isCustomizeMode">{{ $t('folder-customize-mode') }}</template>
|
||||
<template v-else>{{ $t('folder') }}</template>
|
||||
</p>
|
||||
<p v-if="props.folderId != null && images.length === 0 && !fetching">{{ $t('no-image') }}</p>
|
||||
<div ref="slideA" class="slide a"></div>
|
||||
<div ref="slideB" class="slide b"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { } from '@fortawesome/free-solid-svg-icons';
|
||||
import define from './define';
|
||||
import * as os from '@/os';
|
||||
|
||||
const widget = define({
|
||||
name: 'slideshow',
|
||||
props: () => ({
|
||||
height: {
|
||||
type: 'number',
|
||||
default: 300,
|
||||
},
|
||||
folderId: {
|
||||
type: 'string',
|
||||
default: null,
|
||||
hidden: true,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
export default defineComponent({
|
||||
extends: widget,
|
||||
data() {
|
||||
return {
|
||||
images: [],
|
||||
fetching: true,
|
||||
clock: null
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.$nextTick(() => {
|
||||
this.applySize();
|
||||
});
|
||||
|
||||
if (this.props.folderId != null) {
|
||||
this.fetch();
|
||||
}
|
||||
|
||||
this.clock = setInterval(this.change, 10000);
|
||||
},
|
||||
beforeUnmount() {
|
||||
clearInterval(this.clock);
|
||||
},
|
||||
methods: {
|
||||
applySize() {
|
||||
let h;
|
||||
|
||||
if (this.props.size == 1) {
|
||||
h = 250;
|
||||
} else {
|
||||
h = 170;
|
||||
}
|
||||
|
||||
this.$el.style.height = `${h}px`;
|
||||
},
|
||||
resize() {
|
||||
if (this.props.size == 1) {
|
||||
this.props.size = 0;
|
||||
} else {
|
||||
this.props.size++;
|
||||
}
|
||||
this.save();
|
||||
|
||||
this.applySize();
|
||||
},
|
||||
change() {
|
||||
if (this.images.length == 0) return;
|
||||
|
||||
const index = Math.floor(Math.random() * this.images.length);
|
||||
const img = `url(${ this.images[index].url })`;
|
||||
|
||||
(this.$refs.slideB as any).style.backgroundImage = img;
|
||||
|
||||
this.$refs.slideB.classList.add('anime');
|
||||
setTimeout(() => {
|
||||
// 既にこのウィジェットがunmountされていたら要素がない
|
||||
if ((this.$refs.slideA as any) == null) return;
|
||||
|
||||
(this.$refs.slideA as any).style.backgroundImage = img;
|
||||
|
||||
this.$refs.slideB.classList.remove('anime');
|
||||
}, 1000);
|
||||
},
|
||||
fetch() {
|
||||
this.fetching = true;
|
||||
|
||||
os.api('drive/files', {
|
||||
folderId: this.props.folderId,
|
||||
type: 'image/*',
|
||||
limit: 100
|
||||
}).then(images => {
|
||||
this.images = images;
|
||||
this.fetching = false;
|
||||
(this.$refs.slideA as any).style.backgroundImage = '';
|
||||
(this.$refs.slideB as any).style.backgroundImage = '';
|
||||
this.change();
|
||||
});
|
||||
},
|
||||
choose() {
|
||||
os.selectDriveFolder(false).then(folder => {
|
||||
if (folder == null) {
|
||||
return;
|
||||
}
|
||||
this.props.folderId = folder.id;
|
||||
this.save();
|
||||
this.fetch();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.kvausudm {
|
||||
position: relative;
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
cursor: pointer;
|
||||
|
||||
> p {
|
||||
display: block;
|
||||
margin: 1em;
|
||||
text-align: center;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
> * {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
> .slide {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
|
||||
&.b {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&.anime {
|
||||
transition: opacity 1s;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -142,6 +142,7 @@ export default define(meta, async (ps, me) => {
|
||||
enableServiceWorker: instance.enableServiceWorker,
|
||||
|
||||
...(ps.detail ? {
|
||||
pinnedPages: instance.pinnedPages,
|
||||
pinnedClipId: instance.pinnedClipId,
|
||||
cacheRemoteFiles: instance.cacheRemoteFiles,
|
||||
proxyRemoteFiles: instance.proxyRemoteFiles,
|
||||
|
10
yarn.lock
10
yarn.lock
@ -661,6 +661,11 @@
|
||||
"@types/mdurl" "*"
|
||||
highlight.js "^9.7.0"
|
||||
|
||||
"@types/matter-js@0.14.7":
|
||||
version "0.14.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/matter-js/-/matter-js-0.14.7.tgz#b816f1e7b441ee7499027f9566e4fb5baea637b3"
|
||||
integrity sha512-HLUhVTUoKsibpPZ2tCzoCC/f/UYRWPP9WCOUh5F61BlrUESFV5fE7eKq/CmdoEGkNrLW9v407zYlfrTc9hnGIw==
|
||||
|
||||
"@types/mdurl@*":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9"
|
||||
@ -6116,6 +6121,11 @@ material-colors@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/material-colors/-/material-colors-1.2.6.tgz#6d1958871126992ceecc72f4bcc4d8f010865f46"
|
||||
integrity sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==
|
||||
|
||||
matter-js@0.14.2:
|
||||
version "0.14.2"
|
||||
resolved "https://registry.yarnpkg.com/matter-js/-/matter-js-0.14.2.tgz#8169af9e06fdc356ba9e72b49624eb329839883b"
|
||||
integrity sha512-3ttVT8cJlQnGRjBa8MyVrGyvGmnmOkZ3YsyemIw+KwEEdVi70mo32FH1Eta2b3GfdDJFbMDRqyMQt4heNKBUEA==
|
||||
|
||||
mdn-data@2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
|
||||
|
Reference in New Issue
Block a user