Compare commits

...

11 Commits

Author SHA1 Message Date
923cacb98a README.md aktualisiert 2025-03-23 18:29:44 +00:00
b1e564b562 .gitea/workflows/registry.yml hinzugefügt 2025-03-23 18:28:46 +00:00
syuilo
0471e457fe fix(frontend): fix broken styles 2025-03-23 21:23:52 +09:00
syuilo
260d35e2f0 Update CHANGELOG.md 2025-03-22 18:37:41 +09:00
syuilo
3ff9d9f4fd Update CHANGELOG.md 2025-03-22 18:34:56 +09:00
syuilo
27991a3bc8 Update CHANGELOG.md 2025-03-22 18:28:51 +09:00
syuilo
b5f86e5210 refactor(frontend): refactor page styles 2025-03-22 18:25:45 +09:00
syuilo
16cde5568d Update CHANGELOG.md 2025-03-22 15:12:24 +09:00
syuilo
bf07796b6b Update CHANGELOG.md 2025-03-22 15:08:19 +09:00
syuilo
08b131ec33 refactor(backend): better prop name 2025-03-22 08:16:15 +09:00
syuilo
1312fe34c1 Update CHANGELOG.md 2025-03-22 08:12:32 +09:00
41 changed files with 134 additions and 69 deletions

View File

@@ -0,0 +1,51 @@
name: release-tag
on:
push:
branches:
- 'main'
jobs:
release-image:
runs-on: ubuntu-latest
env:
DOCKER_ORG: sendnrw
DOCKER_LATEST: latest
RUNNER_TOOL_CACHE: /toolcache
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker BuildX
uses: docker/setup-buildx-action@v2
with: # replace it with your local IP
config-inline: |
[registry."git.send.nrw"]
http = true
insecure = true
- name: Login to DockerHub
uses: docker/login-action@v2
with:
registry: git.send.nrw # replace it with your local IP
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Get Meta
id: meta
run: |
echo REPO_NAME=$(echo ${GITHUB_REPOSITORY} | awk -F"/" '{print $2}') >> $GITHUB_OUTPUT
echo REPO_VERSION=$(git describe --tags --always | sed 's/^v//') >> $GITHUB_OUTPUT
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
file: ./Dockerfile
platforms: |
linux/amd64
push: true
tags: | # replace it with your local IP and tags
git.send.nrw/${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}
git.send.nrw/${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}

View File

@@ -6,9 +6,24 @@
### Client
- Feat: 設定の管理が強化されました
- 自動でバックアップされるように
- 内部処理が一新され、安定性とパフォーマンスが向上しました
- 全てのクライアント設定がエクスポート(バックアップ)/インポート対象に含まれるようになりました
- プラグイン、テーマ、クライアントに追加されたすべてのアカウント情報も含まれるようになりました
- 自動で設定データをサーバーにバックアップできるように
- 設定→設定のプロファイル→自動バックアップ で有効にできます
- 新しいデバイスからログインしたり、ブラウザから設定データが消えてしまったときに自動で復元されます(復元をスキップすることも可能)
- 任意の設定項目をデバイス間で同期できるように
- 設定項目の「...」メニュー→「デバイス間で同期」
- 同期をオンにした際にサーバーに保存された値とローカルの値が競合する場合はどちらを優先するか選択できます
- 任意の設定項目を初期値にリセットできるように
- 設定項目の「...」メニュー→「初期値にリセット」
- アカウントごとに設定値が分離される設定とそうでないクライアント設定が混在していた(かつ分離するかどうかを設定不可だった)のを、基本的に一律でクライアント全体に適用されるようにし、個別でアカウントごとに異なる設定を行えるように
- 設定項目の「...」メニュー→「アカウントで上書き」をオンにすることで、設定値をそのアカウントでだけ適用するようにできます
- ログアウトすると設定データもブラウザから消去されるようになりプライバシーが向上しました
- 再度ログインすればサーバーのバックアップから設定データを復元可能です
- エクスポートした設定データを他のサーバーでインポートして適用すること(設定の持ち運び)が可能になりました
- Feat: 画面を重ねて表示するオプションを実装(実験的)
- 設定 → その他 → 実験的機能 → Enable stacking router view
- Enhance: プラグインの管理が強化されました
- インストール/アンインストール/設定の変更時にリロード不要になりました
- Enhance: ログアウト時、ブラウザに保存されたWebクライアントのデータを全て消去するように

View File

