Merge branch 'develop' of https://codeberg.org/calckey/calckey into keyboard-accessability

This commit is contained in:
Freeplay 2023-04-29 09:48:10 -04:00
commit 1ee8b7285e
8 changed files with 191 additions and 84 deletions

43
locales/fi.yml Normal file
View File

@ -0,0 +1,43 @@
username: Käyttäjänimi
fetchingAsApObject: Hae Fedeversestä
gotIt: Selvä!
cancel: Peruuta
enterUsername: Anna käyttäjänimi
renotedBy: Buustannut {käyttäjä}
noNotes: Ei lähetyksiä
noNotifications: Ei ilmoituksia
instance: Instanssi
settings: Asetukset
basicSettings: Perusasetukset
otherSettings: Muut asetukset
openInWindow: Avaa ikkunaan
profile: Profiili
timeline: Aikajana
noAccountDescription: Käyttäjä ei ole vielä kirjoittanut kuvaustaan vielä.
login: Kirjaudu sisään
loggingIn: Kirjautuu sisään
logout: Kirjaudu ulos
uploading: Tallentaa ylös...
save: Tallenna
favorites: Kirjanmerkit
unfavorite: Poista kirjanmerkeistä
favorited: Lisätty kirjanmerkkeihin.
alreadyFavorited: Lisätty jo kirjanmerkkeihin.
cantFavorite: Ei voitu lisätä kirjanmerkkeihin.
pin: Kiinnitä profiiliin
unpin: Irroita profiilista
delete: Poista
forgotPassword: Unohtunut salasana
search: Etsi
notifications: Ilmoitukset
password: Salasana
ok: OK
noThankYou: Ei kiitos
signup: Rekisteröidy
users: Käyttäjät
addUser: Lisää käyttäjä
addInstance: Lisää instanssi
favorite: Lisää kirjanmerkkeihin
copyContent: Kopioi sisältö
deleteAndEdit: Poista ja muokkaa
copyLink: Kopioi linkki

View File

@ -77,5 +77,41 @@ defineExpose({
background: var(--cwFg) !important; background: var(--cwFg) !important;
color: var(--cwBg) !important; color: var(--cwBg) !important;
} }
&.fade {
display: block;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
> span {
display: inline-block;
background: var(--panel);
padding: 0.4em 1em;
font-size: 0.8em;
border-radius: 999px;
box-shadow: 0 2px 6px rgb(0 0 0 / 20%);
}
&:hover {
> span {
background: var(--panelHighlight);
}
}
}
&.showLess {
width: 100%;
margin-top: 1em;
position: sticky;
bottom: var(--stickyBottom);
> span {
display: inline-block;
background: var(--panel);
padding: 6px 10px;
font-size: 0.8em;
border-radius: 999px;
box-shadow: 0 0 7px 7px var(--bg);
}
}
} }
</style> </style>

View File

