merge: Collapse user activity, files, and listenbrainz on mobile (resolves #747) (!718)

View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/718

Closes #747

Approved-by: Marie <github@yuugi.dev>
Approved-by: dakkar <dakkar@thenautilus.net>
This commit is contained in:
dakkar 2024-10-27 12:12:30 +00:00
commit 276b30bdc0
7 changed files with 82 additions and 81 deletions

View file

@ -254,7 +254,7 @@ function toPackedUserDetailedNotMe(user: MiUser, override?: Packed<'UserDetailed
isRenoteMuted: false, isRenoteMuted: false,
notify: 'none', notify: 'none',
withReplies: true, withReplies: true,
ListenBrainz: null, listenbrainz: null,
...override, ...override,
}; };
} }

View file

@ -300,7 +300,7 @@ export const packedUserDetailedNotMeOnlySchema = {
nullable: true, optional: false, nullable: true, optional: false,
example: '2018-03-12', example: '2018-03-12',
}, },
ListenBrainz: { listenbrainz: {
type: 'string', type: 'string',
nullable: true, nullable: true,
optional: false, optional: false,

View file

@ -136,13 +136,13 @@ SPDX-License-Identifier: AGPL-3.0-only
<MkInfo v-if="user.pinnedNotes.length === 0 && $i?.id === user.id">{{ i18n.ts.userPagePinTip }}</MkInfo> <MkInfo v-if="user.pinnedNotes.length === 0 && $i?.id === user.id">{{ i18n.ts.userPagePinTip }}</MkInfo>
<template v-if="narrow"> <template v-if="narrow">
<MkLazy> <MkLazy>
<XFiles :key="user.id" :user="user"/> <XFiles :key="user.id" :user="user" :collapsed="true"/>
</MkLazy> </MkLazy>
<MkLazy> <MkLazy>
<XActivity :key="user.id" :user="user"/> <XActivity :key="user.id" :user="user" :collapsed="true"/>
</MkLazy> </MkLazy>
<MkLazy> <MkLazy>
<XListenBrainz v-if="user.listenbrainz && listenbrainzdata" :key="user.id" :user="user"/> <XListenBrainz v-if="user.listenbrainz && listenbrainzdata" :key="user.id" :user="user" :collapsed="true"/>
</MkLazy> </MkLazy>
</template> </template>
<!-- <div v-if="!disableNotes"> <!-- <div v-if="!disableNotes">
@ -215,9 +215,9 @@ import { getStaticImageUrl } from '@/scripts/media-proxy.js';
import { infoImageUrl } from '@/instance.js'; import { infoImageUrl } from '@/instance.js';
const MkNote = defineAsyncComponent(() => const MkNote = defineAsyncComponent(() =>
(defaultStore.state.noteDesign === 'misskey') ? import('@/components/MkNote.vue') : defaultStore.state.noteDesign === 'sharkey'
(defaultStore.state.noteDesign === 'sharkey') ? import('@/components/SkNote.vue') : ? import('@/components/SkNote.vue')
null : import('@/components/MkNote.vue'),
); );
function calcAge(birthdate: string): number { function calcAge(birthdate: string): number {
@ -237,7 +237,7 @@ function calcAge(birthdate: string): number {
const XFiles = defineAsyncComponent(() => import('./index.files.vue')); const XFiles = defineAsyncComponent(() => import('./index.files.vue'));
const XActivity = defineAsyncComponent(() => import('./index.activity.vue')); const XActivity = defineAsyncComponent(() => import('./index.activity.vue'));
const XListenBrainz = defineAsyncComponent(() => import("./index.listenbrainz.vue")); const XListenBrainz = defineAsyncComponent(() => import('./index.listenbrainz.vue'));
//const XTimeline = defineAsyncComponent(() => import('./index.timeline.vue')); //const XTimeline = defineAsyncComponent(() => import('./index.timeline.vue'));
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
@ -269,7 +269,7 @@ if (props.user.listenbrainz) {
const response = await fetch(`https://api.listenbrainz.org/1/user/${props.user.listenbrainz}/playing-now`, { const response = await fetch(`https://api.listenbrainz.org/1/user/${props.user.listenbrainz}/playing-now`, {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json',
}, },
}); });
const data = await response.json(); const data = await response.json();
@ -286,11 +286,11 @@ const background = computed(() => {
if (props.user.backgroundUrl == null) return {}; if (props.user.backgroundUrl == null) return {};
if (defaultStore.state.disableShowingAnimatedImages) { if (defaultStore.state.disableShowingAnimatedImages) {
return { return {
'--backgroundImageStatic': `url('${getStaticImageUrl(props.user.backgroundUrl)}')` '--backgroundImageStatic': `url('${getStaticImageUrl(props.user.backgroundUrl)}')`,
}; };
} else { } else {
return { return {
'--backgroundImageStatic': `url('${props.user.backgroundUrl}')` '--backgroundImageStatic': `url('${props.user.backgroundUrl}')`,
}; };
} }
}); });
@ -303,7 +303,7 @@ const pagination = {
endpoint: 'users/featured-notes' as const, endpoint: 'users/featured-notes' as const,
limit: 10, limit: 10,
params: computed(() => ({ params: computed(() => ({
userId: props.user.id userId: props.user.id,
})), })),
}; };

View file

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
--> -->
<template> <template>
<MkContainer> <MkContainer :foldable="true" :expanded="!collapsed">
<template #icon><i class="ti ti-chart-line"></i></template> <template #icon><i class="ti ti-chart-line"></i></template>
<template #header>{{ i18n.ts.activity }}</template> <template #header>{{ i18n.ts.activity }}</template>
<template #func="{ buttonStyleClass }"> <template #func="{ buttonStyleClass }">
@ -30,8 +30,10 @@ import { i18n } from '@/i18n.js';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
user: Misskey.entities.User; user: Misskey.entities.User;
limit?: number; limit?: number;
collapsed?: boolean;
}>(), { }>(), {
limit: 50, limit: 50,
collapsed: false,
}); });
const chartSrc = ref('per-user-notes'); const chartSrc = ref('per-user-notes');

