1
1
mirror of https://github.com/kokonect-link/cherrypick synced 2024-11-23 22:56:53 +09:00

Merge remote-branch 'misskey/develop'

This commit is contained in:
NoriDev 2023-06-01 10:16:23 +09:00
commit 1d98bbe495
11 changed files with 130 additions and 62 deletions

View File

@ -1112,8 +1112,8 @@ _initialAccountSetting:
initialAccountSettingCompleted: "초기 설정을 모두 완료했어요!"
haveFun: "{name}와 함께 즐거운 시간 보내세요!"
ifYouNeedLearnMore: "{name}(CherryPick)의 사용 방법에 대해 자세히 알아보려면 {link}를 참고해 주세요."
skipAreYouSure: "초기 설정을 건너뛸까요?"
laterAreYouSure: "초기 설정을 나중에 다시 진행할까요?"
skipAreYouSure: "초기 설정을 중단하시겠어요?"
laterAreYouSure: "초기 설정을 나중에 진행할까요?"
_serverRules:
description: "회원 가입 이전에 간단하게 표시할 서버 규칙이에요. 이용 약관의 요약으로 구성하는 것을 추천해요."
_accountMigration:

View File

@ -1,7 +1,7 @@
---
_lang_: "Norsk Bokmål"
headlineMisskey: "Et nettverk forbundet med notes"
introMisskey: "Velkommen! Misskey er en desentralisert mikrobloggtjeneste med åpen kildekode.\nOpprett \"notes\" for å dele tankene dine med alle rundt deg. 📡\nMed \"reaksjoner\" kan du også raskt gi uttrykk for hva du synes om alles notes. 👍\nLa oss utforske en ny verden! 🚀"
headlineMisskey: "Et nettverk forbundet med Notes"
introMisskey: "Velkommen! Misskey er en desentralisert mikrobloggtjeneste med åpen kildekode.\nOpprett \"Notes\" for å dele tankene dine med alle rundt deg. 📡\nMed \"reaksjoner\" kan du også raskt gi uttrykk for hva du synes om alles Notes. 👍\nLa oss utforske en ny verden! 🚀"
monthAndDay: "{day}-{month}"
search: "Søk"
notifications: "Varsler"
@ -15,7 +15,7 @@ cancel: "Avbryt"
noThankYou: "Ikke nå"
enterUsername: "Skriv inn brukernavn"
renotedBy: "Renotes av {user}"
noNotes: "Ingen notes"
noNotes: "Ingen Notes"
noNotifications: "Ingen varsler"
instance: "Server"
settings: "Innstillinger"
@ -46,7 +46,7 @@ copyContent: "Kopier innhold"
copyLink: "Kopier lenke"
delete: "Slett"
deleteAndEdit: "Slett og rediger"
deleteAndEditConfirm: "Er du sikker på at du vil slette denne noten og redigere den? Du vil miste alle reaksjoner, renotes og svar på den."
deleteAndEditConfirm: "Er du sikker på at du vil slette denne Noten og redigere den? Du vil miste alle reaksjoner, Renotes og svar på den."
addToList: "Legg til i liste"
sendMessage: "Send en melding"
copyRSS: "Kopier RSS"
@ -90,9 +90,9 @@ enterEmoji: "Skriv inn en emoji"
renote: "Renote"
renoted: "Renotet."
cantRenote: "Dette innlegget kan ikke renotes."
cantReRenote: "En renote kan ikke renotes."
cantReRenote: "En Renote kan ikke renotes."
quote: "Sitat"
pinnedNote: "Festet note"
pinnedNote: "Festet Note"
pinned: "Fest til profil"
you: "Du"
clickToShow: "Klikk for å vise"
@ -101,13 +101,13 @@ reaction: "Reaksjon"
reactions: "Reaksjoner"
reactionSetting: "Reaksjoner som vises i reaksjonsvelgeren"
reactionSettingDescription2: "Dra for å endre rekkefølgen, klikk for å slette, trykk \"+\" for å legge til."
rememberNoteVisibility: "Husk innstillingene for synlighet av notes"
rememberNoteVisibility: "Husk innstillingene for synlighet av Notes"
attachCancel: "Fjern vedlegg"
enterFileName: "Skriv inn filnavn"
mute: "Skjul"
unmute: "Vis"
renoteMute: "Skjul renotes"
renoteUnmute: "Vis renotes"
renoteMute: "Skjul Renotes"
renoteUnmute: "Vis Renotes"
block: "Blokker"
unblock: "Opphev blokkering"
suspend: "Suspender"
@ -163,7 +163,7 @@ mutedUsers: "Skjulte brukere"
blockedUsers: "Blokkerte brukere"
noUsers: "Det er ingen brukere"
editProfile: "Rediger profil"
noteDeleteConfirm: "Er du sikker på at du vil slette denne noten?"
noteDeleteConfirm: "Er du sikker på at du vil slette denne Noten?"
pinLimitExceeded: "Du kan ikke feste flere."
intro: "Installasjonen av Misskey er ferdig! Vennligst opprett en administratorkonto."
done: "Ferdig"
@ -195,7 +195,7 @@ termsOfService: "Vilkår for bruk"
home: "Hjem"
activity: "Aktivitet"
images: "Bilder"
image: "Bilder"
image: "Bilde"
birthday: "Bursdag"
yearsOld: "{age} år gammel"
light: "Lys"
@ -226,7 +226,7 @@ instanceName: "Servernavn"
instanceDescription: "Serverbeskrivelse"
thisYear: "År"
thisMonth: "Måned"
today: "Dag"
today: "I dag"
dayX: "{day}"
monthX: "{month}"
yearX: "{year}"
@ -242,13 +242,14 @@ basicInfo: "Grunnleggende informasjon"
pinnedUsers: "Festede brukrere"
pinnedUsersDescription: "Liste over brukernavn atskilt med linjeskift som skal festes i \"Utforsk\" fanen."
pinnedPages: "Festede sider"
pinnedNotes: "Festet note"
pinnedNotes: "Festet Note"
hcaptcha: "hCaptcha"
enableHcaptcha: "Aktiver hCaptcha"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Aktiver reCAPTCHA"
turnstile: "Turnstile"
enableTurnstile: "Aktiver Turnstile"
antennas: "Antenner"
name: "Navn"
popularUsers: "Populære brukere"
exploreUsersCount: "Det finnes {count} brukere"
@ -286,7 +287,7 @@ objectStorageRegion: "Region"
objectStorageUseSSL: "Bruk SSL"
objectStorageUseProxy: "Bruk Proxy"
deleteAll: "Slett alt"
newNoteRecived: "Det er nye notes"
newNoteRecived: "Det er nye Notes"
listen: "Lytt"
none: "Ingen"
volume: "Volum"
@ -339,6 +340,7 @@ developer: "Utvikler"
makeExplorable: "Gjør konto synlig i \"Utforsk\""
makeExplorableDescription: "Hvis du slår av dette, vises ikke kontoen din i \"Utforsk\" delen."
left: "Venstre"
nNotes: "{n} Notes"
saveAs: "Lagre som"
value: "Verdi"
deleteConfirm: "Vil du slette?"
@ -424,6 +426,26 @@ _initialAccountSetting:
theseSettingsCanEditLater: "Du kan endre disse innstillingene senere."
_achievements:
_types:
_notes10:
title: "Noen Notes"
_notes100:
title: "Mange Notes"
_notes500:
title: "Dekket i Notes"
_notes1000:
title: "Et fjell av Notes"
_notes5000:
title: "Overfylte Notes"
_notes10000:
title: "Super Notes"
_notes20000:
title: "Trenger... mer... Notes..."
_notes30000:
title: "Notes Notes Notes!"
_notes40000:
title: "Note fabrikk"
_notes50000:
title: "Planet av Notes"
_notes100000:
flavor: "Du har jammen mye å si."
_noteFavorited1:
@ -650,6 +672,7 @@ _deck:
_columns:
notifications: "Varsler"
tl: "Tidslinje"
antenna: "Antenner"
list: "Lister"
channel: "Kanaler"
direct: "Direkte"

