enhance(client): RSSティッカーで表示順序をシャッフルできるように
This commit is contained in:
parent
165c4b2c00
commit
6f45208ab6
|
@ -12,6 +12,7 @@ You should also include the user name that made the change.
|
||||||
## 12.x.x (unreleased)
|
## 12.x.x (unreleased)
|
||||||
|
|
||||||
### Improvements
|
### Improvements
|
||||||
|
- RSSティッカーで表示順序をシャッフルできるように @syuilo
|
||||||
|
|
||||||
### Bugfixes
|
### Bugfixes
|
||||||
- クライアントが起動しなくなることがある問題を修正 @syuilo
|
- クライアントが起動しなくなることがある問題を修正 @syuilo
|
||||||
|
|
|
@ -888,6 +888,7 @@ enableAutoSensitive: "自動NSFW判定"
|
||||||
enableAutoSensitiveDescription: "利用可能な場合は、機械学習を利用して自動でメディアにNSFWフラグを設定します。この機能をオフにしても、インスタンスによっては自動で設定されることがあります。"
|
enableAutoSensitiveDescription: "利用可能な場合は、機械学習を利用して自動でメディアにNSFWフラグを設定します。この機能をオフにしても、インスタンスによっては自動で設定されることがあります。"
|
||||||
activeEmailValidationDescription: "ユーザーのメールアドレスのバリデーションを、捨てアドかどうかや実際に通信可能かどうかなどを判定しより積極的に行います。オフにすると単に文字列として正しいかどうかのみチェックされます。"
|
activeEmailValidationDescription: "ユーザーのメールアドレスのバリデーションを、捨てアドかどうかや実際に通信可能かどうかなどを判定しより積極的に行います。オフにすると単に文字列として正しいかどうかのみチェックされます。"
|
||||||
navbar: "ナビゲーションバー"
|
navbar: "ナビゲーションバー"
|
||||||
|
shuffle: "シャッフル"
|
||||||
|
|
||||||
_sensitiveMediaDetection:
|
_sensitiveMediaDetection:
|
||||||
description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てることができます。サーバーの負荷が少し増えます。"
|
description: "機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てることができます。サーバーの負荷が少し増えます。"
|
||||||
|
|
|
@ -28,6 +28,9 @@
|
||||||
<MkInput v-model="statusbar.props.url" manual-save class="_formBlock" type="url">
|
<MkInput v-model="statusbar.props.url" manual-save class="_formBlock" type="url">
|
||||||
<template #label>URL</template>
|
<template #label>URL</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
|
<MkSwitch v-model="statusbar.props.shuffle" class="_formBlock">
|
||||||
|
<template #label>{{ i18n.ts.shuffle }}</template>
|
||||||
|
</MkSwitch>
|
||||||
<MkInput v-model="statusbar.props.refreshIntervalSec" manual-save class="_formBlock" type="number">
|
<MkInput v-model="statusbar.props.refreshIntervalSec" manual-save class="_formBlock" type="number">
|
||||||
<template #label>{{ i18n.ts.refreshInterval }}</template>
|
<template #label>{{ i18n.ts.refreshInterval }}</template>
|
||||||
</MkInput>
|
</MkInput>
|
||||||
|
@ -100,6 +103,7 @@ watch(() => statusbar.type, () => {
|
||||||
if (statusbar.type === 'rss') {
|
if (statusbar.type === 'rss') {
|
||||||
statusbar.name = 'NEWS';
|
statusbar.name = 'NEWS';
|
||||||
statusbar.props.url = 'http://feeds.afpbb.com/rss/afpbb/afpbbnews';
|
statusbar.props.url = 'http://feeds.afpbb.com/rss/afpbb/afpbbnews';
|
||||||
|
statusbar.props.shuffle = true;
|
||||||
statusbar.props.refreshIntervalSec = 120;
|
statusbar.props.refreshIntervalSec = 120;
|
||||||
statusbar.props.display = 'marquee';
|
statusbar.props.display = 'marquee';
|
||||||
statusbar.props.marqueeDuration = 100;
|
statusbar.props.marqueeDuration = 100;
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
/**
|
||||||
|
* 配列をシャッフル (破壊的)
|
||||||
|
*/
|
||||||
|
export function shuffle<T extends any[]>(array: T): T {
|
||||||
|
let currentIndex = array.length, randomIndex;
|
||||||
|
|
||||||
|
// While there remain elements to shuffle.
|
||||||
|
while (currentIndex !== 0) {
|
||||||
|
// Pick a remaining element.
|
||||||
|
randomIndex = Math.floor(Math.random() * currentIndex);
|
||||||
|
currentIndex--;
|
||||||
|
|
||||||
|
// And swap it with the current element.
|
||||||
|
[array[currentIndex], array[randomIndex]] = [
|
||||||
|
array[randomIndex], array[currentIndex]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
|
@ -20,9 +20,11 @@ import { computed, defineAsyncComponent, ref, toRef, watch } from 'vue';
|
||||||
import MarqueeText from '@/components/marquee.vue';
|
import MarqueeText from '@/components/marquee.vue';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import { useInterval } from '@/scripts/use-interval';
|
import { useInterval } from '@/scripts/use-interval';
|
||||||
|
import { shuffle } from '@/scripts/shuffle';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
url?: string;
|
url?: string;
|
||||||
|
shuffle?: boolean;
|
||||||
display?: 'marquee' | 'oneByOne';
|
display?: 'marquee' | 'oneByOne';
|
||||||
marqueeDuration?: number;
|
marqueeDuration?: number;
|
||||||
marqueeReverse?: boolean;
|
marqueeReverse?: boolean;
|
||||||
|
@ -37,6 +39,9 @@ let key = $ref(0);
|
||||||
const tick = () => {
|
const tick = () => {
|
||||||
fetch(`/api/fetch-rss?url=${props.url}`, {}).then(res => {
|
fetch(`/api/fetch-rss?url=${props.url}`, {}).then(res => {
|
||||||
res.json().then(feed => {
|
res.json().then(feed => {
|
||||||
|
if (props.shuffle) {
|
||||||
|
shuffle(feed.items);
|
||||||
|
}
|
||||||
items.value = feed.items;
|
items.value = feed.items;
|
||||||
fetching.value = false;
|
fetching.value = false;
|
||||||
key++;
|
key++;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
}]"
|
}]"
|
||||||
>
|
>
|
||||||
<span class="name">{{ x.name }}</span>
|
<span class="name">{{ x.name }}</span>
|
||||||
<XRss v-if="x.type === 'rss'" class="body" :refresh-interval-sec="x.props.refreshIntervalSec" :marquee-duration="x.props.marqueeDuration" :marquee-reverse="x.props.marqueeReverse" :display="x.props.display" :url="x.props.url"/>
|
<XRss v-if="x.type === 'rss'" class="body" :refresh-interval-sec="x.props.refreshIntervalSec" :marquee-duration="x.props.marqueeDuration" :marquee-reverse="x.props.marqueeReverse" :display="x.props.display" :url="x.props.url" :shuffle="x.props.shuffle"/>
|
||||||
<XFederation v-else-if="x.type === 'federation'" class="body" :refresh-interval-sec="x.props.refreshIntervalSec" :marquee-duration="x.props.marqueeDuration" :marquee-reverse="x.props.marqueeReverse" :display="x.props.display" :colored="x.props.colored"/>
|
<XFederation v-else-if="x.type === 'federation'" class="body" :refresh-interval-sec="x.props.refreshIntervalSec" :marquee-duration="x.props.marqueeDuration" :marquee-reverse="x.props.marqueeReverse" :display="x.props.display" :colored="x.props.colored"/>
|
||||||
<XUserList v-else-if="x.type === 'userList'" class="body" :refresh-interval-sec="x.props.refreshIntervalSec" :marquee-duration="x.props.marqueeDuration" :marquee-reverse="x.props.marqueeReverse" :display="x.props.display" :user-list-id="x.props.userListId"/>
|
<XUserList v-else-if="x.type === 'userList'" class="body" :refresh-interval-sec="x.props.refreshIntervalSec" :marquee-duration="x.props.marqueeDuration" :marquee-reverse="x.props.marqueeReverse" :display="x.props.display" :user-list-id="x.props.userListId"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -26,6 +26,7 @@ import { GetFormResultType } from '@/scripts/form';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
import MkContainer from '@/components/ui/container.vue';
|
import MkContainer from '@/components/ui/container.vue';
|
||||||
import { useInterval } from '@/scripts/use-interval';
|
import { useInterval } from '@/scripts/use-interval';
|
||||||
|
import { shuffle } from '@/scripts/shuffle';
|
||||||
|
|
||||||
const name = 'rssTicker';
|
const name = 'rssTicker';
|
||||||
|
|
||||||
|
@ -34,6 +35,10 @@ const widgetPropsDef = {
|
||||||
type: 'string' as const,
|
type: 'string' as const,
|
||||||
default: 'http://feeds.afpbb.com/rss/afpbb/afpbbnews',
|
default: 'http://feeds.afpbb.com/rss/afpbb/afpbbnews',
|
||||||
},
|
},
|
||||||
|
shuffle: {
|
||||||
|
type: 'boolean' as const,
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
refreshIntervalSec: {
|
refreshIntervalSec: {
|
||||||
type: 'number' as const,
|
type: 'number' as const,
|
||||||
default: 60,
|
default: 60,
|
||||||
|
@ -80,6 +85,9 @@ let key = $ref(0);
|
||||||
const tick = () => {
|
const tick = () => {
|
||||||
fetch(`/api/fetch-rss?url=${widgetProps.url}`, {}).then(res => {
|
fetch(`/api/fetch-rss?url=${widgetProps.url}`, {}).then(res => {
|
||||||
res.json().then(feed => {
|
res.json().then(feed => {
|
||||||
|
if (widgetProps.shuffle) {
|
||||||
|
shuffle(feed.items);
|
||||||
|
}
|
||||||
items.value = feed.items;
|
items.value = feed.items;
|
||||||
fetching.value = false;
|
fetching.value = false;
|
||||||
key++;
|
key++;
|
||||||
|
|
Loading…
Reference in New Issue