Merge branch 'notification-read-api' into swn
This commit is contained in:
commit
30915d587a
912 changed files with 6686 additions and 4904 deletions
|
|
@ -57,7 +57,7 @@ const lib = emojilist.filter(x => x.category !== 'flags');
|
|||
|
||||
const char2file = (char: string) => {
|
||||
let codes = Array.from(char).map(x => x.codePointAt(0)?.toString(16));
|
||||
if (!codes.includes('200d')) codes = codes.filter(x => x != 'fe0f');
|
||||
if (!codes.includes('200d')) codes = codes.filter(x => x !== 'fe0f');
|
||||
return codes.filter(x => x && x.length).join('-');
|
||||
};
|
||||
|
||||
|
|
@ -192,8 +192,7 @@ function exec() {
|
|||
const cache = sessionStorage.getItem(cacheKey);
|
||||
|
||||
if (cache) {
|
||||
const users = JSON.parse(cache);
|
||||
users.value = users;
|
||||
users.value = JSON.parse(cache);
|
||||
fetching.value = false;
|
||||
} else {
|
||||
os.api('users/search-by-username-and-host', {
|
||||
|
|
@ -208,7 +207,7 @@ function exec() {
|
|||
});
|
||||
}
|
||||
} else if (props.type === 'hashtag') {
|
||||
if (!props.q || props.q == '') {
|
||||
if (!props.q || props.q === '') {
|
||||
hashtags.value = JSON.parse(localStorage.getItem('hashtags') || '[]');
|
||||
fetching.value = false;
|
||||
} else {
|
||||
|
|
@ -231,9 +230,9 @@ function exec() {
|
|||
}
|
||||
}
|
||||
} else if (props.type === 'emoji') {
|
||||
if (!props.q || props.q == '') {
|
||||
if (!props.q || props.q === '') {
|
||||
// 最近使った絵文字をサジェスト
|
||||
emojis.value = defaultStore.state.recentlyUsedEmojis.map(emoji => emojiDb.find(e => e.emoji == emoji)).filter(x => x) as EmojiDef[];
|
||||
emojis.value = defaultStore.state.recentlyUsedEmojis.map(emoji => emojiDb.find(e => e.emoji === emoji)).filter(x => x) as EmojiDef[];
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -241,37 +240,37 @@ function exec() {
|
|||
const max = 30;
|
||||
|
||||
emojiDb.some(x => {
|
||||
if (x.name.startsWith(props.q || '') && !x.aliasOf && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
|
||||
return matched.length == max;
|
||||
if (x.name.startsWith(props.q ?? '') && !x.aliasOf && !matched.some(y => y.emoji === x.emoji)) matched.push(x);
|
||||
return matched.length === max;
|
||||
});
|
||||
|
||||
if (matched.length < max) {
|
||||
emojiDb.some(x => {
|
||||
if (x.name.startsWith(props.q || '') && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
|
||||
return matched.length == max;
|
||||
if (x.name.startsWith(props.q ?? '') && !matched.some(y => y.emoji === x.emoji)) matched.push(x);
|
||||
return matched.length === max;
|
||||
});
|
||||
}
|
||||
|
||||
if (matched.length < max) {
|
||||
emojiDb.some(x => {
|
||||
if (x.name.includes(props.q || '') && !matched.some(y => y.emoji == x.emoji)) matched.push(x);
|
||||
return matched.length == max;
|
||||
if (x.name.includes(props.q ?? '') && !matched.some(y => y.emoji === x.emoji)) matched.push(x);
|
||||
return matched.length === max;
|
||||
});
|
||||
}
|
||||
|
||||
emojis.value = matched;
|
||||
} else if (props.type === 'mfmTag') {
|
||||
if (!props.q || props.q == '') {
|
||||
if (!props.q || props.q === '') {
|
||||
mfmTags.value = MFM_TAGS;
|
||||
return;
|
||||
}
|
||||
|
||||
mfmTags.value = MFM_TAGS.filter(tag => tag.startsWith(props.q || ''));
|
||||
mfmTags.value = MFM_TAGS.filter(tag => tag.startsWith(props.q ?? ''));
|
||||
}
|
||||
}
|
||||
|
||||
function onMousedown(e: Event) {
|
||||
if (!contains(rootEl.value, e.target) && (rootEl.value != e.target)) props.close();
|
||||
if (!contains(rootEl.value, e.target) && (rootEl.value !== e.target)) props.close();
|
||||
}
|
||||
|
||||
function onKeydown(e: KeyboardEvent) {
|
||||
|
|
@ -348,7 +347,7 @@ function chooseUser() {
|
|||
|
||||
onUpdated(() => {
|
||||
setPosition();
|
||||
items.value = suggests.value?.children || [];
|
||||
items.value = suggests.value?.children ?? [];
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ function requestRender() {
|
|||
}
|
||||
|
||||
function callback(response?: string) {
|
||||
emit('update:modelValue', typeof response == 'string' ? response : null);
|
||||
emit('update:modelValue', typeof response === 'string' ? response : null);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ const colors = {
|
|||
red: '#FF4560',
|
||||
purple: '#e300db',
|
||||
orange: '#fe6919',
|
||||
lime: '#c7f400',
|
||||
};
|
||||
const colorSets = [colors.blue, colors.green, colors.yellow, colors.red, colors.purple];
|
||||
const getColor = (i) => {
|
||||
|
|
@ -224,7 +225,7 @@ export default defineComponent({
|
|||
axis: 'y',
|
||||
colors: {
|
||||
0: alpha(x.color ? x.color : getColor(i), 0),
|
||||
[maxes[i]]: alpha(x.color ? x.color : getColor(i), 0.15),
|
||||
[maxes[i]]: alpha(x.color ? x.color : getColor(i), 0.175),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -373,16 +374,6 @@ export default defineComponent({
|
|||
const raw = await os.api('charts/federation', { limit: props.limit, span: props.span });
|
||||
return {
|
||||
series: [{
|
||||
name: 'Sub',
|
||||
type: 'area',
|
||||
data: format(raw.sub),
|
||||
color: colors.orange,
|
||||
}, {
|
||||
name: 'Pub',
|
||||
type: 'area',
|
||||
data: format(raw.pub),
|
||||
color: colors.purple,
|
||||
}, {
|
||||
name: 'Received',
|
||||
type: 'area',
|
||||
data: format(raw.inboxInstances),
|
||||
|
|
@ -397,6 +388,21 @@ export default defineComponent({
|
|||
type: 'area',
|
||||
data: format(raw.stalled),
|
||||
color: colors.red,
|
||||
}, {
|
||||
name: 'Pub & Sub',
|
||||
type: 'area',
|
||||
data: format(raw.pubsub),
|
||||
color: colors.lime,
|
||||
}, {
|
||||
name: 'Pub',
|
||||
type: 'area',
|
||||
data: format(raw.pub),
|
||||
color: colors.purple,
|
||||
}, {
|
||||
name: 'Sub',
|
||||
type: 'area',
|
||||
data: format(raw.sub),
|
||||
color: colors.orange,
|
||||
}],
|
||||
};
|
||||
};
|
||||
|
|
@ -529,12 +535,12 @@ export default defineComponent({
|
|||
name: 'Write',
|
||||
type: 'area',
|
||||
data: format(raw.write),
|
||||
color: colors.blue,
|
||||
color: colors.lime,
|
||||
}, {
|
||||
name: 'Read',
|
||||
type: 'area',
|
||||
data: format(raw.read),
|
||||
color: '#888888',
|
||||
color: colors.blue,
|
||||
}, {
|
||||
name: '< Week',
|
||||
type: 'area',
|
||||
|
|
|
|||
|
|
@ -53,8 +53,8 @@ export default defineComponent({
|
|||
if (el.key == null && item.id) el.key = item.id;
|
||||
|
||||
if (
|
||||
i != props.items.length - 1 &&
|
||||
new Date(item.createdAt).getDate() != new Date(props.items[i + 1].createdAt).getDate()
|
||||
i !== props.items.length - 1 &&
|
||||
new Date(item.createdAt).getDate() !== new Date(props.items[i + 1].createdAt).getDate()
|
||||
) {
|
||||
const separator = h('div', {
|
||||
class: 'separator',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div class="mk-google">
|
||||
<input v-model="query" type="search" :placeholder="q">
|
||||
<button @click="search"><i class="fas fa-search"></i> {{ $ts.search }}</button>
|
||||
<button @click="search"><i class="fas fa-search"></i> {{ $ts.searchByGoogle }}</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<MkModal ref="modal" :prefer-type="'dialog'" @click="$refs.modal.close()" @closed="$emit('closed')">
|
||||
<div class="szkkfdyq _popup">
|
||||
<MkModal ref="modal" v-slot="{ type, maxHeight }" :prefer-type="preferedModalType" :transparent-bg="true" :src="src" @click="modal.close()" @closed="emit('closed')">
|
||||
<div class="szkkfdyq _popup _shadow" :class="{ asDrawer: type === 'drawer' }" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : '' }">
|
||||
<div class="main">
|
||||
<template v-for="item in items">
|
||||
<button v-if="item.action" v-click-anime class="_button" @click="$event => { item.action($event); close(); }">
|
||||
|
|
@ -33,97 +33,94 @@
|
|||
</MkModal>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { } from 'vue';
|
||||
import MkModal from '@/components/ui/modal.vue';
|
||||
import { menuDef } from '@/menu';
|
||||
import { instanceName } from '@/config';
|
||||
import { defaultStore } from '@/store';
|
||||
import { i18n } from '@/i18n';
|
||||
import { deviceKind } from '@/scripts/device-kind';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
MkModal,
|
||||
},
|
||||
|
||||
emits: ['closed'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
menuDef: menuDef,
|
||||
items: [],
|
||||
instanceName,
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
menu(): string[] {
|
||||
return this.$store.state.menu;
|
||||
},
|
||||
},
|
||||
|
||||
created() {
|
||||
this.items = Object.keys(this.menuDef).filter(k => !this.menu.includes(k)).map(k => this.menuDef[k]).filter(def => def.show == null ? true : def.show).map(def => ({
|
||||
type: def.to ? 'link' : 'button',
|
||||
text: this.$ts[def.title],
|
||||
icon: def.icon,
|
||||
to: def.to,
|
||||
action: def.action,
|
||||
indicate: def.indicated,
|
||||
}));
|
||||
},
|
||||
|
||||
methods: {
|
||||
close() {
|
||||
this.$refs.modal.close();
|
||||
}
|
||||
}
|
||||
const props = withDefaults(defineProps<{
|
||||
src?: HTMLElement;
|
||||
}>(), {
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const preferedModalType = (deviceKind === 'desktop' && props.src != null) ? 'popup' :
|
||||
deviceKind === 'smartphone' ? 'drawer' :
|
||||
'dialog';
|
||||
|
||||
const modal = $ref<InstanceType<typeof MkModal>>();
|
||||
|
||||
const menu = defaultStore.state.menu;
|
||||
|
||||
const items = Object.keys(menuDef).filter(k => !menu.includes(k)).map(k => menuDef[k]).filter(def => def.show == null ? true : def.show).map(def => ({
|
||||
type: def.to ? 'link' : 'button',
|
||||
text: i18n.ts[def.title],
|
||||
icon: def.icon,
|
||||
to: def.to,
|
||||
action: def.action,
|
||||
indicate: def.indicated,
|
||||
}));
|
||||
|
||||
function close() {
|
||||
modal.close();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.szkkfdyq {
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
max-width: 800px;
|
||||
padding: 32px;
|
||||
width: min(460px, 100vw);
|
||||
padding: 24px;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
text-align: center;
|
||||
overscroll-behavior: contain;
|
||||
text-align: left;
|
||||
border-radius: 16px;
|
||||
|
||||
@media (max-width: 500px) {
|
||||
padding: 16px;
|
||||
&.asDrawer {
|
||||
width: 100%;
|
||||
padding: 16px 16px calc(env(safe-area-inset-bottom, 0px) + 16px) 16px;
|
||||
border-radius: 24px;
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
> .main, > .sub {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
||||
|
||||
> * {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
vertical-align: bottom;
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
border-radius: var(--radius);
|
||||
|
||||
@media (max-width: 500px) {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
height: 100px;
|
||||
border-radius: 10px;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
color: var(--accent);
|
||||
background: var(--accentedBg);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
> .icon {
|
||||
font-size: 26px;
|
||||
height: 32px;
|
||||
font-size: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
> .text {
|
||||
margin-top: 8px;
|
||||
font-size: 0.9em;
|
||||
margin-top: 12px;
|
||||
font-size: 0.8em;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
render() {
|
||||
if (this.text == null || this.text == '') return;
|
||||
if (this.text == null || this.text === '') return;
|
||||
|
||||
const ast = (this.plain ? mfm.parsePlain : mfm.parse)(this.text, { fnNameList: MFM_TAGS });
|
||||
|
||||
|
|
|
|||
|
|
@ -6,33 +6,26 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { onMounted } from 'vue';
|
||||
import XNotification from './notification.vue';
|
||||
import * as os from '@/os';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XNotification
|
||||
},
|
||||
props: {
|
||||
notification: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ['closed'],
|
||||
data() {
|
||||
return {
|
||||
showing: true,
|
||||
zIndex: os.claimZIndex('high'),
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
window.setTimeout(() => {
|
||||
this.showing = false;
|
||||
}, 6000);
|
||||
}
|
||||
defineProps<{
|
||||
notification: any; // TODO
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const zIndex = os.claimZIndex('high');
|
||||
let showing = $ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
window.setTimeout(() => {
|
||||
showing = false;
|
||||
}, 6000);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ const emit = defineEmits<{
|
|||
(e: 'closed'): void;
|
||||
}>();
|
||||
|
||||
const showing = ref(true);
|
||||
const zIndex = os.claimZIndex('high');
|
||||
let showing = $ref(true);
|
||||
|
||||
onMounted(() => {
|
||||
window.setTimeout(() => {
|
||||
showing.value = false;
|
||||
showing = false;
|
||||
}, 4000);
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ const onBgClick = () => {
|
|||
};
|
||||
|
||||
if (type.value === 'drawer') {
|
||||
maxHeight.value = window.innerHeight / 2;
|
||||
maxHeight.value = window.innerHeight / 1.5;
|
||||
}
|
||||
|
||||
const keymap = {
|
||||
|
|
@ -100,6 +100,7 @@ const MARGIN = 16;
|
|||
const align = () => {
|
||||
if (props.src == null) return;
|
||||
if (type.value === 'drawer') return;
|
||||
if (type.value === 'dialog') return;
|
||||
|
||||
const popover = content.value!;
|
||||
if (popover == null) return;
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ let tweetHeight = $ref(150);
|
|||
|
||||
const requestUrl = new URL(props.url);
|
||||
|
||||
if (requestUrl.hostname == 'twitter.com') {
|
||||
if (requestUrl.hostname === 'twitter.com') {
|
||||
const m = requestUrl.pathname.match(/^\/.+\/status(?:es)?\/(\d+)/);
|
||||
if (m) tweetId = m[1];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ if (localStorage.getItem('accounts') != null) {
|
|||
|
||||
import { computed, createApp, watch, markRaw, version as vueVersion } from 'vue';
|
||||
import compareVersions from 'compare-versions';
|
||||
import * as JSON5 from 'json5';
|
||||
|
||||
import widgets from '@/widgets';
|
||||
import directives from '@/directives';
|
||||
|
|
@ -158,7 +159,9 @@ if ($i && $i.token) {
|
|||
}
|
||||
//#endregion
|
||||
|
||||
fetchInstance().then(() => {
|
||||
const fetchInstanceMetaPromise = fetchInstance();
|
||||
|
||||
fetchInstanceMetaPromise.then(() => {
|
||||
localStorage.setItem('v', instance.version);
|
||||
|
||||
// Init service worker
|
||||
|
|
@ -266,6 +269,14 @@ window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => {
|
|||
});
|
||||
//#endregion
|
||||
|
||||
fetchInstanceMetaPromise.then(() => {
|
||||
if (defaultStore.state.themeInitial) {
|
||||
if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON5.parse(instance.defaultLightTheme));
|
||||
if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON5.parse(instance.defaultDarkTheme));
|
||||
defaultStore.set('themeInitial', false);
|
||||
}
|
||||
});
|
||||
|
||||
// shortcut
|
||||
document.addEventListener('keydown', makeHotkey({
|
||||
'd': () => {
|
||||
|
|
|
|||
|
|
@ -544,7 +544,7 @@ export const uploads = ref<{
|
|||
}[]>([]);
|
||||
|
||||
export function upload(file: File, folder?: any, name?: string, keepOriginal: boolean = defaultStore.state.keepOriginalUploading): Promise<Misskey.entities.DriveFile> {
|
||||
if (folder && typeof folder == 'object') folder = folder.id;
|
||||
if (folder && typeof folder === 'object') folder = folder.id;
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = Math.random().toString();
|
||||
|
|
|
|||
|
|
@ -149,6 +149,7 @@ const patrons = [
|
|||
'oss',
|
||||
'Weeble',
|
||||
'蝉暮せせせ',
|
||||
'ThatOneCalculator',
|
||||
];
|
||||
|
||||
let easterEggReady = false;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,16 @@
|
|||
<template #caption>#RRGGBB</template>
|
||||
</FormInput>
|
||||
|
||||
<FormTextarea v-model="defaultLightTheme" class="_formBlock">
|
||||
<template #label>{{ $ts.instanceDefaultLightTheme }}</template>
|
||||
<template #caption>{{ $ts.instanceDefaultThemeDescription }}</template>
|
||||
</FormTextarea>
|
||||
|
||||
<FormTextarea v-model="defaultDarkTheme" class="_formBlock">
|
||||
<template #label>{{ $ts.instanceDefaultDarkTheme }}</template>
|
||||
<template #caption>{{ $ts.instanceDefaultThemeDescription }}</template>
|
||||
</FormTextarea>
|
||||
|
||||
<FormInput v-model="tosUrl" class="_formBlock">
|
||||
<template #prefix><i class="fas fa-link"></i></template>
|
||||
<template #label>{{ $ts.tosUrl }}</template>
|
||||
|
|
@ -76,11 +86,6 @@
|
|||
<template #caption>{{ $ts.cacheRemoteFilesDescription }}</template>
|
||||
</FormSwitch>
|
||||
|
||||
<FormSwitch v-model="proxyRemoteFiles" class="_formBlock">
|
||||
<template #label>{{ $ts.proxyRemoteFiles }}</template>
|
||||
<template #caption>{{ $ts.proxyRemoteFilesDescription }}</template>
|
||||
</FormSwitch>
|
||||
|
||||
<FormSplit :min-width="280">
|
||||
<FormInput v-model="localDriveCapacityMb" type="number" class="_formBlock">
|
||||
<template #label>{{ $ts.driveCapacityPerLocalAccount }}</template>
|
||||
|
|
@ -181,11 +186,12 @@ export default defineComponent({
|
|||
bannerUrl: null,
|
||||
backgroundImageUrl: null,
|
||||
themeColor: null,
|
||||
defaultLightTheme: null,
|
||||
defaultDarkTheme: null,
|
||||
enableLocalTimeline: false,
|
||||
enableGlobalTimeline: false,
|
||||
pinnedUsers: '',
|
||||
cacheRemoteFiles: false,
|
||||
proxyRemoteFiles: false,
|
||||
localDriveCapacityMb: 0,
|
||||
remoteDriveCapacityMb: 0,
|
||||
enableRegistration: false,
|
||||
|
|
@ -208,13 +214,14 @@ export default defineComponent({
|
|||
this.bannerUrl = meta.bannerUrl;
|
||||
this.backgroundImageUrl = meta.backgroundImageUrl;
|
||||
this.themeColor = meta.themeColor;
|
||||
this.defaultLightTheme = meta.defaultLightTheme;
|
||||
this.defaultDarkTheme = meta.defaultDarkTheme;
|
||||
this.maintainerName = meta.maintainerName;
|
||||
this.maintainerEmail = meta.maintainerEmail;
|
||||
this.enableLocalTimeline = !meta.disableLocalTimeline;
|
||||
this.enableGlobalTimeline = !meta.disableGlobalTimeline;
|
||||
this.pinnedUsers = meta.pinnedUsers.join('\n');
|
||||
this.cacheRemoteFiles = meta.cacheRemoteFiles;
|
||||
this.proxyRemoteFiles = meta.proxyRemoteFiles;
|
||||
this.localDriveCapacityMb = meta.driveCapacityPerLocalUserMb;
|
||||
this.remoteDriveCapacityMb = meta.driveCapacityPerRemoteUserMb;
|
||||
this.enableRegistration = !meta.disableRegistration;
|
||||
|
|
@ -235,13 +242,14 @@ export default defineComponent({
|
|||
bannerUrl: this.bannerUrl,
|
||||
backgroundImageUrl: this.backgroundImageUrl,
|
||||
themeColor: this.themeColor === '' ? null : this.themeColor,
|
||||
defaultLightTheme: this.defaultLightTheme === '' ? null : this.defaultLightTheme,
|
||||
defaultDarkTheme: this.defaultDarkTheme === '' ? null : this.defaultDarkTheme,
|
||||
maintainerName: this.maintainerName,
|
||||
maintainerEmail: this.maintainerEmail,
|
||||
disableLocalTimeline: !this.enableLocalTimeline,
|
||||
disableGlobalTimeline: !this.enableGlobalTimeline,
|
||||
pinnedUsers: this.pinnedUsers.split('\n'),
|
||||
cacheRemoteFiles: this.cacheRemoteFiles,
|
||||
proxyRemoteFiles: this.proxyRemoteFiles,
|
||||
localDriveCapacityMb: parseInt(this.localDriveCapacityMb, 10),
|
||||
remoteDriveCapacityMb: parseInt(this.remoteDriveCapacityMb, 10),
|
||||
disableRegistration: !this.enableRegistration,
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- deprecated
|
||||
<div class="section _block">
|
||||
<div class="title">{{ $ts._mfm.search }}</div>
|
||||
<div class="content">
|
||||
|
|
@ -131,6 +132,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
<div class="section _block">
|
||||
<div class="title">{{ $ts._mfm.flip }}</div>
|
||||
<div class="content">
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
<div class="main _gap">
|
||||
<MkButton v-if="!showNext && hasNext" class="load next" @click="showNext = true"><i class="fas fa-chevron-up"></i></MkButton>
|
||||
<div class="note _gap">
|
||||
<MkRemoteCaution v-if="note.user.host != null" :href="note.url || note.uri" class="_isolated"/>
|
||||
<MkRemoteCaution v-if="note.user.host != null" :href="note.url ?? note.uri" class="_isolated"/>
|
||||
<XNoteDetailed :key="note.id" v-model:note="note" class="_isolated note"/>
|
||||
</div>
|
||||
<div v-if="clips && clips.length > 0" class="_content clips _gap">
|
||||
|
|
|
|||
|
|
@ -29,11 +29,27 @@
|
|||
|
||||
<FormSelect v-model="profile.lang" class="_formBlock">
|
||||
<template #label>{{ i18n.ts.language }}</template>
|
||||
<option v-for="x in langs" :key="x[0]" :value="x[0]">{{ x[1] }}</option>
|
||||
<option v-for="x in Object.keys(langmap)" :key="x" :value="x">{{ langmap[x].nativeName }}</option>
|
||||
</FormSelect>
|
||||
|
||||
<FormSlot>
|
||||
<MkButton @click="editMetadata">{{ i18n.ts._profile.metadataEdit }}</MkButton>
|
||||
<FormSlot class="_formBlock">
|
||||
<FormFolder>
|
||||
<template #icon><i class="fas fa-table-list"></i></template>
|
||||
<template #label>{{ i18n.ts._profile.metadataEdit }}</template>
|
||||
|
||||
<div class="_formRoot">
|
||||
<FormSplit v-for="(record, i) in fields" :min-width="250" class="_formBlock">
|
||||
<FormInput v-model="record.name">
|
||||
<template #label>{{ i18n.ts._profile.metadataLabel }} #{{ i + 1 }}</template>
|
||||
</FormInput>
|
||||
<FormInput v-model="record.value">
|
||||
<template #label>{{ i18n.ts._profile.metadataContent }} #{{ i + 1 }}</template>
|
||||
</FormInput>
|
||||
</FormSplit>
|
||||
<MkButton :disabled="fields.length >= 16" inline style="margin-right: 8px;" @click="addField"><i class="fas fa-plus"></i> {{ i18n.ts.add }}</MkButton>
|
||||
<MkButton inline primary @click="saveFields"><i class="fas fa-check"></i> {{ i18n.ts.save }}</MkButton>
|
||||
</div>
|
||||
</FormFolder>
|
||||
<template #caption>{{ i18n.ts._profile.metadataDescription }}</template>
|
||||
</FormSlot>
|
||||
|
||||
|
|
@ -52,13 +68,16 @@ import FormInput from '@/components/form/input.vue';
|
|||
import FormTextarea from '@/components/form/textarea.vue';
|
||||
import FormSwitch from '@/components/form/switch.vue';
|
||||
import FormSelect from '@/components/form/select.vue';
|
||||
import FormSplit from '@/components/form/split.vue';
|
||||
import FormFolder from '@/components/form/folder.vue';
|
||||
import FormSlot from '@/components/form/slot.vue';
|
||||
import { host, langs } from '@/config';
|
||||
import { host } from '@/config';
|
||||
import { selectFile } from '@/scripts/select-file';
|
||||
import * as os from '@/os';
|
||||
import * as symbols from '@/symbols';
|
||||
import { i18n } from '@/i18n';
|
||||
import { $i } from '@/account';
|
||||
import { langmap } from '@/scripts/langmap';
|
||||
|
||||
const profile = reactive({
|
||||
name: $i.name,
|
||||
|
|
@ -72,23 +91,31 @@ const profile = reactive({
|
|||
alwaysMarkNsfw: $i.alwaysMarkNsfw,
|
||||
});
|
||||
|
||||
const additionalFields = reactive({
|
||||
fieldName0: $i.fields[0] ? $i.fields[0].name : null,
|
||||
fieldValue0: $i.fields[0] ? $i.fields[0].value : null,
|
||||
fieldName1: $i.fields[1] ? $i.fields[1].name : null,
|
||||
fieldValue1: $i.fields[1] ? $i.fields[1].value : null,
|
||||
fieldName2: $i.fields[2] ? $i.fields[2].name : null,
|
||||
fieldValue2: $i.fields[2] ? $i.fields[2].value : null,
|
||||
fieldName3: $i.fields[3] ? $i.fields[3].name : null,
|
||||
fieldValue3: $i.fields[3] ? $i.fields[3].value : null,
|
||||
});
|
||||
|
||||
watch(() => profile, () => {
|
||||
save();
|
||||
}, {
|
||||
deep: true,
|
||||
});
|
||||
|
||||
const fields = reactive($i.fields.map(field => ({ name: field.name, value: field.value })));
|
||||
|
||||
function addField() {
|
||||
fields.push({
|
||||
name: '',
|
||||
value: '',
|
||||
});
|
||||
}
|
||||
|
||||
while (fields.length < 4) {
|
||||
addField();
|
||||
}
|
||||
|
||||
function saveFields() {
|
||||
os.apiWithDialog('i/update', {
|
||||
fields: fields.filter(field => field.name !== '' && field.value !== ''),
|
||||
});
|
||||
}
|
||||
|
||||
function save() {
|
||||
os.apiWithDialog('i/update', {
|
||||
name: profile.name || null,
|
||||
|
|
@ -123,79 +150,6 @@ function changeBanner(ev) {
|
|||
});
|
||||
}
|
||||
|
||||
async function editMetadata() {
|
||||
const { canceled, result } = await os.form(i18n.ts._profile.metadata, {
|
||||
fieldName0: {
|
||||
type: 'string',
|
||||
label: i18n.ts._profile.metadataLabel + ' 1',
|
||||
default: additionalFields.fieldName0,
|
||||
},
|
||||
fieldValue0: {
|
||||
type: 'string',
|
||||
label: i18n.ts._profile.metadataContent + ' 1',
|
||||
default: additionalFields.fieldValue0,
|
||||
},
|
||||
fieldName1: {
|
||||
type: 'string',
|
||||
label: i18n.ts._profile.metadataLabel + ' 2',
|
||||
default: additionalFields.fieldName1,
|
||||
},
|
||||
fieldValue1: {
|
||||
type: 'string',
|
||||
label: i18n.ts._profile.metadataContent + ' 2',
|
||||
default: additionalFields.fieldValue1,
|
||||
},
|
||||
fieldName2: {
|
||||
type: 'string',
|
||||
label: i18n.ts._profile.metadataLabel + ' 3',
|
||||
default: additionalFields.fieldName2,
|
||||
},
|
||||
fieldValue2: {
|
||||
type: 'string',
|
||||
label: i18n.ts._profile.metadataContent + ' 3',
|
||||
default: additionalFields.fieldValue2,
|
||||
},
|
||||
fieldName3: {
|
||||
type: 'string',
|
||||
label: i18n.ts._profile.metadataLabel + ' 4',
|
||||
default: additionalFields.fieldName3,
|
||||
},
|
||||
fieldValue3: {
|
||||
type: 'string',
|
||||
label: i18n.ts._profile.metadataContent + ' 4',
|
||||
default: additionalFields.fieldValue3,
|
||||
},
|
||||
});
|
||||
if (canceled) return;
|
||||
|
||||
additionalFields.fieldName0 = result.fieldName0;
|
||||
additionalFields.fieldValue0 = result.fieldValue0;
|
||||
additionalFields.fieldName1 = result.fieldName1;
|
||||
additionalFields.fieldValue1 = result.fieldValue1;
|
||||
additionalFields.fieldName2 = result.fieldName2;
|
||||
additionalFields.fieldValue2 = result.fieldValue2;
|
||||
additionalFields.fieldName3 = result.fieldName3;
|
||||
additionalFields.fieldValue3 = result.fieldValue3;
|
||||
|
||||
const fields = [
|
||||
{ name: additionalFields.fieldName0, value: additionalFields.fieldValue0 },
|
||||
{ name: additionalFields.fieldName1, value: additionalFields.fieldValue1 },
|
||||
{ name: additionalFields.fieldName2, value: additionalFields.fieldValue2 },
|
||||
{ name: additionalFields.fieldName3, value: additionalFields.fieldValue3 },
|
||||
];
|
||||
|
||||
os.api('i/update', {
|
||||
fields,
|
||||
}).then(i => {
|
||||
os.success();
|
||||
}).catch(err => {
|
||||
os.alert({
|
||||
type: 'error',
|
||||
text: err.id
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
[symbols.PAGE_INFO]: {
|
||||
title: i18n.ts.profile,
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@
|
|||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, onActivated, onMounted, ref, watch } from 'vue';
|
||||
import * as JSON5 from 'json5';
|
||||
import FormSwitch from '@/components/form/switch.vue';
|
||||
import FormSelect from '@/components/form/select.vue';
|
||||
import FormGroup from '@/components/form/group.vue';
|
||||
|
|
@ -99,6 +100,8 @@ import { isDeviceDarkmode } from '@/scripts/is-device-darkmode';
|
|||
import { ColdDeviceStorage } from '@/store';
|
||||
import { i18n } from '@/i18n';
|
||||
import { defaultStore } from '@/store';
|
||||
import { instance } from '@/instance';
|
||||
import { concat } from '@/scripts/array';
|
||||
import { fetchThemes, getThemes } from '@/theme-store';
|
||||
import * as symbols from '@/symbols';
|
||||
|
||||
|
|
@ -122,9 +125,12 @@ export default defineComponent({
|
|||
};
|
||||
|
||||
const installedThemes = ref(getThemes());
|
||||
const themes = computed(() => builtinThemes.concat(installedThemes.value));
|
||||
const darkThemes = computed(() => themes.value.filter(t => t.base == 'dark' || t.kind == 'dark'));
|
||||
const lightThemes = computed(() => themes.value.filter(t => t.base == 'light' || t.kind == 'light'));
|
||||
const instanceThemes = [];
|
||||
if (instance.defaultLightTheme != null) instanceThemes.push(JSON5.parse(instance.defaultLightTheme));
|
||||
if (instance.defaultDarkTheme != null) instanceThemes.push(JSON5.parse(instance.defaultDarkTheme));
|
||||
const themes = computed(() => instanceThemes.concat(builtinThemes.concat(installedThemes.value)));
|
||||
const darkThemes = computed(() => themes.value.filter(t => t.base === 'dark' || t.kind === 'dark'));
|
||||
const lightThemes = computed(() => themes.value.filter(t => t.base === 'light' || t.kind === 'light'));
|
||||
const darkTheme = ColdDeviceStorage.ref('darkTheme');
|
||||
const darkThemeId = computed({
|
||||
get() {
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
<template>
|
||||
<form class="mk-setup" @submit.prevent="submit()">
|
||||
<h1>Welcome to Misskey!</h1>
|
||||
<div>
|
||||
<div class="_formRoot">
|
||||
<p>{{ $ts.intro }}</p>
|
||||
<MkInput v-model="username" pattern="^[a-zA-Z0-9_]{1,20}$" spellcheck="false" required data-cy-admin-username>
|
||||
<MkInput v-model="username" pattern="^[a-zA-Z0-9_]{1,20}$" spellcheck="false" required data-cy-admin-username class="_formBlock">
|
||||
<template #label>{{ $ts.username }}</template>
|
||||
<template #prefix>@</template>
|
||||
<template #suffix>@{{ host }}</template>
|
||||
</MkInput>
|
||||
<MkInput v-model="password" type="password" data-cy-admin-password>
|
||||
<MkInput v-model="password" type="password" data-cy-admin-password class="_formBlock">
|
||||
<template #label>{{ $ts.password }}</template>
|
||||
<template #prefix><i class="fas fa-lock"></i></template>
|
||||
</MkInput>
|
||||
<footer>
|
||||
<MkButton primary type="submit" :disabled="submitting" data-cy-admin-ok>
|
||||
<div class="bottom _formBlock">
|
||||
<MkButton gradate type="submit" :disabled="submitting" data-cy-admin-ok>
|
||||
{{ submitting ? $ts.processing : $ts.done }}<MkEllipsis v-if="submitting"/>
|
||||
</MkButton>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
|
@ -92,7 +92,7 @@ export default defineComponent({
|
|||
margin-top: 0;
|
||||
}
|
||||
|
||||
> footer {
|
||||
> .bottom {
|
||||
> * {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,34 +5,24 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import XSetup from './welcome.setup.vue';
|
||||
import XEntrance from './welcome.entrance.a.vue';
|
||||
import { instanceName } from '@/config';
|
||||
import * as os from '@/os';
|
||||
import * as symbols from '@/symbols';
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
XSetup,
|
||||
XEntrance,
|
||||
},
|
||||
let meta = $ref(null);
|
||||
|
||||
data() {
|
||||
return {
|
||||
[symbols.PAGE_INFO]: {
|
||||
title: instanceName,
|
||||
icon: null
|
||||
},
|
||||
meta: null
|
||||
}
|
||||
},
|
||||
os.api('meta', { detail: true }).then(res => {
|
||||
meta = res;
|
||||
});
|
||||
|
||||
created() {
|
||||
os.api('meta', { detail: true }).then(meta => {
|
||||
this.meta = meta;
|
||||
});
|
||||
}
|
||||
defineExpose({
|
||||
[symbols.PAGE_INFO]: computed(() => ({
|
||||
title: instanceName,
|
||||
icon: null,
|
||||
})),
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
666
packages/client/src/scripts/langmap.ts
Normal file
666
packages/client/src/scripts/langmap.ts
Normal file
|
|
@ -0,0 +1,666 @@
|
|||
// TODO: sharedに置いてバックエンドのと統合したい
|
||||
export const langmap = {
|
||||
'ach': {
|
||||
nativeName: 'Lwo',
|
||||
},
|
||||
'ady': {
|
||||
nativeName: 'Адыгэбзэ',
|
||||
},
|
||||
'af': {
|
||||
nativeName: 'Afrikaans',
|
||||
},
|
||||
'af-NA': {
|
||||
nativeName: 'Afrikaans (Namibia)',
|
||||
},
|
||||
'af-ZA': {
|
||||
nativeName: 'Afrikaans (South Africa)',
|
||||
},
|
||||
'ak': {
|
||||
nativeName: 'Tɕɥi',
|
||||
},
|
||||
'ar': {
|
||||
nativeName: 'العربية',
|
||||
},
|
||||
'ar-AR': {
|
||||
nativeName: 'العربية',
|
||||
},
|
||||
'ar-MA': {
|
||||
nativeName: 'العربية',
|
||||
},
|
||||
'ar-SA': {
|
||||
nativeName: 'العربية (السعودية)',
|
||||
},
|
||||
'ay-BO': {
|
||||
nativeName: 'Aymar aru',
|
||||
},
|
||||
'az': {
|
||||
nativeName: 'Azərbaycan dili',
|
||||
},
|
||||
'az-AZ': {
|
||||
nativeName: 'Azərbaycan dili',
|
||||
},
|
||||
'be-BY': {
|
||||
nativeName: 'Беларуская',
|
||||
},
|
||||
'bg': {
|
||||
nativeName: 'Български',
|
||||
},
|
||||
'bg-BG': {
|
||||
nativeName: 'Български',
|
||||
},
|
||||
'bn': {
|
||||
nativeName: 'বাংলা',
|
||||
},
|
||||
'bn-IN': {
|
||||
nativeName: 'বাংলা (ভারত)',
|
||||
},
|
||||
'bn-BD': {
|
||||
nativeName: 'বাংলা(বাংলাদেশ)',
|
||||
},
|
||||
'br': {
|
||||
nativeName: 'Brezhoneg',
|
||||
},
|
||||
'bs-BA': {
|
||||
nativeName: 'Bosanski',
|
||||
},
|
||||
'ca': {
|
||||
nativeName: 'Català',
|
||||
},
|
||||
'ca-ES': {
|
||||
nativeName: 'Català',
|
||||
},
|
||||
'cak': {
|
||||
nativeName: 'Maya Kaqchikel',
|
||||
},
|
||||
'ck-US': {
|
||||
nativeName: 'ᏣᎳᎩ (tsalagi)',
|
||||
},
|
||||
'cs': {
|
||||
nativeName: 'Čeština',
|
||||
},
|
||||
'cs-CZ': {
|
||||
nativeName: 'Čeština',
|
||||
},
|
||||
'cy': {
|
||||
nativeName: 'Cymraeg',
|
||||
},
|
||||
'cy-GB': {
|
||||
nativeName: 'Cymraeg',
|
||||
},
|
||||
'da': {
|
||||
nativeName: 'Dansk',
|
||||
},
|
||||
'da-DK': {
|
||||
nativeName: 'Dansk',
|
||||
},
|
||||
'de': {
|
||||
nativeName: 'Deutsch',
|
||||
},
|
||||
'de-AT': {
|
||||
nativeName: 'Deutsch (Österreich)',
|
||||
},
|
||||
'de-DE': {
|
||||
nativeName: 'Deutsch (Deutschland)',
|
||||
},
|
||||
'de-CH': {
|
||||
nativeName: 'Deutsch (Schweiz)',
|
||||
},
|
||||
'dsb': {
|
||||
nativeName: 'Dolnoserbšćina',
|
||||
},
|
||||
'el': {
|
||||
nativeName: 'Ελληνικά',
|
||||
},
|
||||
'el-GR': {
|
||||
nativeName: 'Ελληνικά',
|
||||
},
|
||||
'en': {
|
||||
nativeName: 'English',
|
||||
},
|
||||
'en-GB': {
|
||||
nativeName: 'English (UK)',
|
||||
},
|
||||
'en-AU': {
|
||||
nativeName: 'English (Australia)',
|
||||
},
|
||||
'en-CA': {
|
||||
nativeName: 'English (Canada)',
|
||||
},
|
||||
'en-IE': {
|
||||
nativeName: 'English (Ireland)',
|
||||
},
|
||||
'en-IN': {
|
||||
nativeName: 'English (India)',
|
||||
},
|
||||
'en-PI': {
|
||||
nativeName: 'English (Pirate)',
|
||||
},
|
||||
'en-SG': {
|
||||
nativeName: 'English (Singapore)',
|
||||
},
|
||||
'en-UD': {
|
||||
nativeName: 'English (Upside Down)',
|
||||
},
|
||||
'en-US': {
|
||||
nativeName: 'English (US)',
|
||||
},
|
||||
'en-ZA': {
|
||||
nativeName: 'English (South Africa)',
|
||||
},
|
||||
'en@pirate': {
|
||||
nativeName: 'English (Pirate)',
|
||||
},
|
||||
'eo': {
|
||||
nativeName: 'Esperanto',
|
||||
},
|
||||
'eo-EO': {
|
||||
nativeName: 'Esperanto',
|
||||
},
|
||||
'es': {
|
||||
nativeName: 'Español',
|
||||
},
|
||||
'es-AR': {
|
||||
nativeName: 'Español (Argentine)',
|
||||
},
|
||||
'es-419': {
|
||||
nativeName: 'Español (Latinoamérica)',
|
||||
},
|
||||
'es-CL': {
|
||||
nativeName: 'Español (Chile)',
|
||||
},
|
||||
'es-CO': {
|
||||
nativeName: 'Español (Colombia)',
|
||||
},
|
||||
'es-EC': {
|
||||
nativeName: 'Español (Ecuador)',
|
||||
},
|
||||
'es-ES': {
|
||||
nativeName: 'Español (España)',
|
||||
},
|
||||
'es-LA': {
|
||||
nativeName: 'Español (Latinoamérica)',
|
||||
},
|
||||
'es-NI': {
|
||||
nativeName: 'Español (Nicaragua)',
|
||||
},
|
||||
'es-MX': {
|
||||
nativeName: 'Español (México)',
|
||||
},
|
||||
'es-US': {
|
||||
nativeName: 'Español (Estados Unidos)',
|
||||
},
|
||||
'es-VE': {
|
||||
nativeName: 'Español (Venezuela)',
|
||||
},
|
||||
'et': {
|
||||
nativeName: 'eesti keel',
|
||||
},
|
||||
'et-EE': {
|
||||
nativeName: 'Eesti (Estonia)',
|
||||
},
|
||||
'eu': {
|
||||
nativeName: 'Euskara',
|
||||
},
|
||||
'eu-ES': {
|
||||
nativeName: 'Euskara',
|
||||
},
|
||||
'fa': {
|
||||
nativeName: 'فارسی',
|
||||
},
|
||||
'fa-IR': {
|
||||
nativeName: 'فارسی',
|
||||
},
|
||||
'fb-LT': {
|
||||
nativeName: 'Leet Speak',
|
||||
},
|
||||
'ff': {
|
||||
nativeName: 'Fulah',
|
||||
},
|
||||
'fi': {
|
||||
nativeName: 'Suomi',
|
||||
},
|
||||
'fi-FI': {
|
||||
nativeName: 'Suomi',
|
||||
},
|
||||
'fo': {
|
||||
nativeName: 'Føroyskt',
|
||||
},
|
||||
'fo-FO': {
|
||||
nativeName: 'Føroyskt (Færeyjar)',
|
||||
},
|
||||
'fr': {
|
||||
nativeName: 'Français',
|
||||
},
|
||||
'fr-CA': {
|
||||
nativeName: 'Français (Canada)',
|
||||
},
|
||||
'fr-FR': {
|
||||
nativeName: 'Français (France)',
|
||||
},
|
||||
'fr-BE': {
|
||||
nativeName: 'Français (Belgique)',
|
||||
},
|
||||
'fr-CH': {
|
||||
nativeName: 'Français (Suisse)',
|
||||
},
|
||||
'fy-NL': {
|
||||
nativeName: 'Frysk',
|
||||
},
|
||||
'ga': {
|
||||
nativeName: 'Gaeilge',
|
||||
},
|
||||
'ga-IE': {
|
||||
nativeName: 'Gaeilge',
|
||||
},
|
||||
'gd': {
|
||||
nativeName: 'Gàidhlig',
|
||||
},
|
||||
'gl': {
|
||||
nativeName: 'Galego',
|
||||
},
|
||||
'gl-ES': {
|
||||
nativeName: 'Galego',
|
||||
},
|
||||
'gn-PY': {
|
||||
nativeName: 'Avañe\'ẽ',
|
||||
},
|
||||
'gu-IN': {
|
||||
nativeName: 'ગુજરાતી',
|
||||
},
|
||||
'gv': {
|
||||
nativeName: 'Gaelg',
|
||||
},
|
||||
'gx-GR': {
|
||||
nativeName: 'Ἑλληνική ἀρχαία',
|
||||
},
|
||||
'he': {
|
||||
nativeName: 'עברית',
|
||||
},
|
||||
'he-IL': {
|
||||
nativeName: 'עברית',
|
||||
},
|
||||
'hi': {
|
||||
nativeName: 'हिन्दी',
|
||||
},
|
||||
'hi-IN': {
|
||||
nativeName: 'हिन्दी',
|
||||
},
|
||||
'hr': {
|
||||
nativeName: 'Hrvatski',
|
||||
},
|
||||
'hr-HR': {
|
||||
nativeName: 'Hrvatski',
|
||||
},
|
||||
'hsb': {
|
||||
nativeName: 'Hornjoserbšćina',
|
||||
},
|
||||
'ht': {
|
||||
nativeName: 'Kreyòl',
|
||||
},
|
||||
'hu': {
|
||||
nativeName: 'Magyar',
|
||||
},
|
||||
'hu-HU': {
|
||||
nativeName: 'Magyar',
|
||||
},
|
||||
'hy': {
|
||||
nativeName: 'Հայերեն',
|
||||
},
|
||||
'hy-AM': {
|
||||
nativeName: 'Հայերեն (Հայաստան)',
|
||||
},
|
||||
'id': {
|
||||
nativeName: 'Bahasa Indonesia',
|
||||
},
|
||||
'id-ID': {
|
||||
nativeName: 'Bahasa Indonesia',
|
||||
},
|
||||
'is': {
|
||||
nativeName: 'Íslenska',
|
||||
},
|
||||
'is-IS': {
|
||||
nativeName: 'Íslenska (Iceland)',
|
||||
},
|
||||
'it': {
|
||||
nativeName: 'Italiano',
|
||||
},
|
||||
'it-IT': {
|
||||
nativeName: 'Italiano',
|
||||
},
|
||||
'ja': {
|
||||
nativeName: '日本語',
|
||||
},
|
||||
'ja-JP': {
|
||||
nativeName: '日本語 (日本)',
|
||||
},
|
||||
'jv-ID': {
|
||||
nativeName: 'Basa Jawa',
|
||||
},
|
||||
'ka-GE': {
|
||||
nativeName: 'ქართული',
|
||||
},
|
||||
'kk-KZ': {
|
||||
nativeName: 'Қазақша',
|
||||
},
|
||||
'km': {
|
||||
nativeName: 'ភាសាខ្មែរ',
|
||||
},
|
||||
'kl': {
|
||||
nativeName: 'kalaallisut',
|
||||
},
|
||||
'km-KH': {
|
||||
nativeName: 'ភាសាខ្មែរ',
|
||||
},
|
||||
'kab': {
|
||||
nativeName: 'Taqbaylit',
|
||||
},
|
||||
'kn': {
|
||||
nativeName: 'ಕನ್ನಡ',
|
||||
},
|
||||
'kn-IN': {
|
||||
nativeName: 'ಕನ್ನಡ (India)',
|
||||
},
|
||||
'ko': {
|
||||
nativeName: '한국어',
|
||||
},
|
||||
'ko-KR': {
|
||||
nativeName: '한국어 (한국)',
|
||||
},
|
||||
'ku-TR': {
|
||||
nativeName: 'Kurdî',
|
||||
},
|
||||
'kw': {
|
||||
nativeName: 'Kernewek',
|
||||
},
|
||||
'la': {
|
||||
nativeName: 'Latin',
|
||||
},
|
||||
'la-VA': {
|
||||
nativeName: 'Latin',
|
||||
},
|
||||
'lb': {
|
||||
nativeName: 'Lëtzebuergesch',
|
||||
},
|
||||
'li-NL': {
|
||||
nativeName: 'Lèmbörgs',
|
||||
},
|
||||
'lt': {
|
||||
nativeName: 'Lietuvių',
|
||||
},
|
||||
'lt-LT': {
|
||||
nativeName: 'Lietuvių',
|
||||
},
|
||||
'lv': {
|
||||
nativeName: 'Latviešu',
|
||||
},
|
||||
'lv-LV': {
|
||||
nativeName: 'Latviešu',
|
||||
},
|
||||
'mai': {
|
||||
nativeName: 'मैथिली, মৈথিলী',
|
||||
},
|
||||
'mg-MG': {
|
||||
nativeName: 'Malagasy',
|
||||
},
|
||||
'mk': {
|
||||
nativeName: 'Македонски',
|
||||
},
|
||||
'mk-MK': {
|
||||
nativeName: 'Македонски (Македонски)',
|
||||
},
|
||||
'ml': {
|
||||
nativeName: 'മലയാളം',
|
||||
},
|
||||
'ml-IN': {
|
||||
nativeName: 'മലയാളം',
|
||||
},
|
||||
'mn-MN': {
|
||||
nativeName: 'Монгол',
|
||||
},
|
||||
'mr': {
|
||||
nativeName: 'मराठी',
|
||||
},
|
||||
'mr-IN': {
|
||||
nativeName: 'मराठी',
|
||||
},
|
||||
'ms': {
|
||||
nativeName: 'Bahasa Melayu',
|
||||
},
|
||||
'ms-MY': {
|
||||
nativeName: 'Bahasa Melayu',
|
||||
},
|
||||
'mt': {
|
||||
nativeName: 'Malti',
|
||||
},
|
||||
'mt-MT': {
|
||||
nativeName: 'Malti',
|
||||
},
|
||||
'my': {
|
||||
nativeName: 'ဗမာစကာ',
|
||||
},
|
||||
'no': {
|
||||
nativeName: 'Norsk',
|
||||
},
|
||||
'nb': {
|
||||
nativeName: 'Norsk (bokmål)',
|
||||
},
|
||||
'nb-NO': {
|
||||
nativeName: 'Norsk (bokmål)',
|
||||
},
|
||||
'ne': {
|
||||
nativeName: 'नेपाली',
|
||||
},
|
||||
'ne-NP': {
|
||||
nativeName: 'नेपाली',
|
||||
},
|
||||
'nl': {
|
||||
nativeName: 'Nederlands',
|
||||
},
|
||||
'nl-BE': {
|
||||
nativeName: 'Nederlands (België)',
|
||||
},
|
||||
'nl-NL': {
|
||||
nativeName: 'Nederlands (Nederland)',
|
||||
},
|
||||
'nn-NO': {
|
||||
nativeName: 'Norsk (nynorsk)',
|
||||
},
|
||||
'oc': {
|
||||
nativeName: 'Occitan',
|
||||
},
|
||||
'or-IN': {
|
||||
nativeName: 'ଓଡ଼ିଆ',
|
||||
},
|
||||
'pa': {
|
||||
nativeName: 'ਪੰਜਾਬੀ',
|
||||
},
|
||||
'pa-IN': {
|
||||
nativeName: 'ਪੰਜਾਬੀ (ਭਾਰਤ ਨੂੰ)',
|
||||
},
|
||||
'pl': {
|
||||
nativeName: 'Polski',
|
||||
},
|
||||
'pl-PL': {
|
||||
nativeName: 'Polski',
|
||||
},
|
||||
'ps-AF': {
|
||||
nativeName: 'پښتو',
|
||||
},
|
||||
'pt': {
|
||||
nativeName: 'Português',
|
||||
},
|
||||
'pt-BR': {
|
||||
nativeName: 'Português (Brasil)',
|
||||
},
|
||||
'pt-PT': {
|
||||
nativeName: 'Português (Portugal)',
|
||||
},
|
||||
'qu-PE': {
|
||||
nativeName: 'Qhichwa',
|
||||
},
|
||||
'rm-CH': {
|
||||
nativeName: 'Rumantsch',
|
||||
},
|
||||
'ro': {
|
||||
nativeName: 'Română',
|
||||
},
|
||||
'ro-RO': {
|
||||
nativeName: 'Română',
|
||||
},
|
||||
'ru': {
|
||||
nativeName: 'Русский',
|
||||
},
|
||||
'ru-RU': {
|
||||
nativeName: 'Русский',
|
||||
},
|
||||
'sa-IN': {
|
||||
nativeName: 'संस्कृतम्',
|
||||
},
|
||||
'se-NO': {
|
||||
nativeName: 'Davvisámegiella',
|
||||
},
|
||||
'sh': {
|
||||
nativeName: 'српскохрватски',
|
||||
},
|
||||
'si-LK': {
|
||||
nativeName: 'සිංහල',
|
||||
},
|
||||
'sk': {
|
||||
nativeName: 'Slovenčina',
|
||||
},
|
||||
'sk-SK': {
|
||||
nativeName: 'Slovenčina (Slovakia)',
|
||||
},
|
||||
'sl': {
|
||||
nativeName: 'Slovenščina',
|
||||
},
|
||||
'sl-SI': {
|
||||
nativeName: 'Slovenščina',
|
||||
},
|
||||
'so-SO': {
|
||||
nativeName: 'Soomaaliga',
|
||||
},
|
||||
'sq': {
|
||||
nativeName: 'Shqip',
|
||||
},
|
||||
'sq-AL': {
|
||||
nativeName: 'Shqip',
|
||||
},
|
||||
'sr': {
|
||||
nativeName: 'Српски',
|
||||
},
|
||||
'sr-RS': {
|
||||
nativeName: 'Српски (Serbia)',
|
||||
},
|
||||
'su': {
|
||||
nativeName: 'Basa Sunda',
|
||||
},
|
||||
'sv': {
|
||||
nativeName: 'Svenska',
|
||||
},
|
||||
'sv-SE': {
|
||||
nativeName: 'Svenska',
|
||||
},
|
||||
'sw': {
|
||||
nativeName: 'Kiswahili',
|
||||
},
|
||||
'sw-KE': {
|
||||
nativeName: 'Kiswahili',
|
||||
},
|
||||
'ta': {
|
||||
nativeName: 'தமிழ்',
|
||||
},
|
||||
'ta-IN': {
|
||||
nativeName: 'தமிழ்',
|
||||
},
|
||||
'te': {
|
||||
nativeName: 'తెలుగు',
|
||||
},
|
||||
'te-IN': {
|
||||
nativeName: 'తెలుగు',
|
||||
},
|
||||
'tg': {
|
||||
nativeName: 'забо́ни тоҷикӣ́',
|
||||
},
|
||||
'tg-TJ': {
|
||||
nativeName: 'тоҷикӣ',
|
||||
},
|
||||
'th': {
|
||||
nativeName: 'ภาษาไทย',
|
||||
},
|
||||
'th-TH': {
|
||||
nativeName: 'ภาษาไทย (ประเทศไทย)',
|
||||
},
|
||||
'fil': {
|
||||
nativeName: 'Filipino',
|
||||
},
|
||||
'tlh': {
|
||||
nativeName: 'tlhIngan-Hol',
|
||||
},
|
||||
'tr': {
|
||||
nativeName: 'Türkçe',
|
||||
},
|
||||
'tr-TR': {
|
||||
nativeName: 'Türkçe',
|
||||
},
|
||||
'tt-RU': {
|
||||
nativeName: 'татарча',
|
||||
},
|
||||
'uk': {
|
||||
nativeName: 'Українська',
|
||||
},
|
||||
'uk-UA': {
|
||||
nativeName: 'Українська',
|
||||
},
|
||||
'ur': {
|
||||
nativeName: 'اردو',
|
||||
},
|
||||
'ur-PK': {
|
||||
nativeName: 'اردو',
|
||||
},
|
||||
'uz': {
|
||||
nativeName: 'O\'zbek',
|
||||
},
|
||||
'uz-UZ': {
|
||||
nativeName: 'O\'zbek',
|
||||
},
|
||||
'vi': {
|
||||
nativeName: 'Tiếng Việt',
|
||||
},
|
||||
'vi-VN': {
|
||||
nativeName: 'Tiếng Việt',
|
||||
},
|
||||
'xh-ZA': {
|
||||
nativeName: 'isiXhosa',
|
||||
},
|
||||
'yi': {
|
||||
nativeName: 'ייִדיש',
|
||||
},
|
||||
'yi-DE': {
|
||||
nativeName: 'ייִדיש (German)',
|
||||
},
|
||||
'zh': {
|
||||
nativeName: '中文',
|
||||
},
|
||||
'zh-Hans': {
|
||||
nativeName: '中文简体',
|
||||
},
|
||||
'zh-Hant': {
|
||||
nativeName: '中文繁體',
|
||||
},
|
||||
'zh-CN': {
|
||||
nativeName: '中文(中国大陆)',
|
||||
},
|
||||
'zh-HK': {
|
||||
nativeName: '中文(香港)',
|
||||
},
|
||||
'zh-SG': {
|
||||
nativeName: '中文(新加坡)',
|
||||
},
|
||||
'zh-TW': {
|
||||
nativeName: '中文(台灣)',
|
||||
},
|
||||
'zu-ZA': {
|
||||
nativeName: 'isiZulu',
|
||||
},
|
||||
};
|
||||
|
|
@ -17,6 +17,7 @@ export const themeProps = Object.keys(lightTheme.props).filter(key => !key.start
|
|||
|
||||
export const builtinThemes = [
|
||||
require('@/themes/l-light.json5'),
|
||||
require('@/themes/l-coffee.json5'),
|
||||
require('@/themes/l-apricot.json5'),
|
||||
require('@/themes/l-rainy.json5'),
|
||||
require('@/themes/l-vivid.json5'),
|
||||
|
|
@ -29,6 +30,7 @@ export const builtinThemes = [
|
|||
require('@/themes/d-future.json5'),
|
||||
require('@/themes/d-botanical.json5'),
|
||||
require('@/themes/d-cherry.json5'),
|
||||
require('@/themes/d-ice.json5'),
|
||||
require('@/themes/d-pumpkin.json5'),
|
||||
require('@/themes/d-black.json5'),
|
||||
] as Theme[];
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ export const defaultStore = markRaw(new Storage('base', {
|
|||
},
|
||||
keepCw: {
|
||||
where: 'account',
|
||||
default: false
|
||||
default: true
|
||||
},
|
||||
showFullAcct: {
|
||||
where: 'account',
|
||||
|
|
@ -230,6 +230,10 @@ export const defaultStore = markRaw(new Storage('base', {
|
|||
where: 'device',
|
||||
default: ''
|
||||
},
|
||||
themeInitial: {
|
||||
where: 'device',
|
||||
default: true,
|
||||
},
|
||||
aiChanMode: {
|
||||
where: 'device',
|
||||
default: false
|
||||
|
|
|
|||
13
packages/client/src/themes/d-ice.json5
Normal file
13
packages/client/src/themes/d-ice.json5
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
id: '66e7e5a9-cd43-42cd-837d-12f47841fa34',
|
||||
|
||||
name: 'Mi Ice Dark',
|
||||
author: 'syuilo',
|
||||
|
||||
base: 'dark',
|
||||
|
||||
props: {
|
||||
accent: '#47BFE8',
|
||||
bg: '#212526',
|
||||
},
|
||||
}
|
||||
21
packages/client/src/themes/l-coffee.json5
Normal file
21
packages/client/src/themes/l-coffee.json5
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
id: '6ed80faa-74f0-42c2-98e4-a64d9e138eab',
|
||||
|
||||
name: 'Mi Coffee Light',
|
||||
author: 'syuilo',
|
||||
|
||||
base: 'light',
|
||||
|
||||
props: {
|
||||
accent: '#9f8989',
|
||||
bg: '#f5f3f3',
|
||||
fg: '#7f6666',
|
||||
panel: '#fff',
|
||||
divider: 'rgba(87, 68, 68, 0.1)',
|
||||
renote: 'rgb(160, 172, 125)',
|
||||
link: 'rgb(137, 151, 159)',
|
||||
mention: '@accent',
|
||||
mentionMe: 'rgb(170, 149, 98)',
|
||||
hashtag: '@accent',
|
||||
},
|
||||
}
|
||||
|
|
@ -11,6 +11,8 @@
|
|||
<XStreamIndicator/>
|
||||
|
||||
<div v-if="pendingApiRequestsCount > 0" id="wait"></div>
|
||||
|
||||
<div v-if="dev" id="devTicker"><span>DEV BUILD</span></div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
|
@ -58,12 +60,28 @@ export default defineComponent({
|
|||
uploads,
|
||||
popups,
|
||||
pendingApiRequestsCount,
|
||||
dev: _DEV_,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@keyframes dev-ticker-blink {
|
||||
0% { opacity: 1; }
|
||||
50% { opacity: 0; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@keyframes progress-spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
#wait {
|
||||
display: block;
|
||||
position: fixed;
|
||||
|
|
@ -85,12 +103,19 @@ export default defineComponent({
|
|||
}
|
||||
}
|
||||
|
||||
@keyframes progress-spinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
#devTicker {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2147483647;
|
||||
color: #ff0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
padding: 4px 5px;
|
||||
font-size: 14px;
|
||||
pointer-events: none;
|
||||
|
||||
> span {
|
||||
animation: dev-ticker-blink 2s infinite;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -25,69 +25,55 @@
|
|||
<MkA v-click-anime class="item" active-class="active" to="/settings">
|
||||
<i class="fas fa-cog fa-fw"></i><span class="text">{{ $ts.settings }}</span>
|
||||
</MkA>
|
||||
<button class="item _button post" data-cy-open-post-form @click="post">
|
||||
<button class="item _button post" data-cy-open-post-form @click="os.post">
|
||||
<i class="fas fa-pencil-alt fa-fw"></i><span class="text">{{ $ts.note }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, ref, watch } from 'vue';
|
||||
import { host } from '@/config';
|
||||
import { search } from '@/scripts/search';
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import * as os from '@/os';
|
||||
import { menuDef } from '@/menu';
|
||||
import { openAccountMenu } from '@/account';
|
||||
import { $i, openAccountMenu as openAccountMenu_ } from '@/account';
|
||||
import { defaultStore } from '@/store';
|
||||
|
||||
export default defineComponent({
|
||||
setup(props, context) {
|
||||
const iconOnly = ref(false);
|
||||
const iconOnly = ref(false);
|
||||
|
||||
const menu = computed(() => defaultStore.state.menu);
|
||||
const otherMenuItemIndicated = computed(() => {
|
||||
for (const def in menuDef) {
|
||||
if (menu.value.includes(def)) continue;
|
||||
if (menuDef[def].indicated) return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const calcViewState = () => {
|
||||
iconOnly.value = (window.innerWidth <= 1279) || (defaultStore.state.menuDisplay === 'sideIcon');
|
||||
};
|
||||
|
||||
calcViewState();
|
||||
|
||||
window.addEventListener('resize', calcViewState);
|
||||
|
||||
watch(defaultStore.reactiveState.menuDisplay, () => {
|
||||
calcViewState();
|
||||
});
|
||||
|
||||
return {
|
||||
host: host,
|
||||
accounts: [],
|
||||
connection: null,
|
||||
menu,
|
||||
menuDef: menuDef,
|
||||
otherMenuItemIndicated,
|
||||
iconOnly,
|
||||
post: os.post,
|
||||
search,
|
||||
openAccountMenu:(ev) => {
|
||||
openAccountMenu({
|
||||
withExtraOperation: true,
|
||||
}, ev);
|
||||
},
|
||||
more: () => {
|
||||
os.popup(import('@/components/launch-pad.vue'), {}, {
|
||||
}, 'closed');
|
||||
},
|
||||
};
|
||||
},
|
||||
const menu = computed(() => defaultStore.state.menu);
|
||||
const otherMenuItemIndicated = computed(() => {
|
||||
for (const def in menuDef) {
|
||||
if (menu.value.includes(def)) continue;
|
||||
if (menuDef[def].indicated) return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
const calcViewState = () => {
|
||||
iconOnly.value = (window.innerWidth <= 1279) || (defaultStore.state.menuDisplay === 'sideIcon');
|
||||
};
|
||||
|
||||
calcViewState();
|
||||
|
||||
window.addEventListener('resize', calcViewState);
|
||||
|
||||
watch(defaultStore.reactiveState.menuDisplay, () => {
|
||||
calcViewState();
|
||||
});
|
||||
|
||||
function openAccountMenu(ev: MouseEvent) {
|
||||
openAccountMenu_({
|
||||
withExtraOperation: true,
|
||||
}, ev);
|
||||
}
|
||||
|
||||
function more(ev: MouseEvent) {
|
||||
os.popup(import('@/components/launch-pad.vue'), {
|
||||
src: ev.currentTarget ?? ev.target,
|
||||
}, {
|
||||
}, 'closed');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -101,11 +101,13 @@ export default defineComponent({
|
|||
},
|
||||
|
||||
more(ev) {
|
||||
os.popup(import('@/components/launch-pad.vue'), {}, {
|
||||
os.popup(import('@/components/launch-pad.vue'), {
|
||||
src: ev.currentTarget ?? ev.target,
|
||||
}, {
|
||||
}, 'closed');
|
||||
},
|
||||
|
||||
openAccountMenu:(ev) => {
|
||||
openAccountMenu: (ev) => {
|
||||
openAccountMenu({
|
||||
withExtraOperation: true,
|
||||
}, ev);
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ export default defineComponent({
|
|||
|
||||
more(ev) {
|
||||
os.popup(import('@/components/launch-pad.vue'), {}, {
|
||||
src: ev.currentTarget ?? ev.target,
|
||||
}, 'closed');
|
||||
},
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue