Merge branch 'develop' into sw-notification-action

This commit is contained in:
tamaina 2021-05-21 19:56:52 +09:00
commit 5b52417673
81 changed files with 2712 additions and 625 deletions

View file

@ -1,5 +1,5 @@
<template>
<MkModal ref="modal" :manual-showing="manualShowing" :src="src" @click="$refs.modal.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')">
<MkModal ref="modal" :manual-showing="manualShowing" :src="src" :front="true" @click="$refs.modal.close()" @opening="opening" @close="$emit('close')" @closed="$emit('closed')">
<MkEmojiPicker :show-pinned="showPinned" :as-reaction-picker="asReactionPicker" @chosen="chosen" ref="picker"/>
</MkModal>
</template>

View file

@ -9,8 +9,9 @@
<div class="menu" v-else>
<div class="body">
<div>Ads by {{ host }}</div>
<!--<MkButton>{{ $ts.stopThisAd }}</MkButton>-->
<button class="_textButton" @click="toggleMenu">{{ $ts.close }}</button>
<!--<MkButton class="button" primary>{{ $ts._ad.like }}</MkButton>-->
<MkButton v-if="ad.ratio !== 0" class="button" @click="reduceFrequency">{{ $ts._ad.reduceFrequencyOfThisAd }}</MkButton>
<button class="_textButton" @click="toggleMenu">{{ $ts._ad.back }}</button>
</div>
</div>
</div>
@ -19,9 +20,11 @@
<script lang="ts">
import { defineComponent, ref } from 'vue';
import { instance } from '@client/instance';
import { Instance, instance } from '@client/instance';
import { host } from '@client/config';
import MkButton from '@client/components/ui/button.vue';
import { defaultStore } from '@client/store';
import * as os from '@client/os';
export default defineComponent({
components: {
@ -45,35 +48,65 @@ export default defineComponent({
showMenu.value = !showMenu.value;
};
let ad = null;
const choseAd = (): Instance['ads'][number] | null => {
if (props.specify) {
return props.specify as Instance['ads'][number];
}
if (props.specify) {
ad = props.specify;
} else {
let ads = instance.ads.filter(ad => props.prefer.includes(ad.place));
const allAds = instance.ads.map(ad => defaultStore.state.mutedAds.includes(ad.id) ? {
...ad,
ratio: 0
} : ad);
let ads = allAds.filter(ad => props.prefer.includes(ad.place));
if (ads.length === 0) {
ads = instance.ads.filter(ad => ad.place === 'square');
ads = allAds.filter(ad => ad.place === 'square');
}
const high = ads.filter(ad => ad.priority === 'high');
const middle = ads.filter(ad => ad.priority === 'middle');
const low = ads.filter(ad => ad.priority === 'low');
const lowPriorityAds = ads.filter(ad => ad.ratio === 0);
ads = ads.filter(ad => ad.ratio !== 0);
if (high.length > 0) {
ad = high[Math.floor(Math.random() * high.length)];
} else if (middle.length > 0) {
ad = middle[Math.floor(Math.random() * middle.length)];
} else if (low.length > 0) {
ad = low[Math.floor(Math.random() * low.length)];
if (ads.length === 0) {
if (lowPriorityAds.length !== 0) {
return lowPriorityAds[Math.floor(Math.random() * lowPriorityAds.length)];
} else {
return null;
}
}
}
const totalFactor = ads.reduce((a, b) => a + b.ratio, 0);
const r = Math.random() * totalFactor;
let stackedFactor = 0;
for (const ad of ads) {
if (r >= stackedFactor && r <= stackedFactor + ad.ratio) {
return ad;
} else {
stackedFactor += ad.ratio;
}
}
return null;
};
const chosen = ref(choseAd());
const reduceFrequency = () => {
if (chosen.value == null) return;
if (defaultStore.state.mutedAds.includes(chosen.value.id)) return;
defaultStore.push('mutedAds', chosen.value.id);
os.success();
chosen.value = choseAd();
showMenu.value = false;
};
return {
ad,
ad: chosen,
showMenu,
toggleMenu,
host,
reduceFrequency,
};
}
});
@ -157,6 +190,10 @@ export default defineComponent({
margin: 0 auto;
max-width: 400px;
border: solid 1px var(--divider);
> .button {
margin: 8px auto;
}
}
}
}

View file

@ -9,7 +9,6 @@
</div>
</div>
<div class="gqnyydlz" :style="{ background: color }" v-else>
<i class="fas fa-eye-slash" @click="hide = true"></i>
<a
:href="image.url"
:title="image.name"
@ -18,6 +17,7 @@
<ImgWithBlurhash :hash="image.blurhash" :src="url" :alt="image.name" :title="image.name" :cover="false"/>
<div class="gif" v-if="image.type === 'image/gif'">GIF</div>
</a>
<i class="fas fa-eye-slash" @click="hide = true"></i>
</div>
</template>

View file

@ -1,6 +1,6 @@
<template>
<transition :name="$store.state.animation ? popup ? 'modal-popup' : 'modal' : ''" :duration="$store.state.animation ? popup ? 500 : 300 : 0" appear @after-leave="onClosed" @enter="$emit('opening')" @after-enter="childRendered">
<div v-show="manualShowing != null ? manualShowing : showing" class="mk-modal" v-hotkey.global="keymap" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
<div v-show="manualShowing != null ? manualShowing : showing" class="qzhlnise" :class="{ front }" v-hotkey.global="keymap" :style="{ pointerEvents: (manualShowing != null ? manualShowing : showing) ? 'auto' : 'none', '--transformOrigin': transformOrigin }">
<div class="bg _modalBg" @click="onBgClick" @contextmenu.prevent.stop="() => {}"></div>
<div class="content" :class="{ popup, fixed, top: position === 'top' }" @click.self="onBgClick" ref="content">
<slot></slot>
@ -41,6 +41,11 @@ export default defineComponent({
},
position: {
required: false
},
front: {
type: Boolean,
required: false,
default: false,
}
},
emits: ['opening', 'click', 'esc', 'close', 'closed'],
@ -224,7 +229,7 @@ export default defineComponent({
}
}
.mk-modal {
.qzhlnise {
> .bg {
z-index: 10000;
}
@ -269,5 +274,19 @@ export default defineComponent({
position: fixed;
}
}
&.front {
> .bg {
z-index: 20000;
}
> .content:not(.popup) {
z-index: 20000;
}
> .content.popup {
z-index: 20000;
}
}
}
</style>

View file

@ -3,10 +3,17 @@ import { api } from './os';
// TODO: 他のタブと永続化されたstateを同期
type Instance = {
export type Instance = {
emojis: {
category: string;
}[];
ads: {
id: string;
ratio: number;
place: string;
url: string;
imageUrl: string;
}[];
};
const data = localStorage.getItem('instance');

View file

@ -15,12 +15,17 @@
<MkRadio v-model="ad.place" value="horizontal">horizontal</MkRadio>
<MkRadio v-model="ad.place" value="horizontal-big">horizontal-big</MkRadio>
</div>
<!--
<div style="margin: 32px 0;">
{{ $ts.priority }}
<MkRadio v-model="ad.priority" value="high">{{ $ts.high }}</MkRadio>
<MkRadio v-model="ad.priority" value="middle">{{ $ts.middle }}</MkRadio>
<MkRadio v-model="ad.priority" value="low">{{ $ts.low }}</MkRadio>
</div>
-->
<MkInput v-model:value="ad.ratio" type="number">
<span>{{ $ts.ratio }}</span>
</MkInput>
<MkInput v-model:value="ad.expiresAt" type="date">
<span>{{ $ts.expiration }}</span>
</MkInput>
@ -82,6 +87,7 @@ export default defineComponent({
memo: '',
place: 'square',
priority: 'middle',
ratio: 1,
url: '',
imageUrl: null,
expiresAt: null,

View file

@ -43,6 +43,7 @@
<FormGroup>
<template #label>{{ $ts.info }}</template>
<FormLink :active="page === 'database'" replace to="/instance/database"><template #icon><i class="fas fa-database"></i></template>{{ $ts.database }}</FormLink>
<FormLink :active="page === 'logs'" replace to="/instance/logs"><template #icon><i class="fas fa-stream"></i></template>{{ $ts.logs }}</FormLink>
</FormGroup>
</FormBase>
</div>
@ -105,6 +106,7 @@ export default defineComponent({
case 'announcements': return defineAsyncComponent(() => import('./announcements.vue'));
case 'ads': return defineAsyncComponent(() => import('./ads.vue'));
case 'database': return defineAsyncComponent(() => import('./database.vue'));
case 'logs': return defineAsyncComponent(() => import('./logs.vue'));
case 'abuses': return defineAsyncComponent(() => import('./abuses.vue'));
case 'settings': return defineAsyncComponent(() => import('./settings.vue'));
case 'files-settings': return defineAsyncComponent(() => import('./files-settings.vue'));

View file

@ -123,7 +123,7 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, markRaw } from 'vue';
import Chart from 'chart.js';
import XModalWindow from '@client/components/ui/modal-window.vue';
import MkUsersDialog from '@client/components/users-dialog.vue';
@ -280,7 +280,7 @@ export default defineComponent({
}
Chart.defaults.global.defaultFontColor = getComputedStyle(document.documentElement).getPropertyValue('--fg');
this.chartInstance = new Chart(this.canvas, {
this.chartInstance = markRaw(new Chart(this.canvas, {
type: 'line',
data: {
labels: new Array(chartLimit).fill(0).map((_, i) => this.getDate(i).toLocaleString()).slice().reverse(),
@ -331,7 +331,7 @@ export default defineComponent({
mode: 'index',
}
}
});
}));
},
getDate(ago: number) {

View file

@ -5,13 +5,13 @@
<span>{{ $ts.domain }}</span>
</MkInput>
<MkSelect v-model:value="logLevel">
<template #label>{{ $ts.level }}</template>
<option value="all">{{ $ts.levels.all }}</option>
<option value="info">{{ $ts.levels.info }}</option>
<option value="success">{{ $ts.levels.success }}</option>
<option value="warning">{{ $ts.levels.warning }}</option>
<option value="error">{{ $ts.levels.error }}</option>
<option value="debug">{{ $ts.levels.debug }}</option>
<template #label>Level</template>
<option value="all">All</option>
<option value="info">Info</option>
<option value="success">Success</option>
<option value="warning">Warning</option>
<option value="error">Error</option>
<option value="debug">Debug</option>
</MkSelect>
</div>
@ -45,6 +45,8 @@ export default defineComponent({
MkTextarea,
},
emits: ['info'],
data() {
return {
[symbols.PAGE_INFO]: {
@ -72,6 +74,10 @@ export default defineComponent({
this.fetchLogs();
},
mounted() {
this.$emit('info', this[symbols.PAGE_INFO]);
},
methods: {
fetchLogs() {
os.api('admin/logs', {

View file

@ -27,7 +27,7 @@
</template>
<script lang="ts">
import { defineComponent } from 'vue';
import { defineComponent, markRaw } from 'vue';
import Chart from 'chart.js';
import number from '../../filters/number';
@ -69,7 +69,7 @@ export default defineComponent({
Chart.defaults.global.defaultFontColor = getComputedStyle(document.documentElement).getPropertyValue('--fg');
this.chart = new Chart(this.$refs.chart, {
this.chart = markRaw(new Chart(this.$refs.chart, {
type: 'line',
data: {
labels: [],
@ -152,7 +152,7 @@ export default defineComponent({
mode: 'index',
}
}
});
}));
this.connection.on('stats', this.onStats);
this.connection.on('statsLog', this.onStatsLog);

View file

@ -55,6 +55,10 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'account',
default: []
},
mutedAds: {
where: 'account',
default: [] as string[]
},
menu: {
where: 'deviceAccount',

View file

@ -64,11 +64,8 @@ export default defineComponent({
<style lang="scss" scoped>
.wtdtxvec {
--margin: 8px;
--panelShadow: none;
padding: 0 var(--margin);
::v-deep(._panel) {
box-shadow: none;
}
}
</style>

View file

@ -114,6 +114,7 @@ export default defineComponent({
overflow: hidden;
font-size: 0.9em;
color: var(--fg);
padding-right: 8px;
> .a {
display: block;
@ -129,6 +130,9 @@ export default defineComponent({
font-size: 75%;
opacity: 0.7;
line-height: $bodyInfoHieght;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}