Merge branch 'misskey-develop' into merge/2025-03-24

This commit is contained in:
Hazelnoot 2025-03-31 16:07:41 -04:00
commit 2983092c06
59 changed files with 633 additions and 251 deletions

View file

@ -296,7 +296,7 @@ onMounted(async () => {
left: 0;
padding: 12px;
border-top: solid 0.5px var(--MI_THEME-divider);
background: var(--MI_THEME-acrylicBg);
background: color(from var(--MI_THEME-bg) srgb r g b / 0.5);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
}

View file

@ -213,7 +213,7 @@ async function del() {
left: 0;
padding: 12px;
border-top: solid 0.5px var(--MI_THEME-divider);
background: var(--MI_THEME-acrylicBg);
background: color(from var(--MI_THEME-bg) srgb r g b / 0.5);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
}

View file

@ -304,7 +304,7 @@ definePage(() => ({
.footer {
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
background: var(--MI_THEME-acrylicBg);
background: color(from var(--MI_THEME-bg) srgb r g b / 0.5);
border-top: solid 0.5px var(--MI_THEME-divider);
}

View file

@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="[$style.root, { [$style.isMe]: isMe }]">
<MkAvatar :class="$style.avatar" :user="message.fromUser" :link="!isMe" :preview="false"/>
<div :class="$style.body" @contextmenu.stop="onContextmenu">
<div v-if="!isMe && prefer.s['chat.showSenderName']" :class="$style.header"><MkUserName :user="message.fromUser"/></div>
<div :class="$style.header"><MkUserName v-if="!isMe && prefer.s['chat.showSenderName']" :user="message.fromUser"/></div>
<MkFukidashi :class="$style.fukidashi" :tail="isMe ? 'right' : 'left'" :accented="isMe">
<div v-if="!message.isDeleted" :class="$style.content">
<Mfm
@ -216,10 +216,6 @@ function showMenu(ev: MouseEvent, contextmenu = false) {
flex-direction: row-reverse;
text-align: right;
.content {
color: var(--MI_THEME-fgOnAccent);
}
.footer {
flex-direction: row-reverse;
}
@ -230,8 +226,27 @@ function showMenu(ev: MouseEvent, contextmenu = false) {
position: sticky;
top: calc(16px + var(--MI-stickyTop, 0px));
display: block;
width: 52px;
height: 52px;
width: 50px;
height: 50px;
}
@container (max-width: 450px) {
.root {
&.isMe {
.avatar {
display: none;
}
}
}
.avatar {
width: 42px;
height: 42px;
}
.fukidashi {
font-size: 90%;
}
}
.body {
@ -239,6 +254,7 @@ function showMenu(ev: MouseEvent, contextmenu = false) {
}
.header {
min-height: 4px; // fukidashi調
font-size: 80%;
}
@ -252,9 +268,6 @@ function showMenu(ev: MouseEvent, contextmenu = false) {
word-break: break-word;
}
.file {
}
.footer {
display: flex;
flex-direction: row;

View file

@ -119,7 +119,8 @@ function start(ev: MouseEvent) {
}
async function startUser() {
os.selectUser().then(user => {
// TODO: localOnly
os.selectUser({ localOnly: true }).then(user => {
router.push(`/chat/user/${user.id}`);
});
}

View file

@ -63,11 +63,11 @@ function save() {
async function del() {
const { canceled } = await os.confirm({
type: 'warning',
text: i18n.ts.areYouSure,
text: i18n.tsx.deleteAreYouSure({ x: name_.value }),
});
if (canceled) return;
misskeyApi('chat/rooms/delete', {
await os.apiWithDialog('chat/rooms/delete', {
roomId: props.room.id,
});
router.push('/chat');
@ -81,10 +81,6 @@ watch(isMuted, async () => {
mute: isMuted.value,
});
});
onMounted(async () => {
});
</script>
<style lang="scss" module>

View file

@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkUserCardMini :user="room.owner"/>
</MkA>
<hr>
<hr v-if="memberships.length > 0">
<div v-for="membership in memberships" :key="membership.id" :class="$style.membership">
<MkA :class="$style.membershipBody" :to="`${userPage(membership.user)}`">

View file

@ -9,20 +9,25 @@ SPDX-License-Identifier: AGPL-3.0-only
v-model="searchQuery"
:placeholder="i18n.ts._chat.searchMessages"
type="search"
@enter="search()"
>
<template #prefix><i class="ti ti-search"></i></template>
</MkInput>
<MkButton v-if="searchQuery.length > 0" primary rounded @click="search">{{ i18n.ts.search }}</MkButton>
<MkButton primary rounded @click="search">{{ i18n.ts.search }}</MkButton>
<MkFoldableSection v-if="searched">
<template #header>{{ i18n.ts.searchResult }}</template>
<div class="_gaps_s">
<div v-if="searchResults.length > 0" class="_gaps_s">
<div v-for="message in searchResults" :key="message.id" :class="$style.searchResultItem">
<XMessage :message="message" :user="message.fromUser" :isSearchResult="true"/>
</div>
</div>
<div v-else class="_fullinfo">
<img :src="infoImageUrl" draggable="false"/>
<div>{{ i18n.ts.notFound }}</div>
</div>
</MkFoldableSection>
</div>
</template>
@ -33,6 +38,7 @@ import * as Misskey from 'misskey-js';
import XMessage from './XMessage.vue';
import MkButton from '@/components/MkButton.vue';
import { i18n } from '@/i18n.js';
import { infoImageUrl } from '@/instance.js';
import { misskeyApi } from '@/utility/misskey-api.js';
import * as os from '@/os.js';
import MkInput from '@/components/MkInput.vue';

View file

@ -67,7 +67,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<Transition name="fade">
<div v-show="showIndicator" :class="$style.new">
<button class="_buttonPrimary" :class="$style.newButton" @click="onIndicatorClick">
<i class="fas ti-fw fa-arrow-circle-down" :class="$style.newIcon"></i>{{ i18n.ts.newMessageExists }}
<i class="fas ti-fw fa-arrow-circle-down" :class="$style.newIcon"></i>{{ i18n.ts._chat.newMessage }}
</button>
</div>
</Transition>
@ -391,6 +391,7 @@ const headerActions = computed(() => [{
definePage(computed(() => !initializing.value ? user.value ? {
userName: user,
title: user.value.name ?? user.value.username,
avatar: user,
} : {
title: room.value?.name,

View file

@ -245,7 +245,7 @@ async function del() {
left: 0;
padding: 12px;
border-top: solid 0.5px var(--MI_THEME-divider);
background: var(--MI_THEME-acrylicBg);
background: color(from var(--MI_THEME-bg) srgb r g b / 0.5);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
}

View file

@ -467,7 +467,7 @@ definePage(() => ({
<style lang="scss" module>
.footer {
backdrop-filter: var(--MI-blur, blur(15px));
background: var(--MI_THEME-acrylicBg);
background: color(from var(--MI_THEME-bg) srgb r g b / 0.5);
border-top: solid .5px var(--MI_THEME-divider);
}
</style>

View file

@ -292,7 +292,7 @@ onUnmounted(() => {
.footer {
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
background: var(--MI_THEME-acrylicBg);
background: color(from var(--MI_THEME-bg) srgb r g b / 0.5);
border-top: solid 0.5px var(--MI_THEME-divider);
}
</style>

View file

@ -45,6 +45,35 @@ SPDX-License-Identifier: AGPL-3.0-only
</MkRadios>
</MkPreferenceContainer>
</SearchMarker>
<SearchMarker :keywords="['menu', 'position']">
<MkPreferenceContainer k="deck.menuPosition">
<MkRadios v-model="menuPosition">
<template #label><SearchLabel>{{ i18n.ts._deck.deckMenuPosition }}</SearchLabel></template>
<option value="right">{{ i18n.ts.right }}</option>
<option value="bottom">{{ i18n.ts.bottom }}</option>
</MkRadios>
</MkPreferenceContainer>
</SearchMarker>
<SearchMarker :keywords="['navbar', 'position']">
<MkPreferenceContainer k="deck.navbarPosition">
<MkRadios v-model="navbarPosition">
<template #label><SearchLabel>{{ i18n.ts._deck.navbarPosition }}</SearchLabel></template>
<option value="left">{{ i18n.ts.left }}</option>
<option value="top">{{ i18n.ts.top }}</option>
<option value="bottom">{{ i18n.ts.bottom }}</option>
</MkRadios>
</MkPreferenceContainer>
</SearchMarker>
<SearchMarker :keywords="['column', 'gap', 'margin']">
<MkPreferenceContainer k="deck.columnGap">
<MkRange v-model="columnGap" :min="3" :max="100" :step="1" :continuousUpdate="true">
<template #label><SearchLabel>{{ i18n.ts._deck.columnGap }}</SearchLabel></template>
</MkRange>
</MkPreferenceContainer>
</SearchMarker>
</div>
</SearchMarker>
</template>
@ -53,6 +82,7 @@ SPDX-License-Identifier: AGPL-3.0-only
import { computed, ref } from 'vue';
import MkSwitch from '@/components/MkSwitch.vue';
import MkRadios from '@/components/MkRadios.vue';
import MkRange from '@/components/MkRange.vue';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
import { prefer } from '@/preferences.js';
@ -62,6 +92,9 @@ const navWindow = prefer.model('deck.navWindow');
const useSimpleUiForNonRootPages = prefer.model('deck.useSimpleUiForNonRootPages');
const alwaysShowMainColumn = prefer.model('deck.alwaysShowMainColumn');
const columnAlign = prefer.model('deck.columnAlign');
const columnGap = prefer.model('deck.columnGap');
const menuPosition = prefer.model('deck.menuPosition');
const navbarPosition = prefer.model('deck.navbarPosition');
const profilesSyncEnabled = ref(prefer.isSyncEnabled('deck.profiles'));

View file

@ -38,14 +38,13 @@ import MkTextarea from '@/components/MkTextarea.vue';
import MkSelect from '@/components/MkSelect.vue';
import MkInput from '@/components/MkInput.vue';
import MkButton from '@/components/MkButton.vue';
import { getBuiltinThemesRef } from '@/theme.js';
import { getBuiltinThemesRef, getThemesRef, removeTheme } from '@/theme.js';
import { copyToClipboard } from '@/utility/copy-to-clipboard.js';
import * as os from '@/os.js';
import { getThemes, removeTheme } from '@/theme-store.js';
import { i18n } from '@/i18n.js';
import { definePage } from '@/page.js';
const installedThemes = ref(getThemes());
const installedThemes = getThemesRef();
const builtinThemes = getBuiltinThemesRef();
const selectedThemeId = ref<string | null>(null);

View file

@ -210,20 +210,19 @@ import FormLink from '@/components/form/link.vue';
import MkButton from '@/components/MkButton.vue';
import MkFolder from '@/components/MkFolder.vue';
import MkThemePreview from '@/components/MkThemePreview.vue';
import { getBuiltinThemesRef } from '@/theme.js';
import { getBuiltinThemesRef, getThemesRef } from '@/theme.js';
import { selectFile } from '@/utility/select-file.js';
import { isDeviceDarkmode } from '@/utility/is-device-darkmode.js';
import { store } from '@/store.js';
import { i18n } from '@/i18n.js';
import { instance } from '@/instance.js';
import { uniqueBy } from '@/utility/array.js';
import { getThemes } from '@/theme-store.js';
import { definePage } from '@/page.js';
import { miLocalStorage } from '@/local-storage.js';
import { reloadAsk } from '@/utility/reload-ask.js';
import { prefer } from '@/preferences.js';
const installedThemes = ref(getThemes());
const installedThemes = getThemesRef();
const builtinThemes = getBuiltinThemesRef();
const instanceDarkTheme = computed<Theme | null>(() => instance.defaultDarkTheme ? JSON5.parse(instance.defaultDarkTheme) : null);
@ -281,10 +280,6 @@ watch(wallpaper, async () => {
await reloadAsk({ reason: i18n.ts.reloadToApplySetting, unison: true });
});
onActivated(() => {
installedThemes.value = getThemes();
});
function setWallpaper(event) {
selectFile(event.currentTarget ?? event.target, null).then(file => {
wallpaper.value = file.url;

View file

@ -77,7 +77,7 @@ definePage(() => ({
.footer {
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
background: var(--MI_THEME-acrylicBg);
background: color(from var(--MI_THEME-bg) srgb r g b / 0.5);
border-top: solid 0.5px var(--MI_THEME-divider);
display: flex;
}

View file

@ -86,10 +86,9 @@ import MkCodeEditor from '@/components/MkCodeEditor.vue';
import MkTextarea from '@/components/MkTextarea.vue';
import MkFolder from '@/components/MkFolder.vue';
import { $i } from '@/i.js';
import { applyTheme } from '@/theme.js';
import { addTheme, applyTheme } from '@/theme.js';
import * as os from '@/os.js';
import { store } from '@/store.js';
import { addTheme } from '@/theme-store.js';
import { i18n } from '@/i18n.js';
import { useLeaveGuard } from '@/use/use-leave-guard.js';
import { definePage } from '@/page.js';

View file

@ -151,7 +151,7 @@ misskeyApiGet('federation/instances', {
left: 0;
right: 0;
margin: auto;
background: var(--MI_THEME-acrylicPanel);
background: color(from var(--MI_THEME-panel) srgb r g b / 0.5);
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));
border-radius: var(--MI-radius-ellipse);