@ -89,7 +89,7 @@
/> />
</div> </div>
</div> </div>
<div class="tail"> <div class="tail" :class="{ collapsed }">
<header> <header>
<span v-if="notification.type === 'pollEnded'">{{ <span v-if="notification.type === 'pollEnded'">{{
i18n.ts._notification.pollEnded i18n.ts._notification.pollEnded
@ -112,11 +112,11 @@
v-if="notification.type === 'reaction'" v-if="notification.type === 'reaction'"
class="text" class="text"
:to="notePage(notification.note)" :to="notePage(notification.note)"
:title="getNoteSummary(notification.note)" :title="summary"
> >
<i class="ph-quotes ph-fill ph-lg"></i> <i class="ph-quotes ph-fill ph-lg"></i>
<Mfm <Mfm
:text="getNoteSummary(notification.note)" :text="summary"
:plain="true" :plain="true"
:nowrap="!full" :nowrap="!full"
:custom-emojis="notification.note.emojis" :custom-emojis="notification.note.emojis"
@ -142,10 +142,10 @@
v-if="notification.type === 'reply'" v-if="notification.type === 'reply'"
class="text" class="text"
:to="notePage(notification.note)" :to="notePage(notification.note)"
:title="getNoteSummary(notification.note)" :title="summary"
> >
<Mfm <Mfm
:text="getNoteSummary(notification.note)" :text="summary"
:plain="true" :plain="true"
:nowrap="!full" :nowrap="!full"
:custom-emojis="notification.note.emojis" :custom-emojis="notification.note.emojis"
@ -155,10 +155,10 @@
v-if="notification.type === 'mention'" v-if="notification.type === 'mention'"
class="text" class="text"
:to="notePage(notification.note)" :to="notePage(notification.note)"
:title="getNoteSummary(notification.note)" :title="summary"
> >
<Mfm <Mfm
:text="getNoteSummary(notification.note)" :text="summary"
:plain="true" :plain="true"
:nowrap="!full" :nowrap="!full"
:custom-emojis="notification.note.emojis" :custom-emojis="notification.note.emojis"
@ -168,10 +168,10 @@
v-if="notification.type === 'quote'" v-if="notification.type === 'quote'"
class="text" class="text"
:to="notePage(notification.note)" :to="notePage(notification.note)"
:title="getNoteSummary(notification.note)" :title="summary"
> >
<Mfm <Mfm
:text="getNoteSummary(notification.note)" :text="summary"
:plain="true" :plain="true"
:nowrap="!full" :nowrap="!full"
:custom-emojis="notification.note.emojis" :custom-emojis="notification.note.emojis"
@ -181,11 +181,11 @@
v-if="notification.type === 'pollVote'" v-if="notification.type === 'pollVote'"
class="text" class="text"
:to="notePage(notification.note)" :to="notePage(notification.note)"
:title="getNoteSummary(notification.note)" :title="summary"
> >
<i class="ph-quotes ph-fill ph-lg"></i> <i class="ph-quotes ph-fill ph-lg"></i>
<Mfm <Mfm
:text="getNoteSummary(notification.note)" :text="summary"
:plain="true" :plain="true"
:nowrap="!full" :nowrap="!full"
:custom-emojis="notification.note.emojis" :custom-emojis="notification.note.emojis"
@ -196,11 +196,11 @@
v-if="notification.type === 'pollEnded'" v-if="notification.type === 'pollEnded'"
class="text" class="text"
:to="notePage(notification.note)" :to="notePage(notification.note)"
:title="getNoteSummary(notification.note)" :title="summary"
> >
<i class="ph-quotes ph-fill ph-lg"></i> <i class="ph-quotes ph-fill ph-lg"></i>
<Mfm <Mfm
:text="getNoteSummary(notification.note)" :text="summary"
:plain="true" :plain="true"
:nowrap="!full" :nowrap="!full"
:custom-emojis="notification.note.emojis" :custom-emojis="notification.note.emojis"
@ -264,6 +264,7 @@
<span v-if="notification.type === 'app'" class="text"> <span v-if="notification.type === 'app'" class="text">
<Mfm :text="notification.body" :nowrap="!full" /> <Mfm :text="notification.body" :nowrap="!full" />
</span> </span>
<xShowMoreButton v-if="isLong" v-model="collapsed"></xShowMoreButton>
</div> </div>
</div> </div>
</template> </template>
@ -274,6 +275,7 @@ import * as misskey from "calckey-js";
import XReactionIcon from "@/components/MkReactionIcon.vue"; import XReactionIcon from "@/components/MkReactionIcon.vue";
import MkFollowButton from "@/components/MkFollowButton.vue"; import MkFollowButton from "@/components/MkFollowButton.vue";
import XReactionTooltip from "@/components/MkReactionTooltip.vue"; import XReactionTooltip from "@/components/MkReactionTooltip.vue";
import XShowMoreButton from "./MkShowMoreButton.vue";
import { getNoteSummary } from "@/scripts/get-note-summary"; import { getNoteSummary } from "@/scripts/get-note-summary";
import { notePage } from "@/filters/note"; import { notePage } from "@/filters/note";
import { userPage } from "@/filters/user"; import { userPage } from "@/filters/user";
@ -299,12 +301,19 @@ const props = withDefaults(
const elRef = ref<HTMLElement>(null); const elRef = ref<HTMLElement>(null);
const reactionRef = ref(null); const reactionRef = ref(null);
const summary = getNoteSummary(props.notification.note);
const showEmojiReactions = const showEmojiReactions =
defaultStore.state.enableEmojiReactions || defaultStore.state.enableEmojiReactions ||
defaultStore.state.showEmojisInReactionNotifications; defaultStore.state.showEmojisInReactionNotifications;
const defaultReaction = ["⭐", "👍", "❤️"].includes(instance.defaultReaction) const defaultReaction = ["⭐", "👍", "❤️"].includes(instance.defaultReaction)
? instance.defaultReaction ? instance.defaultReaction
: "⭐"; : "⭐";
const isLong = (summary.split("\n").length > 3 || summary.length > 200);
const collapsed = $ref(isLong);
let readObserver: IntersectionObserver | undefined; let readObserver: IntersectionObserver | undefined;
let connection; let connection;
@ -486,6 +495,7 @@ useTooltip(reactionRef, (showing) => {
} }
> .tail { > .tail {
position: relative;
flex: 1; flex: 1;
min-width: 0; min-width: 0;
@ -526,6 +536,17 @@ useTooltip(reactionRef, (showing) => {
margin-left: 4px; margin-left: 4px;
} }
} }
&.collapsed > .text {
display: block;
position: relative;
max-height: calc(4em + 50px);
overflow: hidden;
mask: linear-gradient(black calc(100% - 64px), transparent);
-webkit-mask: linear-gradient(
black calc(100% - 64px),
transparent
);
}
} }
} }
</style> </style>

View File

@ -55,7 +55,7 @@
:class="{ active: showPreview }" :class="{ active: showPreview }"
@click="showPreview = !showPreview" @click="showPreview = !showPreview"
> >
<i class="ph-file-code ph-bold ph-lg"></i> <i class="ph-binoculars ph-bold ph-lg"></i>
</button> </button>
<button <button
class="submit _buttonGradate" class="submit _buttonGradate"

View File

@ -154,22 +154,22 @@ export default defineComponent({
? i18n.ts.unmarkAsSensitive ? i18n.ts.unmarkAsSensitive
: i18n.ts.markAsSensitive, : i18n.ts.markAsSensitive,
icon: file.isSensitive icon: file.isSensitive
? "ph-eye-slash ph-bold ph-lg" ? "ph-eye ph-bold ph-lg"
: "ph-eye ph-bold ph-lg", : "ph-eye-slash ph-bold ph-lg",
action: () => { action: () => {
this.toggleSensitive(file); this.toggleSensitive(file);
}, },
}, },
{ {
text: i18n.ts.describeFile, text: i18n.ts.describeFile,
icon: "ph-cursor-text ph-bold ph-lg", icon: "ph-subtitles ph-bold ph-lg",
action: () => { action: () => {
this.describe(file); this.describe(file);
}, },
}, },
{ {
text: i18n.ts.attachCancel, text: i18n.ts.attachCancel,
icon: "ph-circle-wavy-warning ph-bold ph-lg", icon: "ph-x ph-bold ph-lg",
action: () => { action: () => {
this.detachMedia(file.id); this.detachMedia(file.id);
}, },

View File

@ -0,0 +1,68 @@
<template>
<button
v-if="modelValue"
class="fade _button"
@click.stop="toggle"
>
<span>{{ i18n.ts.showMore }}</span>
</button>
<button
v-if="!modelValue"
class="showLess _button"
@click.stop="toggle"
>
<span>{{ i18n.ts.showLess }}</span>
</button>
</template>
<script lang="ts" setup>
import { i18n } from "@/i18n";
const props = defineProps<{
modelValue: boolean;
}>();
const emit = defineEmits<{
(ev: "update:modelValue", v: boolean): void;
}>();
const toggle = () => {
emit("update:modelValue", !props.modelValue);
};
</script>
<style lang="scss" scoped>
.fade {
display: block;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
> span {
display: inline-block;
background: var(--panel);
padding: 0.4em 1em;
font-size: 0.8em;
border-radius: 999px;
box-shadow: 0 2px 6px rgb(0 0 0 / 20%);
}
&:hover {
> span {
background: var(--panelHighlight);
}
}
}
.showLess {
width: 100%;
margin-top: 1em;
position: sticky;
bottom: var(--stickyBottom);
> span {
display: inline-block;
background: var(--panel);
padding: 6px 10px;
font-size: 0.8em;
border-radius: 999px;
box-shadow: 0 0 7px 7px var(--bg);
}
}
</style>

View File

@ -106,20 +106,7 @@
v-on:focus="cwButton?.focus()" v-on:focus="cwButton?.focus()"
></div> ></div>
</div> </div>
<button <XShowMoreButton v-if="isLong" v-model="collapsed"></XShowMoreButton>
v-if="isLong && collapsed"
class="fade _button"
@click.stop="collapsed = false"
>
<span>{{ i18n.ts.showMore }}</span>
</button>
<button
v-if="isLong && !collapsed"
class="showLess _button"
@click.stop="collapsed = true"
>
<span>{{ i18n.ts.showLess }}</span>
</button>
<XCwButton v-if="note.cw && showContent" v-model="showContent" :note="note" /> <XCwButton v-if="note.cw && showContent" v-model="showContent" :note="note" />
</div> </div>
</div> </div>
@ -133,6 +120,7 @@ import XNoteSimple from "@/components/MkNoteSimple.vue";
import XMediaList from "@/components/MkMediaList.vue"; import XMediaList from "@/components/MkMediaList.vue";
import XPoll from "@/components/MkPoll.vue"; import XPoll from "@/components/MkPoll.vue";
import MkUrlPreview from "@/components/MkUrlPreview.vue"; import MkUrlPreview from "@/components/MkUrlPreview.vue";
import XShowMoreButton from "./MkShowMoreButton.vue";
import XCwButton from "@/components/MkCwButton.vue"; import XCwButton from "@/components/MkCwButton.vue";
import { extractUrlFromMfm } from "@/scripts/extract-url-from-mfm"; import { extractUrlFromMfm } from "@/scripts/extract-url-from-mfm";
import { i18n } from "@/i18n"; import { i18n } from "@/i18n";
@ -157,6 +145,7 @@ const isLong =
props.note.text != null && props.note.text != null &&
(props.note.text.split("\n").length > 9 || props.note.text.length > 500); (props.note.text.split("\n").length > 9 || props.note.text.length > 500);
const collapsed = $ref(props.note.cw == null && isLong); const collapsed = $ref(props.note.cw == null && isLong);
const urls = props.note.text const urls = props.note.text
? extractUrlFromMfm(mfm.parse(props.note.text)).slice(0, 5) ? extractUrlFromMfm(mfm.parse(props.note.text)).slice(0, 5)
: null; : null;
@ -285,44 +274,6 @@ function focusFooter(ev) {
top: 40px; top: 40px;
} }
} }
:deep(.fade) {
display: block;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
z-index: 2;
> span {
display: inline-block;
background: var(--panel);
padding: 0.4em 1em;
font-size: 0.8em;
border-radius: 999px;
box-shadow: 0 2px 6px rgb(0 0 0 / 20%);
}
&:hover, &:focus {
> span {
background: var(--panelHighlight);
}
}
}
}
:deep(.showLess) {
width: 100%;
margin-top: 1em;
position: sticky;
bottom: var(--stickyBottom);
> span {
display: inline-block;
background: var(--panel);
padding: 6px 10px;
font-size: 0.8em;
border-radius: 999px;
box-shadow: 0 0 7px 7px var(--bg);
}
} }
} }
} }