View File

@ -52,6 +52,8 @@ addToList: "添加至列表"
sendMessage: "发送"
copyRSS: "复制RSS"
copyUsername: "复制用户名"
copyUserId: "复制用户ID"
copyNoteId: "复制帖子ID"
searchUser: "搜索用户"
reply: "回复"
loadMore: "查看更多"
@ -802,6 +804,7 @@ noMaintainerInformationWarning: "管理人员信息未设置。"
noBotProtectionWarning: "Bot保护未设置。"
configure: "设置"
postToGallery: "发送到图库"
postToHashtag: "投稿到这个标签"
gallery: "图库"
recentPosts: "最新发布"
popularPosts: "热门投稿"
@ -835,6 +838,7 @@ translatedFrom: "从 {x} 翻译"
accountDeletionInProgress: "正在删除账户"
usernameInfo: "在服务器上唯一标识您的帐户的名称。您可以使用字母 (a ~ z, A ~ Z)、数字 (0 ~ 9) 和下划线 (_)。用户名以后不能更改。"
aiChanMode: "小蓝模式"
devMode: "开发者模式"
keepCw: "回复时维持隐藏内容"
pubSub: "Pub/Sub账户"
lastCommunication: "最近通信"
@ -844,6 +848,8 @@ breakFollow: "移除关注者"
breakFollowConfirm: "你想取消关注吗?"
itsOn: "已开启"
itsOff: "已关闭"
on: "开启"
off: "关闭"
emailRequiredForSignup: "注册账户需要电子邮件地址"
unread: "未读"
filter: "筛选"
@ -1000,6 +1006,8 @@ cannotBeChangedLater: "之后不能再更改。"
reactionAcceptance: "接受表情回应"
likeOnly: "仅点赞"
likeOnlyForRemote: "远程仅点赞"
nonSensitiveOnly: "仅限非敏感内容"
nonSensitiveOnlyForLocalLikeOnlyForRemote: "仅限非敏感内容(远程仅点赞)"
rolesAssignedToMe: "指派给自己的角色"
resetPasswordConfirm: "确定重置密码?"
sensitiveWords: "敏感词"
@ -1057,6 +1065,15 @@ preventAiLearning: "拒绝接受生成式AI的学习"
preventAiLearningDescription: "要求文章生成AI或图像生成AI不能够以发布的帖子和图像等内容作为学习对象。这是通过在HTML响应中包含noai标志来实现的这不能完全阻止AI学习你的发布内容并不是所有AI都会遵守这类请求。"
options: "选项"
specifyUser: "用户指定"
failedToPreviewUrl: "无法预览"
update: "更新"
rolesThatCanBeUsedThisEmojiAsReaction: "可以使用表情作为回应的角色"
rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "在没有指定角色的情况下,任何人都可以使用表情作为回应。"
rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "角色必须是公开的。"
cancelReactionConfirm: "要取消回应吗?"
changeReactionConfirm: "要更改回应吗?"
later: "一会再说"
goToMisskey: "去往Misskey"
_initialAccountSetting:
accountCreated: "账户创建完成了!"
letsStartAccountSetup: "来进行帐户的初始设置吧。"
@ -1071,6 +1088,7 @@ _initialAccountSetting:
haveFun: "希望{name}在这里玩得开心!"
ifYouNeedLearnMore: "关于{name}(Misskey)的使用方法,详见{link}。"
skipAreYouSure: "要跳过初始设置吗?"
laterAreYouSure: "要稍后再进行初始设定吗?"
_serverRules:
description: "在新用户注册前显示服务器的简单规则。推荐显示服务条款的主要内容。"
_accountMigration:

