feat (client): add private visibility

This commit is contained in:
naskya 2024-02-21 07:24:52 +09:00
parent f04bf9f78e
commit fa0e65cc1b
No known key found for this signature in database
GPG Key ID: 712D413B3A9FED5C
10 changed files with 75 additions and 9 deletions

View File

@ -6,6 +6,8 @@ Critical security updates are indicated by the :warning: icon.
- Add the ability to give regular (non-moderator) users permission to manage custom emojis
- Fix a bug that made impossible to update user profiles under some conditions
- Add "private" (only me) post visibility
- It's just a paraphrase of DMs without recipients
## :warning: v20240217-1

View File

@ -1172,12 +1172,14 @@ postSearch: "Post search on this server"
showBigPostButton: "Show a huge post button on the posting form"
emojiModPerm: "Custom emoji management permission"
emojiModPermDescription: "Add: Allow this user to add new custom emojis and to set tag/category/license to newly added custom emojis.\nAdd and Edit: \"Add\" Permission + Allow this user to edit the name/category/tag/license of the existing custom emojis.\nAllow All: \"Add and Edit\" Permission + Allow this user to delete existing custom emojis."
private: "Private"
privateDescription: "Make visible for you only"
_emojiModPerm:
unauthorized: "None"
add: "Add"
mod: "Add and Edit"
full: "Allow All"
_sensitiveMediaDetection:
description: "Reduces the effort of server moderation through automatically recognizing
NSFW media via Machine Learning. This will slightly increase the load on the server."

View File

@ -2026,3 +2026,5 @@ _emojiModPerm:
add: "追加"
mod: "追加と変更"
full: "全て許可"
private: "秘密"
privateDescription: "あなた以外には非公開"

View File

@ -1995,3 +1995,5 @@ languageForTranslation: 帖子翻译语言
vibrate: 播放振动
openServerInfo: 点击帖子上的服务器滚动条时显示服务器信息
clickToShowPatterns: 点击显示模块模式
private: "秘密"
privateDescription: "仅你可见"

View File

@ -2012,3 +2012,5 @@ moreUrlsDescription: "請以下列形式輸入欲釘選在左下角幫助選單
showPreviewByDefault: "自動開啟發文介面中的預覽顯示"
preventMisclick: "預防誤觸"
hideFollowButtons: "隱藏會誤觸的追隨按鈕"
private: "祕密"
privateDescription: "僅你可見"

View File

@ -50,6 +50,9 @@
<span v-if="visibility === 'specified'"
><i :class="icon('ph-envelope-simple-open')"></i
></span>
<span v-if="visibility === 'private'"
><i :class="icon('ph-eye-slash')"></i
></span>
</button>
<button
ref="languageButton"
@ -557,6 +560,8 @@ if (
}).then((users) => {
users.forEach(pushVisibleUser);
});
} else {
visibility.value = "private";
}
if (props.reply.userId !== $i.id) {
@ -1015,11 +1020,14 @@ async function post() {
cw: useCw.value ? cw.value || "" : undefined,
lang: language.value ? language.value : undefined,
localOnly: localOnly.value,
visibility: visibility.value,
visibility:
visibility.value === "private" ? "specified" : visibility.value,
visibleUserIds:
visibility.value === "specified"
? visibleUsers.value.map((u) => u.id)
: undefined,
visibility.value === "private"
? []
: visibility.value === "specified"
? visibleUsers.value.map((u) => u.id)
: undefined,
};
if (withHashtags.value && hashtags.value && hashtags.value.trim() !== "") {

View File

@ -11,10 +11,20 @@
:class="icon('ph-lock')"
></i>
<i
v-else-if="note.visibility === 'specified'"
v-else-if="
note.visibility === 'specified' &&
note.visibleUserIds != null &&
note.visibleUserIds.length > 0
"
ref="specified"
:class="icon('ph-envelope-simple-open')"
></i>
<i
v-else-if="note.visibility === 'specified'"
v-tooltip="i18n.ts._visibility.private"
ref="specified"
:class="icon('ph-eye-slash')"
></i>
</span>
<span v-if="note.localOnly" :class="$style.localOnly"
><i
@ -42,7 +52,11 @@ const props = defineProps<{
const specified = ref<HTMLElement>();
if (props.note.visibility === "specified") {
if (
props.note.visibility === "specified" &&
props.note.visibleUserIds != null &&
props.note.visibleUserIds.length > 0
) {
useTooltip(specified, async (showing) => {
const users = await os.api("users/show", {
userIds: props.note.visibleUserIds,

View File

@ -84,6 +84,25 @@
}}</span>
</div>
</button>
<button
key="private"
class="_button"
:class="[$style.item, { [$style.active]: v === 'private' }]"
data-index="5"
@click="choose('private')"
>
<div :class="$style.icon">
<i :class="icon('ph-eye-slash')"></i>
</div>
<div :class="$style.body">
<span :class="$style.itemTitle">{{
i18n.ts._visibility.private
}}</span>
<span :class="$style.itemDescription">{{
i18n.ts._visibility.privateDescription
}}</span>
</div>
</button>
<div :class="$style.divider"></div>
<button
key="localOnly"
@ -154,7 +173,9 @@ watch(localOnly, () => {
emit("changeLocalOnly", localOnly.value);
});
function choose(visibility: (typeof noteVisibilities)[number]): void {
function choose(
visibility: (typeof noteVisibilities)[number] | "private",
): void {
v.value = visibility;
emit("changeVisibility", visibility);
nextTick(() => {

View File

@ -113,6 +113,11 @@
#suffix
>{{ i18n.ts._visibility.specified }}</template
>
<template
v-else-if="defaultNoteVisibility === 'private'"
#suffix
>{{ i18n.ts._visibility.private }}</template
>
<FormSelect v-model="defaultNoteVisibility" class="_formBlock">
<option value="public">
@ -125,6 +130,9 @@
<option value="specified">
{{ i18n.ts._visibility.specified }}
</option>
<option value="private">
{{ i18n.ts._visibility.private }}
</option>
</FormSelect>
<FormSwitch v-model="defaultNoteLocalOnly" class="_formBlock">{{
i18n.ts._visibility.localOnly

View File

@ -122,7 +122,12 @@ export const defaultStore = markRaw(
},
visibility: {
where: "deviceAccount",
default: "public" as "public" | "home" | "followers" | "specified",
default: "public" as
| "public"
| "home"
| "followers"
| "specified"
| "private",
},
localOnly: {
where: "deviceAccount",