View file

@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
--> -->
<template> <template>
<MkContainer :max-height="300" :foldable="true"> <MkContainer :max-height="300" :foldable="true" :expanded="!collapsed">
<template #icon><i class="ti ti-photo"></i></template> <template #icon><i class="ti ti-photo"></i></template>
<template #header>{{ i18n.ts.files }}</template> <template #header>{{ i18n.ts.files }}</template>
<div :class="$style.root"> <div :class="$style.root">
@ -43,9 +43,12 @@ import ImgWithBlurhash from '@/components/MkImgWithBlurhash.vue';
import { defaultStore } from '@/store.js'; import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
const props = defineProps<{ const props = withDefaults(defineProps<{
user: Misskey.entities.UserDetailed; user: Misskey.entities.UserDetailed;
}>(); collapsed?: boolean;
}>(), {
collapsed: false,
});
const fetching = ref(true); const fetching = ref(true);
const files = ref<{ const files = ref<{

View file

@ -4,19 +4,18 @@ SPDX-License-Identifier: AGPL-3.0-only
--> -->
<template> <template>
<MkContainer :foldable="true"> <MkContainer :foldable="true" :expanded="!collapsed">
<template #header <template #header>
><i <i
class="ph-headphones ph-bold ph-lg" class="ph-headphones ph-bold ph-lg"
style="margin-right: 0.5em" style="margin-right: 0.5em"
></i ></i>Music
>Music</template </template>
>
<div style="padding: 8px"> <div style="padding: 8px">
<div class="flex"> <div class="flex">
<a :href="listenbrainz.musicbrainzurl"> <a :href="listenbrainz.musicbrainzurl">
<img class="image" :src="listenbrainz.img" :alt="listenbrainz.title" /> <img class="image" :src="listenbrainz.img" :alt="listenbrainz.title"/>
<div class="flex flex-col items-start"> <div class="flex flex-col items-start">
<p class="text-sm font-bold">Now Playing: {{ listenbrainz.title }}</p> <p class="text-sm font-bold">Now Playing: {{ listenbrainz.title }}</p>
<p class="text-xs font-medium">{{ listenbrainz.artist }}</p> <p class="text-xs font-medium">{{ listenbrainz.artist }}</p>
@ -29,19 +28,19 @@ SPDX-License-Identifier: AGPL-3.0-only
</a> </a>
</div> </div>
</div> </div>
</MkContainer> </MkContainer>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
/* eslint-disable no-mixed-spaces-and-tabs */ import * as misskey from 'misskey-js';
import {} from "vue"; import MkContainer from '@/components/MkContainer.vue';
import * as misskey from "misskey-js";
import MkContainer from "@/components/MkContainer.vue";
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
user: misskey.entities.User; user: misskey.entities.UserDetailed;
}>(), collapsed?: boolean;
{}, }>(), {
collapsed: false,
},
); );
const listenbrainz = { title: '', artist: '', lastlisten: '', img: '', musicbrainzurl: '', listenbrainzurl: '' }; const listenbrainz = { title: '', artist: '', lastlisten: '', img: '', musicbrainzurl: '', listenbrainzurl: '' };
if (props.user.listenbrainz) { if (props.user.listenbrainz) {
@ -49,7 +48,7 @@ if (props.user.listenbrainz) {
const response = await fetch(`https://api.listenbrainz.org/1/metadata/lookup/?artist_name=${artist}&recording_name=${title}`, { const response = await fetch(`https://api.listenbrainz.org/1/metadata/lookup/?artist_name=${artist}&recording_name=${title}`, {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json',
}, },
}); });
const data = await response.json(); const data = await response.json();
@ -66,7 +65,7 @@ if (props.user.listenbrainz) {
const response = await fetch(`https://api.listenbrainz.org/1/user/${props.user.listenbrainz}/playing-now`, { const response = await fetch(`https://api.listenbrainz.org/1/user/${props.user.listenbrainz}/playing-now`, {
method: 'GET', method: 'GET',
headers: { headers: {
'Content-Type': 'application/json' 'Content-Type': 'application/json',
}, },
}); });
const data = await response.json(); const data = await response.json();
@ -74,22 +73,20 @@ if (props.user.listenbrainz) {
const title: string = data.payload.listens[0].track_metadata.track_name; const title: string = data.payload.listens[0].track_metadata.track_name;
const artist: string = data.payload.listens[0].track_metadata.artist_name; const artist: string = data.payload.listens[0].track_metadata.artist_name;
const lastlisten: string = data.payload.listens[0].playing_now; const lastlisten: string = data.payload.listens[0].playing_now;
const img: string = 'https://coverartarchive.org/img/big_logo.svg'; const img = 'https://coverartarchive.org/img/big_logo.svg';
await getLMData(title, artist).then((data) => { await getLMData(title, artist).then((lmData) => {
if (!data) { if (!lmData) {
listenbrainz.title = title; listenbrainz.title = title;
listenbrainz.img = img; listenbrainz.img = img;
listenbrainz.artist = artist; listenbrainz.artist = artist;
listenbrainz.lastlisten = lastlisten; listenbrainz.lastlisten = lastlisten;
return;
} else { } else {
listenbrainz.title = data[0]; listenbrainz.title = lmData[0];
listenbrainz.img = data[2]; listenbrainz.img = lmData[2];
listenbrainz.artist = data[1]; listenbrainz.artist = lmData[1];
listenbrainz.lastlisten = lastlisten; listenbrainz.lastlisten = lastlisten;
listenbrainz.musicbrainzurl = data[3]; listenbrainz.musicbrainzurl = lmData[3];
listenbrainz.listenbrainzurl = data[4]; listenbrainz.listenbrainzurl = lmData[4];
return;
} }
}); });
} }
@ -119,8 +116,7 @@ if (props.user.listenbrainz) {
} }
.text-sm { .text-sm {
font-size: 0.875rem; font-size: 0.875rem;
margin: 0; margin: 0 0 0.3rem;
margin-bottom: 0.3rem;
} }
.font-bold { .font-bold {
font-weight: 700; font-weight: 700;

View file

@ -3939,7 +3939,7 @@ export type components = {
/** @example 2018-03-12 */ /** @example 2018-03-12 */
birthday: string | null; birthday: string | null;
/** @example Steve */ /** @example Steve */
ListenBrainz: string | null; listenbrainz: string | null;
/** @example ja-JP */ /** @example ja-JP */
lang: string | null; lang: string | null;
fields: { fields: {