View File

@ -34,7 +34,7 @@
</template>
<script lang="ts" setup>
import { onMounted, ref, shallowRef, watch } from 'vue';
import { onMounted, onUnmounted, ref, shallowRef, watch } from 'vue';
import { defaultStore } from '@/store';
import { i18n } from '@/i18n';
@ -83,13 +83,19 @@ function afterLeave(el) {
const calcOmit = () => {
if (omitted.value || ignoreOmit.value || props.maxHeight == null) return;
if (!contentEl.value) return;
const height = contentEl.value.offsetHeight;
omitted.value = height > props.maxHeight;
};
const omitObserver = new ResizeObserver((entries, observer) => {
calcOmit();
});
onMounted(() => {
watch(showBody, v => {
const headerHeight = props.showHeader ? headerEl.value.offsetHeight : 0;
if (!rootEl.value) return;
const headerHeight = props.showHeader ? headerEl.value?.offsetHeight ?? 0 : 0;
rootEl.value.style.minHeight = `${headerHeight}px`;
if (v) {
rootEl.value.style.flexBasis = 'auto';
@ -100,13 +106,15 @@ onMounted(() => {
immediate: true,
});
rootEl.value.style.setProperty('--maxHeight', props.maxHeight + 'px');
if (rootEl.value) rootEl.value.style.setProperty('--maxHeight', props.maxHeight + 'px');
calcOmit();
new ResizeObserver((entries, observer) => {
calcOmit();
}).observe(contentEl.value);
if (contentEl.value) omitObserver.observe(contentEl.value);
});
onUnmounted(() => {
omitObserver.disconnect();
});
</script>

View File

@ -87,6 +87,7 @@ function showMenu(ev: MouseEvent) {
}, ...(iAmModerator ? [{
text: i18n.ts.markAsSensitive,
icon: 'ti ti-eye-exclamation',
danger: true,
action: () => {
os.apiWithDialog('drive/files/update', { fileId: props.image.id, isSensitive: true });
},

View File

@ -17,7 +17,7 @@
</template>
<script lang="ts" setup>
import { nextTick, onMounted, watch, provide } from 'vue';
import { nextTick, onMounted, watch, provide, onUnmounted } from 'vue';
import * as os from '@/os';
import { isTouchUsing } from '@/scripts/touch';
import { defaultStore } from '@/store';
@ -38,7 +38,7 @@ type ModalTypes = 'popup' | 'dialog' | 'drawer';
const props = withDefaults(defineProps<{
manualShowing?: boolean | null;
anchor?: { x: string; y: string; };
src?: HTMLElement;
src?: HTMLElement | null;
preferType?: ModalTypes | 'auto';
zPriority?: 'low' | 'middle' | 'high';
noOverlap?: boolean;
@ -264,6 +264,10 @@ const onOpened = () => {
}, { passive: true });
};
const alignObserver = new ResizeObserver((entries, observer) => {
align();
});
onMounted(() => {
watch(() => props.src, async () => {
if (props.src) {
@ -278,12 +282,14 @@ onMounted(() => {
}, { immediate: true });
nextTick(() => {
new ResizeObserver((entries, observer) => {
align();
}).observe(content!);
alignObserver.observe(content!);
});
});
onUnmounted(() => {
alignObserver.disconnect();
});
defineExpose({
close,
});

View File

@ -8,7 +8,7 @@
</template>
<script lang="ts" setup>
import { onMounted } from 'vue';
import { onMounted, onUnmounted } from 'vue';
import { i18n } from '@/i18n';
const props = withDefaults(defineProps<{
@ -21,16 +21,22 @@ let content = $shallowRef<HTMLElement>();
let omitted = $ref(false);
let ignoreOmit = $ref(false);
onMounted(() => {
const calcOmit = () => {
if (omitted || ignoreOmit) return;
omitted = content.offsetHeight > props.maxHeight;
};
const calcOmit = () => {
if (omitted || ignoreOmit) return;
omitted = content.offsetHeight > props.maxHeight;
};
const omitObserver = new ResizeObserver((entries, observer) => {
calcOmit();
new ResizeObserver((entries, observer) => {
calcOmit();
}).observe(content);
});
onMounted(() => {
calcOmit();
omitObserver.observe(content);
});
onUnmounted(() => {
omitObserver.disconnect();
});
</script>

View File

@ -1,6 +1,6 @@
<template>
<div ref="rootEl">
<div :class="[$style.root, {[$style.reduceAnimation]: !defaultStore.state.animation, [$style.showEl]: showEl && isMobile && isAllowHideHeader && mainRouter.currentRoute.value.name !== 'index', [$style.showElTl]: showEl && isMobile && isAllowHideHeader && mainRouter.currentRoute.value.name === 'index' }]" ref="headerEl">
<div ref="headerEl" :class="[$style.root, {[$style.reduceAnimation]: !defaultStore.state.animation, [$style.showEl]: showEl && isMobile && isAllowHideHeader && mainRouter.currentRoute.value.name !== 'index', [$style.showElTl]: showEl && isMobile && isAllowHideHeader && mainRouter.currentRoute.value.name === 'index' }]">
<slot name="header"></slot>
</div>
<div ref="bodyEl" :data-sticky-container-header-height="headerHeight">
@ -14,14 +14,13 @@
<script lang="ts" setup>
import { onMounted, onUnmounted, provide, inject, Ref, ref, watch } from 'vue';
import { $$ } from 'vue/macros';
import { CURRENT_STICKY_BOTTOM, CURRENT_STICKY_TOP } from '@/const';
import { miLocalStorage } from '@/local-storage';
import { deviceKind } from '@/scripts/device-kind';
import { mainRouter } from '@/router';
import { defaultStore } from '@/store';
import { eventBus } from '@/scripts/cherrypick/eventBus';
const isFriendly = ref(miLocalStorage.getItem('ui') === 'friendly');
const isAllowHideHeader = ref(mainRouter.currentRoute.value.name === 'index' || mainRouter.currentRoute.value.name === 'explore' || mainRouter.currentRoute.value.name === 'my-notifications' || mainRouter.currentRoute.value.name === 'my-favorites');
const MOBILE_THRESHOLD = 500;
@ -104,6 +103,10 @@ onMounted(() => {
onUnmounted(() => {
observer.disconnect();
});
defineExpose({
rootEl: $$(rootEl),
});
</script>
<style lang="scss" module>

View File

@ -64,11 +64,7 @@
}
html {
touch-action: manipulation;
background-color: var(--bg);
background-attachment: fixed;
background-size: cover;
background-position: center;
color: var(--fg);
accent-color: var(--accent);
overflow: auto;
@ -202,6 +198,7 @@ html._themeChanging_ {
}
html, body {
touch-action: manipulation;
margin: 0;
padding: 0;
scroll-behavior: smooth;

View File

@ -2,14 +2,10 @@
<div :class="[$style.root, { [$style.narrow]: isMobile }]">
<XSidebar v-if="!isMobile" :class="$style.sidebar"/>
<MkStickyContainer :class="[$style.contents, { [$style.narrow]: isMobile }]">
<MkStickyContainer ref="contents" :class="[$style.contents, { [$style.narrow]: isMobile }]" style="container-type: inline-size;" @contextmenu.stop="onContextmenu">
<template #header><XStatusBars :class="$style.statusbars"/></template>
<main style="min-width: 0;" @contextmenu.stop="onContextmenu">
<div :class="$style.content" style="container-type: inline-size;">
<RouterView/>
</div>
<div v-if="!(mainRouter.currentRoute.value.name === 'messaging-room' || mainRouter.currentRoute.value.name === 'messaging-room-group')" :class="$style.spacer"></div>
</main>
<RouterView/>
<div v-if="!(mainRouter.currentRoute.value.name === 'messaging-room' || mainRouter.currentRoute.value.name === 'messaging-room-group')" :class="$style.spacer"></div>
</MkStickyContainer>
<div v-if="isDesktop && mainRouter.currentRoute.value.name !== 'my-notifications'" :class="$style.notificationWidgets">
@ -94,13 +90,14 @@
</template>
<script lang="ts" setup>
import { defineAsyncComponent, provide, onMounted, onBeforeUnmount, computed, ref, watch, ComputedRef, inject, Ref } from 'vue';
import { defineAsyncComponent, provide, onMounted, onBeforeUnmount, computed, ref, watch, ComputedRef, shallowRef, Ref } from 'vue';
import XCommon from './_common_/common.vue';
import type MkStickyContainer from '@/components/global/MkStickyContainer.vue';
import { instanceName } from '@/config';
import XDrawerMenu from '@/ui/friendly/navbar-for-mobile.vue';
import * as os from '@/os';
import { defaultStore } from '@/store';
// import { navbarItemDef } from '@/navbar';
import { navbarItemDef } from '@/navbar';
import { i18n } from '@/i18n';
import { $i, openAccountMenu as openAccountMenu_ } from '@/account';
import { mainRouter } from '@/router';
@ -110,6 +107,7 @@ import { miLocalStorage } from '@/local-storage';
import { eventBus } from '@/scripts/cherrypick/eventBus';
import { CURRENT_STICKY_BOTTOM } from '@/const';
import CPAvatar from '@/components/global/CPAvatar-Friendly.vue';
const XWidgets = defineAsyncComponent(() => import('./universal.widgets.vue'));
const XNotifications = defineAsyncComponent(() => import('@/pages/notifications.vue'));
const XSidebar = defineAsyncComponent(() => import('@/ui/friendly/navbar.vue'));
@ -137,6 +135,7 @@ let longTouchNavHome = $ref(false);
let pageMetadata = $ref<null | ComputedRef<PageMetadata>>();
const widgetsShowing = $ref(false);
const navFooter = $shallowRef<HTMLElement>();
const contents = shallowRef<InstanceType<typeof MkStickyContainer>>();
provide('router', mainRouter);
provideMetadataReceiver((info) => {
@ -239,7 +238,10 @@ const onContextmenu = (ev) => {
};
function top() {
// TODO
contents.value.rootEl.scrollTo({
top: 0,
behavior: 'smooth',
});
}
function queueUpdated(q: number): void {
@ -474,6 +476,7 @@ $float-button-size: 65px;
top: 0;
right: 0;
z-index: 1001;
width: 330px;
height: 100dvh;
padding: var(--margin) var(--margin) calc(var(--margin) + env(safe-area-inset-bottom, 0px)) !important;
box-sizing: border-box;

View File

@ -2,14 +2,10 @@
<div :class="$style.root">
<XSidebar v-if="!isMobile" :class="$style.sidebar"/>
<MkStickyContainer :class="$style.contents">
<MkStickyContainer ref="contents" :class="$style.contents" style="container-type: inline-size;" @contextmenu.stop="onContextmenu">
<template #header><XStatusBars :class="$style.statusbars"/></template>
<main style="min-width: 0;" @contextmenu.stop="onContextmenu">
<div :class="$style.content" style="container-type: inline-size;">
<RouterView/>
</div>
<div :class="$style.spacer"></div>
</main>
<RouterView/>
<div :class="$style.spacer"></div>
</MkStickyContainer>
<div v-if="isDesktop" :class="$style.widgets">
@ -84,8 +80,9 @@
</template>
<script lang="ts" setup>
import { defineAsyncComponent, provide, onMounted, computed, ref, ComputedRef, watch, inject, Ref } from 'vue';
import { defineAsyncComponent, provide, onMounted, computed, ref, ComputedRef, watch, shallowRef, Ref } from 'vue';
import XCommon from './_common_/common.vue';
import type MkStickyContainer from '@/components/global/MkStickyContainer.vue';
import { instanceName } from '@/config';
import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue';
import * as os from '@/os';
@ -98,6 +95,7 @@ import { PageMetadata, provideMetadataReceiver } from '@/scripts/page-metadata';
import { deviceKind } from '@/scripts/device-kind';
import { miLocalStorage } from '@/local-storage';
import { CURRENT_STICKY_BOTTOM } from '@/const';
const XWidgets = defineAsyncComponent(() => import('./universal.widgets.vue'));
const XSidebar = defineAsyncComponent(() => import('@/ui/_common_/navbar.vue'));
const XStatusBars = defineAsyncComponent(() => import('@/ui/_common_/statusbars.vue'));
@ -115,6 +113,7 @@ window.addEventListener('resize', () => {
let pageMetadata = $ref<null | ComputedRef<PageMetadata>>();
const widgetsShowing = $ref(false);
const navFooter = $shallowRef<HTMLElement>();
const contents = shallowRef<InstanceType<typeof MkStickyContainer>>();
provide('router', mainRouter);
provideMetadataReceiver((info) => {
@ -194,7 +193,10 @@ const onContextmenu = (ev) => {
};
function top() {
// TODO
contents.value.rootEl.scrollTo({
top: 0,
behavior: 'smooth',
});
}
let navFooterHeight = $ref(0);
@ -319,6 +321,7 @@ $widgets-hide-threshold: 1090px;
top: 0;
right: 0;
z-index: 1001;
width: 310px;
height: 100dvh;
padding: var(--margin) var(--margin) calc(var(--margin) + env(safe-area-inset-bottom, 0px)) !important;
box-sizing: border-box;