View File

@ -55,20 +55,7 @@
:custom-emojis="user.emojis" :custom-emojis="user.emojis"
/> />
</div> </div>
<button <XShowMoreButton v-if="isLong" v-model="collapsed"></XShowMoreButton>
v-if="isLong && collapsed"
class="fade _button"
@click.stop="collapsed = false"
>
<span>{{ i18n.ts.showMore }}</span>
</button>
<button
v-if="isLong && !collapsed"
class="showLess _button"
@click.stop="collapsed = true"
>
<span>{{ i18n.ts.showLess }}</span>
</button>
<div v-if="user.fields.length > 0" class="fields"> <div v-if="user.fields.length > 0" class="fields">
<dl <dl
v-for="(field, i) in user.fields" v-for="(field, i) in user.fields"
@ -128,6 +115,7 @@ import * as Acct from "calckey-js/built/acct";
import type * as misskey from "calckey-js"; import type * as misskey from "calckey-js";
import MkFollowButton from "@/components/MkFollowButton.vue"; import MkFollowButton from "@/components/MkFollowButton.vue";
import { userPage } from "@/filters/user"; import { userPage } from "@/filters/user";
import XShowMoreButton from "./MkShowMoreButton.vue";
import * as os from "@/os"; import * as os from "@/os";
import { $i } from "@/account"; import { $i } from "@/account";
import { i18n } from "@/i18n"; import { i18n } from "@/i18n";