@@ -6,7 +6,7 @@
**🌎 **Misskey** is an open source, federated social media platform that's free forever! 🚀**
[Learn more](https://misskey-hub.net/)
---
<a href="https://misskey-hub.net/servers/">

View File

@@ -391,10 +391,10 @@ export class ApiCallService implements OnApplicationShutdown {
}
}
if (ep.meta.requireRolePolicy != null && (this.meta.rootUserId !== user!.id)) {
if (ep.meta.requiredRolePolicy != null && (this.meta.rootUserId !== user!.id)) {
const myRoles = await this.roleService.getUserRoles(user!.id);
const policies = await this.roleService.getUserPolicies(user!.id);
if (!policies[ep.meta.requireRolePolicy] && !myRoles.some(r => r.isAdministrator)) {
if (!policies[ep.meta.requiredRolePolicy] && !myRoles.some(r => r.isAdministrator)) {
throw new ApiError({
message: 'You are not assigned to a required role.',
code: 'ROLE_PERMISSION_DENIED',

View File

@@ -39,7 +39,7 @@ interface IEndpointMetaBase {
*/
readonly requireAdmin?: boolean;
readonly requireRolePolicy?: KeyOf<'RolePolicies'>;
readonly requiredRolePolicy?: KeyOf<'RolePolicies'>;
/**
* 引っ越し済みのユーザーによるリクエストを禁止するか

View File

@@ -12,7 +12,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageAvatarDecorations',
requiredRolePolicy: 'canManageAvatarDecorations',
kind: 'write:admin:avatar-decorations',
res: {

View File

@@ -13,7 +13,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageAvatarDecorations',
requiredRolePolicy: 'canManageAvatarDecorations',
kind: 'write:admin:avatar-decorations',
errors: {
},

View File

@@ -13,7 +13,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageAvatarDecorations',
requiredRolePolicy: 'canManageAvatarDecorations',
kind: 'read:admin:avatar-decorations',
res: {

View File

@@ -13,7 +13,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageAvatarDecorations',
requiredRolePolicy: 'canManageAvatarDecorations',
kind: 'write:admin:avatar-decorations',
errors: {

View File

@@ -11,7 +11,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'write:admin:emoji',
} as const;

View File

@@ -16,7 +16,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'write:admin:emoji',
errors: {

View File

@@ -17,7 +17,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'write:admin:emoji',
errors: {

View File

@@ -11,7 +11,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'write:admin:emoji',
} as const;

View File

@@ -11,7 +11,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'write:admin:emoji',
errors: {

View File

@@ -10,7 +10,7 @@ import { QueueService } from '@/core/QueueService.js';
export const meta = {
secure: true,
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
} as const;
export const paramDef = {

View File

@@ -16,7 +16,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'read:admin:emoji',
res: {

View File

@@ -16,7 +16,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'read:admin:emoji',
res: {

View File

@@ -11,7 +11,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'write:admin:emoji',
} as const;

View File

@@ -11,7 +11,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'write:admin:emoji',
} as const;

View File

@@ -11,7 +11,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'write:admin:emoji',
} as const;

View File

@@ -11,7 +11,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'write:admin:emoji',
} as const;

View File

@@ -14,7 +14,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'write:admin:emoji',
errors: {

View File

@@ -16,7 +16,7 @@ import { ApiError } from '../../error.js';
export const meta = {
secure: true,
requireCredential: true,
requireRolePolicy: 'canImportAntennas',
requiredRolePolicy: 'canImportAntennas',
prohibitMoved: true,
limit: {

View File

@@ -15,7 +15,7 @@ import { ApiError } from '../../error.js';
export const meta = {
secure: true,
requireCredential: true,
requireRolePolicy: 'canImportBlocking',
requiredRolePolicy: 'canImportBlocking',
prohibitMoved: true,
limit: {

View File

@@ -15,7 +15,7 @@ import { ApiError } from '../../error.js';
export const meta = {
secure: true,
requireCredential: true,
requireRolePolicy: 'canImportFollowing',
requiredRolePolicy: 'canImportFollowing',
prohibitMoved: true,
limit: {
duration: ms('1hour'),

View File

@@ -15,7 +15,7 @@ import { ApiError } from '../../error.js';
export const meta = {
secure: true,
requireCredential: true,
requireRolePolicy: 'canImportMuting',
requiredRolePolicy: 'canImportMuting',
prohibitMoved: true,
limit: {

View File

@@ -15,7 +15,7 @@ import { ApiError } from '../../error.js';
export const meta = {
secure: true,
requireCredential: true,
requireRolePolicy: 'canImportUserLists',
requiredRolePolicy: 'canImportUserLists',
prohibitMoved: true,
limit: {
duration: ms('1hour'),

View File

@@ -18,7 +18,7 @@ export const meta = {
tags: ['meta'],
requireCredential: true,
requireRolePolicy: 'canInvite',
requiredRolePolicy: 'canInvite',
kind: 'write:invite-codes',
errors: {

View File

@@ -14,7 +14,7 @@ export const meta = {
tags: ['meta'],
requireCredential: true,
requireRolePolicy: 'canInvite',
requiredRolePolicy: 'canInvite',
kind: 'write:invite-codes',
errors: {

View File

@@ -15,7 +15,7 @@ export const meta = {
tags: ['meta'],
requireCredential: true,
requireRolePolicy: 'canInvite',
requiredRolePolicy: 'canInvite',
kind: 'read:invite-codes',
res: {

View File

@@ -14,7 +14,7 @@ export const meta = {
tags: ['meta'],
requireCredential: true,
requireRolePolicy: 'canInvite',
requiredRolePolicy: 'canInvite',
kind: 'read:invite-codes',
res: {

View File

@@ -12,7 +12,7 @@ export const meta = {
tags: ['admin'],
requireCredential: true,
requireRolePolicy: 'canManageCustomEmojis',
requiredRolePolicy: 'canManageCustomEmojis',
kind: 'read:admin:emoji',
res: {

View File

@@ -109,12 +109,6 @@ export const ROLE_POLICIES = [
'canImportUserLists',
] as const;
// なんか動かない
//export const CURRENT_STICKY_TOP = Symbol('CURRENT_STICKY_TOP');
//export const CURRENT_STICKY_BOTTOM = Symbol('CURRENT_STICKY_BOTTOM');
export const CURRENT_STICKY_TOP = 'CURRENT_STICKY_TOP';
export const CURRENT_STICKY_BOTTOM = 'CURRENT_STICKY_BOTTOM';
export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://xn--931a.moe/assets/error.jpg';
export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://xn--931a.moe/assets/not-found.jpg';
export const DEFAULT_INFO_IMAGE_URL = 'https://xn--931a.moe/assets/info.jpg';

View File

@@ -23,8 +23,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { onMounted, onUnmounted, provide, inject, ref, watch, useTemplateRef } from 'vue';
import { CURRENT_STICKY_BOTTOM, CURRENT_STICKY_TOP } from '@@/js/const.js';
import type { Ref } from 'vue';
import { DI } from '@/di.js';
const rootEl = useTemplateRef('rootEl');
const headerEl = useTemplateRef('headerEl');
@@ -32,13 +31,13 @@ const footerEl = useTemplateRef('footerEl');
const headerHeight = ref<string | undefined>();
const childStickyTop = ref(0);
const parentStickyTop = inject<Ref<number>>(CURRENT_STICKY_TOP, ref(0));
provide(CURRENT_STICKY_TOP, childStickyTop);
const parentStickyTop = inject(DI.currentStickyTop, ref(0));
provide(DI.currentStickyTop, childStickyTop);
const footerHeight = ref<string | undefined>();
const childStickyBottom = ref(0);
const parentStickyBottom = inject<Ref<number>>(CURRENT_STICKY_BOTTOM, ref(0));
provide(CURRENT_STICKY_BOTTOM, childStickyBottom);
const parentStickyBottom = inject(DI.currentStickyBottom, ref(0));
provide(DI.currentStickyBottom, childStickyBottom);
const calc = () => {
// コンポーネントが表示されてないけどKeepAliveで残ってる場合などは null になる

View File

@@ -4,11 +4,15 @@ SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<MkStickyContainer class="_pageScrollable">
<template #header><MkPageHeader v-model:tab="tab" :actions="actions" :tabs="tabs"/></template>
<slot></slot>
<template #footer><slot name="footer"></slot></template>
</MkStickyContainer>
<div :class="[$style.root, reversed ? '_pageScrollableReversed' : '_pageScrollable']">
<MkStickyContainer>
<template #header><MkPageHeader v-model:tab="tab" :actions="actions" :tabs="tabs"/></template>
<div :class="$style.body">
<slot></slot>
</div>
<template #footer><slot name="footer"></slot></template>
</MkStickyContainer>
</div>
</template>
<script lang="ts" setup>
@@ -21,6 +25,7 @@ const props = withDefaults(defineProps<{
thin?: boolean;
hideTitle?: boolean;
displayMyAvatar?: boolean;
reversed?: boolean;
}>(), {
tabs: () => ([] as Tab[]),
});
@@ -29,5 +34,11 @@ const tab = defineModel<string>('tab');
</script>
<style lang="scss" module>
.root {
}
.body {
min-height: calc(100cqh - (var(--MI-stickyTop, 0px) + var(--MI-stickyBottom, 0px)));
}
</style>

View File

@@ -12,4 +12,6 @@ export const DI = {
mock: Symbol() as InjectionKey<boolean>,
pageMetadata: Symbol() as InjectionKey<Ref<Record<string, any>>>,
viewId: Symbol() as InjectionKey<string>,
currentStickyTop: Symbol() as InjectionKey<Ref<number>>,
currentStickyBottom: Symbol() as InjectionKey<Ref<number>>,
};

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="700" :class="$style.main">
<MkSpacer :contentMax="700">
<MkHorizontalSwipe v-model:tab="tab" :tabs="headerTabs">
<div v-if="channel && tab === 'overview'" class="_gaps">
<div class="_panel" :class="$style.bannerContainer">
@@ -270,10 +270,6 @@ definePage(() => ({
</script>
<style lang="scss" module>
.main {
min-height: calc(100cqh - (var(--MI-stickyTop, 0px) + var(--MI-stickyBottom, 0px)));
}
.footer {
-webkit-backdrop-filter: var(--MI-blur, blur(15px));
backdrop-filter: var(--MI-blur, blur(15px));

View File

@@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only
</p>
</div>
</MkSpacer>
<MkSpacer v-else-if="list" :contentMax="700" :class="$style.main">
<MkSpacer v-else-if="list" :contentMax="700">
<div v-if="list" class="members _margin">
<div :class="$style.member_text">{{ i18n.ts.members }}</div>
<div class="_gaps_s">
@@ -106,10 +106,6 @@ definePage(() => ({
}));
</script>
<style lang="scss" module>
.main {
min-height: calc(100cqh - (var(--MI-stickyTop, 0px) + var(--MI-stickyBottom, 0px)));
}
.userItem {
display: flex;
}

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<PageWithHeader :actions="headerActions" :tabs="headerTabs">
<MkSpacer :contentMax="700" :class="$style.main">
<MkSpacer :contentMax="700">
<div v-if="list" class="_gaps">
<MkFolder>
<template #label>{{ i18n.ts.settings }}</template>
@@ -197,10 +197,6 @@ definePage(() => ({
</script>
<style lang="scss" module>
.main {
min-height: calc(100cqh - (var(--MI-stickyTop, 0px) + var(--MI-stickyBottom, 0px)));
}
.userItem {
display: flex;
}

View File

@@ -179,11 +179,20 @@ rt {
._pageScrollable {
height: 100%;
overflow: auto;
overflow: clip;
overflow-y: scroll;
overscroll-behavior: contain;
}
._pageScrollableReversed {
height: 100%;
overflow: clip;
overflow-y: scroll;
overscroll-behavior: contain;
display: flex;
flex-direction: column-reverse;
}
._indicatorCircle {
display: inline-block;
width: 1em;

View File

@@ -97,7 +97,6 @@ SPDX-License-Identifier: AGPL-3.0-only
<script lang="ts" setup>
import { defineAsyncComponent, provide, onMounted, computed, ref, watch, useTemplateRef } from 'vue';
import { instanceName } from '@@/js/config.js';
import { CURRENT_STICKY_BOTTOM } from '@@/js/const.js';
import { isLink } from '@@/js/is-link.js';
import XCommon from './_common_/common.vue';
import type { Ref } from 'vue';
@@ -200,16 +199,13 @@ const onContextmenu = (ev) => {
};
const navFooterHeight = ref(0);
provide<Ref<number>>(CURRENT_STICKY_BOTTOM, navFooterHeight);
watch(navFooter, () => {
if (navFooter.value) {
navFooterHeight.value = navFooter.value.offsetHeight;
window.document.body.style.setProperty('--MI-stickyBottom', `${navFooterHeight.value}px`);
window.document.body.style.setProperty('--MI-minBottomSpacing', 'var(--MI-minBottomSpacingMobile)');
} else {
navFooterHeight.value = 0;
window.document.body.style.setProperty('--MI-stickyBottom', '0px');
window.document.body.style.setProperty('--MI-minBottomSpacing', '0px');
}
}, {