Frontend: Removed the gallery feature
This commit is contained in:
parent
d16f9d704d
commit
364074aecc
|
@ -14,7 +14,6 @@ import {
|
||||||
FollowingFolloweePopulated,
|
FollowingFolloweePopulated,
|
||||||
FollowingFollowerPopulated,
|
FollowingFollowerPopulated,
|
||||||
FollowRequest,
|
FollowRequest,
|
||||||
GalleryPost,
|
|
||||||
Instance,
|
Instance,
|
||||||
LiteInstanceMetadata,
|
LiteInstanceMetadata,
|
||||||
MeDetailed,
|
MeDetailed,
|
||||||
|
@ -563,25 +562,6 @@ export type Endpoints = {
|
||||||
"following/requests/list": { req: NoParams; res: FollowRequest[] };
|
"following/requests/list": { req: NoParams; res: FollowRequest[] };
|
||||||
"following/requests/reject": { req: { userId: User["id"] }; res: null };
|
"following/requests/reject": { req: { userId: User["id"] }; res: null };
|
||||||
|
|
||||||
// gallery
|
|
||||||
"gallery/featured": { req: TODO; res: TODO };
|
|
||||||
"gallery/popular": { req: TODO; res: TODO };
|
|
||||||
"gallery/posts": { req: TODO; res: TODO };
|
|
||||||
"gallery/posts/create": { req: TODO; res: TODO };
|
|
||||||
"gallery/posts/delete": { req: { postId: GalleryPost["id"] }; res: null };
|
|
||||||
"gallery/posts/like": { req: TODO; res: TODO };
|
|
||||||
"gallery/posts/show": { req: TODO; res: TODO };
|
|
||||||
"gallery/posts/unlike": { req: TODO; res: TODO };
|
|
||||||
"gallery/posts/update": { req: TODO; res: TODO };
|
|
||||||
|
|
||||||
// games
|
|
||||||
"games/reversi/games": { req: TODO; res: TODO };
|
|
||||||
"games/reversi/games/show": { req: TODO; res: TODO };
|
|
||||||
"games/reversi/games/surrender": { req: TODO; res: TODO };
|
|
||||||
"games/reversi/invitations": { req: TODO; res: TODO };
|
|
||||||
"games/reversi/match": { req: TODO; res: TODO };
|
|
||||||
"games/reversi/match/cancel": { req: TODO; res: TODO };
|
|
||||||
|
|
||||||
// get-online-users-count
|
// get-online-users-count
|
||||||
"get-online-users-count": { req: NoParams; res: { count: number } };
|
"get-online-users-count": { req: NoParams; res: { count: number } };
|
||||||
|
|
||||||
|
@ -611,8 +591,6 @@ export type Endpoints = {
|
||||||
};
|
};
|
||||||
res: NoteFavorite[];
|
res: NoteFavorite[];
|
||||||
};
|
};
|
||||||
"i/gallery/likes": { req: TODO; res: TODO };
|
|
||||||
"i/gallery/posts": { req: TODO; res: TODO };
|
|
||||||
"i/get-word-muted-notes-count": { req: TODO; res: TODO };
|
"i/get-word-muted-notes-count": { req: TODO; res: TODO };
|
||||||
"i/import-following": { req: TODO; res: TODO };
|
"i/import-following": { req: TODO; res: TODO };
|
||||||
"i/import-user-lists": { req: TODO; res: TODO };
|
"i/import-user-lists": { req: TODO; res: TODO };
|
||||||
|
@ -950,7 +928,6 @@ export type Endpoints = {
|
||||||
};
|
};
|
||||||
res: FollowingFolloweePopulated[];
|
res: FollowingFolloweePopulated[];
|
||||||
};
|
};
|
||||||
"users/gallery/posts": { req: TODO; res: TODO };
|
|
||||||
"users/get-frequently-replied-users": { req: TODO; res: TODO };
|
"users/get-frequently-replied-users": { req: TODO; res: TODO };
|
||||||
"users/lists/create": { req: { name: string }; res: UserList };
|
"users/lists/create": { req: { name: string }; res: UserList };
|
||||||
"users/lists/delete": { req: { listId: UserList["id"] }; res: null };
|
"users/lists/delete": { req: { listId: UserList["id"] }; res: null };
|
||||||
|
|
|
@ -44,12 +44,4 @@ export const permissions = [
|
||||||
"read:reactions",
|
"read:reactions",
|
||||||
"write:reactions",
|
"write:reactions",
|
||||||
"write:votes",
|
"write:votes",
|
||||||
"read:pages",
|
|
||||||
"write:pages",
|
|
||||||
"write:page-likes",
|
|
||||||
"read:page-likes",
|
|
||||||
"read:gallery",
|
|
||||||
"write:gallery",
|
|
||||||
"read:gallery-likes",
|
|
||||||
"write:gallery-likes",
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -121,8 +121,6 @@ export type DriveFile = {
|
||||||
|
|
||||||
export type DriveFolder = TODO;
|
export type DriveFolder = TODO;
|
||||||
|
|
||||||
export type GalleryPost = TODO;
|
|
||||||
|
|
||||||
export type Note = {
|
export type Note = {
|
||||||
id: ID;
|
id: ID;
|
||||||
createdAt: DateString;
|
createdAt: DateString;
|
||||||
|
|
|
@ -1,118 +0,0 @@
|
||||||
<template>
|
|
||||||
<MkA :to="`/gallery/${post.id}`" class="ttasepnz _panel">
|
|
||||||
<div class="thumbnail">
|
|
||||||
<ImgWithBlurhash
|
|
||||||
class="img"
|
|
||||||
:src="post.files[0].thumbnailUrl"
|
|
||||||
:hash="post.files[0].blurhash"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<article>
|
|
||||||
<header>
|
|
||||||
<MagAvatarResolvingProxy :user="post.user" class="avatar" />
|
|
||||||
</header>
|
|
||||||
<footer>
|
|
||||||
<span class="title">{{ post.title }}</span>
|
|
||||||
</footer>
|
|
||||||
</article>
|
|
||||||
</MkA>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import ImgWithBlurhash from "@/components/MkImgWithBlurhash.vue";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
post: any;
|
|
||||||
}>();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.ttasepnz {
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
height: 200px;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus {
|
|
||||||
text-decoration: none;
|
|
||||||
color: var(--accent);
|
|
||||||
|
|
||||||
> .thumbnail {
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
> article {
|
|
||||||
> footer {
|
|
||||||
&:before {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .thumbnail {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
position: absolute;
|
|
||||||
transition: all 0.5s ease;
|
|
||||||
|
|
||||||
> .img {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> article {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
> header {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
> .avatar {
|
|
||||||
margin-left: auto;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> footer {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
padding: 16px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
color: #fff;
|
|
||||||
text-shadow: 0 0 8px var(--shadow);
|
|
||||||
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: -1;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: linear-gradient(rgba(0, 0, 0, 0.4), transparent);
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .title {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -49,7 +49,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from "vue";
|
import { onMounted } from "vue";
|
||||||
import * as misskey from "calckey-js";
|
import * as misskey from "calckey-js";
|
||||||
import PhotoSwipeLightbox from "photoswipe/lightbox";
|
import PhotoSwipeLightbox from "photoswipe/lightbox";
|
||||||
import PhotoSwipe from "photoswipe";
|
import PhotoSwipe from "photoswipe";
|
||||||
|
@ -68,7 +68,6 @@ const props = defineProps<{
|
||||||
inDm?: boolean;
|
inDm?: boolean;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const gallery = ref(null);
|
|
||||||
const pswpZIndex = os.claimZIndex("middle");
|
const pswpZIndex = os.claimZIndex("middle");
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
@ -104,7 +103,6 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
}),
|
}),
|
||||||
gallery: gallery.value,
|
|
||||||
children: ".image",
|
children: ".image",
|
||||||
thumbSelector: ".image",
|
thumbSelector: ".image",
|
||||||
loop: false,
|
loop: false,
|
||||||
|
|
|
@ -63,11 +63,6 @@ export const navbarItemDef = reactive({
|
||||||
show: computed(() => $i != null),
|
show: computed(() => $i != null),
|
||||||
to: "/my/favorites",
|
to: "/my/favorites",
|
||||||
},
|
},
|
||||||
gallery: {
|
|
||||||
title: "gallery",
|
|
||||||
icon: "ph-image-square ph-bold ph-lg",
|
|
||||||
to: "/gallery",
|
|
||||||
},
|
|
||||||
clips: {
|
clips: {
|
||||||
title: "clips",
|
title: "clips",
|
||||||
icon: "ph-paperclip ph-bold ph-lg",
|
icon: "ph-paperclip ph-bold ph-lg",
|
||||||
|
|
|
@ -1,195 +0,0 @@
|
||||||
<template>
|
|
||||||
<MkStickyContainer>
|
|
||||||
<template #header
|
|
||||||
><MkPageHeader :actions="headerActions" :tabs="headerTabs"
|
|
||||||
/></template>
|
|
||||||
<MkSpacer :content-max="800" :margin-min="16" :margin-max="32">
|
|
||||||
<FormSuspense :p="init">
|
|
||||||
<FormInput v-model="title">
|
|
||||||
<template #label>{{ i18n.ts.title }}</template>
|
|
||||||
</FormInput>
|
|
||||||
|
|
||||||
<FormTextarea v-model="description" :max="500">
|
|
||||||
<template #label>{{ i18n.ts.description }}</template>
|
|
||||||
</FormTextarea>
|
|
||||||
|
|
||||||
<div class="">
|
|
||||||
<div
|
|
||||||
v-for="file in files"
|
|
||||||
:key="file.id"
|
|
||||||
class="wqugxsfx"
|
|
||||||
:style="{
|
|
||||||
backgroundImage: file
|
|
||||||
? `url(${file.thumbnailUrl})`
|
|
||||||
: null,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<div class="name">{{ file.name }}</div>
|
|
||||||
<button
|
|
||||||
v-tooltip="i18n.ts.remove"
|
|
||||||
class="remove _button"
|
|
||||||
@click="remove(file)"
|
|
||||||
>
|
|
||||||
<i class="ph-x ph-bold ph-lg"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<FormButton primary @click="selectFile"
|
|
||||||
><i class="ph-plus ph-bold ph-lg"></i>
|
|
||||||
{{ i18n.ts.attachFile }}</FormButton
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<FormSwitch v-model="isSensitive">{{
|
|
||||||
i18n.ts.markAsSensitive
|
|
||||||
}}</FormSwitch>
|
|
||||||
|
|
||||||
<FormButton v-if="postId" primary @click="save"
|
|
||||||
><i class="ph-floppy-disk-back ph-bold ph-lg"></i>
|
|
||||||
{{ i18n.ts.save }}</FormButton
|
|
||||||
>
|
|
||||||
<FormButton v-else primary @click="save"
|
|
||||||
><i class="ph-floppy-disk-back ph-bold ph-lg"></i>
|
|
||||||
{{ i18n.ts.publish }}</FormButton
|
|
||||||
>
|
|
||||||
|
|
||||||
<FormButton v-if="postId" danger @click="del"
|
|
||||||
><i class="ph-trash ph-bold ph-lg"></i>
|
|
||||||
{{ i18n.ts.delete }}</FormButton
|
|
||||||
>
|
|
||||||
</FormSuspense>
|
|
||||||
</MkSpacer>
|
|
||||||
</MkStickyContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { computed, inject, watch } from "vue";
|
|
||||||
import FormButton from "@/components/MkButton.vue";
|
|
||||||
import FormInput from "@/components/form/input.vue";
|
|
||||||
import FormTextarea from "@/components/form/textarea.vue";
|
|
||||||
import FormSwitch from "@/components/form/switch.vue";
|
|
||||||
import FormSuspense from "@/components/form/suspense.vue";
|
|
||||||
import { selectFiles } from "@/scripts/select-file";
|
|
||||||
import * as os from "@/os";
|
|
||||||
import { useRouter } from "@/router";
|
|
||||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
|
||||||
import { i18n } from "@/i18n";
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
postId?: string;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
let init = $ref(null);
|
|
||||||
let files = $ref([]);
|
|
||||||
let description = $ref(null);
|
|
||||||
let title = $ref(null);
|
|
||||||
let isSensitive = $ref(false);
|
|
||||||
|
|
||||||
function selectFile(evt) {
|
|
||||||
selectFiles(evt.currentTarget ?? evt.target, null).then((selected) => {
|
|
||||||
files = files.concat(selected);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function remove(file) {
|
|
||||||
files = files.filter((f) => f.id !== file.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function save() {
|
|
||||||
if (props.postId) {
|
|
||||||
await os.apiWithDialog("gallery/posts/update", {
|
|
||||||
postId: props.postId,
|
|
||||||
title: title,
|
|
||||||
description: description,
|
|
||||||
fileIds: files.map((file) => file.id),
|
|
||||||
isSensitive: isSensitive,
|
|
||||||
});
|
|
||||||
router.push(`/gallery/${props.postId}`);
|
|
||||||
} else {
|
|
||||||
const created = await os.apiWithDialog("gallery/posts/create", {
|
|
||||||
title: title,
|
|
||||||
description: description,
|
|
||||||
fileIds: files.map((file) => file.id),
|
|
||||||
isSensitive: isSensitive,
|
|
||||||
});
|
|
||||||
router.push(`/gallery/${created.id}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function del() {
|
|
||||||
const { canceled } = await os.confirm({
|
|
||||||
type: "warning",
|
|
||||||
text: i18n.ts.deleteConfirm,
|
|
||||||
});
|
|
||||||
if (canceled) return;
|
|
||||||
await os.apiWithDialog("gallery/posts/delete", {
|
|
||||||
postId: props.postId,
|
|
||||||
});
|
|
||||||
router.push("/gallery");
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.postId,
|
|
||||||
() => {
|
|
||||||
init = () =>
|
|
||||||
props.postId
|
|
||||||
? os
|
|
||||||
.api("gallery/posts/show", {
|
|
||||||
postId: props.postId,
|
|
||||||
})
|
|
||||||
.then((post) => {
|
|
||||||
files = post.files;
|
|
||||||
title = post.title;
|
|
||||||
description = post.description;
|
|
||||||
isSensitive = post.isSensitive;
|
|
||||||
})
|
|
||||||
: Promise.resolve(null);
|
|
||||||
},
|
|
||||||
{ immediate: true }
|
|
||||||
);
|
|
||||||
|
|
||||||
const headerActions = $computed(() => []);
|
|
||||||
|
|
||||||
const headerTabs = $computed(() => []);
|
|
||||||
|
|
||||||
definePageMetadata(
|
|
||||||
computed(() =>
|
|
||||||
props.postId
|
|
||||||
? {
|
|
||||||
title: i18n.ts.edit,
|
|
||||||
icon: "ph-pencil ph-bold ph-lg",
|
|
||||||
}
|
|
||||||
: {
|
|
||||||
title: i18n.ts.postToGallery,
|
|
||||||
icon: "ph-pencil ph-bold ph-lg",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.wqugxsfx {
|
|
||||||
height: 200px;
|
|
||||||
background-size: contain;
|
|
||||||
background-position: center;
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
> .name {
|
|
||||||
position: absolute;
|
|
||||||
top: 8px;
|
|
||||||
left: 9px;
|
|
||||||
padding: 8px;
|
|
||||||
background: var(--panel);
|
|
||||||
}
|
|
||||||
|
|
||||||
> .remove {
|
|
||||||
position: absolute;
|
|
||||||
top: 8px;
|
|
||||||
right: 9px;
|
|
||||||
padding: 8px;
|
|
||||||
background: var(--panel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,223 +0,0 @@
|
||||||
<template>
|
|
||||||
<MkStickyContainer>
|
|
||||||
<template #header
|
|
||||||
><MkPageHeader
|
|
||||||
v-model:tab="tab"
|
|
||||||
:actions="headerActions"
|
|
||||||
:tabs="headerTabs"
|
|
||||||
:display-back-button="true"
|
|
||||||
/></template>
|
|
||||||
<MkSpacer :content-max="1200">
|
|
||||||
<swiper
|
|
||||||
:round-lengths="true"
|
|
||||||
:touch-angle="25"
|
|
||||||
:threshold="10"
|
|
||||||
:centeredSlides="true"
|
|
||||||
:modules="[Virtual]"
|
|
||||||
:space-between="20"
|
|
||||||
:virtual="true"
|
|
||||||
:allow-touch-move="
|
|
||||||
!(
|
|
||||||
deviceKind === 'desktop' &&
|
|
||||||
!defaultStore.state.swipeOnDesktop
|
|
||||||
)
|
|
||||||
"
|
|
||||||
@swiper="setSwiperRef"
|
|
||||||
@slide-change="onSlideChange"
|
|
||||||
>
|
|
||||||
<swiper-slide>
|
|
||||||
<MkFolder class="_gap">
|
|
||||||
<template #header
|
|
||||||
><i class="ph-clock ph-bold ph-lg"></i>
|
|
||||||
{{ i18n.ts.recentPosts }}</template
|
|
||||||
>
|
|
||||||
<MkPagination
|
|
||||||
v-slot="{ items }"
|
|
||||||
:pagination="recentPostsPagination"
|
|
||||||
:disable-auto-load="true"
|
|
||||||
>
|
|
||||||
<div class="vfpdbgtk">
|
|
||||||
<MkGalleryPostPreview
|
|
||||||
v-for="post in items"
|
|
||||||
:key="post.id"
|
|
||||||
:post="post"
|
|
||||||
class="post"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</MkPagination>
|
|
||||||
</MkFolder>
|
|
||||||
<MkFolder class="_gap">
|
|
||||||
<template #header
|
|
||||||
><i class="ph-fire-simple ph-bold ph-lg"></i>
|
|
||||||
{{ i18n.ts.popularPosts }}</template
|
|
||||||
>
|
|
||||||
<MkPagination
|
|
||||||
v-slot="{ items }"
|
|
||||||
:pagination="popularPostsPagination"
|
|
||||||
:disable-auto-load="true"
|
|
||||||
>
|
|
||||||
<div class="vfpdbgtk">
|
|
||||||
<MkGalleryPostPreview
|
|
||||||
v-for="post in items"
|
|
||||||
:key="post.id"
|
|
||||||
:post="post"
|
|
||||||
class="post"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</MkPagination>
|
|
||||||
</MkFolder>
|
|
||||||
</swiper-slide>
|
|
||||||
<swiper-slide>
|
|
||||||
<MkPagination
|
|
||||||
v-slot="{ items }"
|
|
||||||
:pagination="likedPostsPagination"
|
|
||||||
>
|
|
||||||
<div class="vfpdbgtk">
|
|
||||||
<MkGalleryPostPreview
|
|
||||||
v-for="like in items"
|
|
||||||
:key="like.id"
|
|
||||||
:post="like.post"
|
|
||||||
class="post"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</MkPagination>
|
|
||||||
</swiper-slide>
|
|
||||||
<swiper-slide>
|
|
||||||
<MkA to="/gallery/new" class="_link" style="margin: 16px"
|
|
||||||
><i class="ph-plus ph-bold ph-lg"></i>
|
|
||||||
{{ i18n.ts.postToGallery }}</MkA
|
|
||||||
>
|
|
||||||
<MkPagination
|
|
||||||
v-slot="{ items }"
|
|
||||||
:pagination="myPostsPagination"
|
|
||||||
>
|
|
||||||
<div class="vfpdbgtk">
|
|
||||||
<MkGalleryPostPreview
|
|
||||||
v-for="post in items"
|
|
||||||
:key="post.id"
|
|
||||||
:post="post"
|
|
||||||
class="post"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</MkPagination>
|
|
||||||
</swiper-slide>
|
|
||||||
</swiper>
|
|
||||||
</MkSpacer>
|
|
||||||
</MkStickyContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { computed, defineComponent, watch, onMounted } from "vue";
|
|
||||||
import { Virtual } from "swiper";
|
|
||||||
import { Swiper, SwiperSlide } from "swiper/vue";
|
|
||||||
import MkFolder from "@/components/MkFolder.vue";
|
|
||||||
import MkPagination from "@/components/MkPagination.vue";
|
|
||||||
import MkGalleryPostPreview from "@/components/MkGalleryPostPreview.vue";
|
|
||||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
|
||||||
import { deviceKind } from "@/scripts/device-kind";
|
|
||||||
import { i18n } from "@/i18n";
|
|
||||||
import { useRouter } from "@/router";
|
|
||||||
import { defaultStore } from "@/store";
|
|
||||||
import "swiper/scss";
|
|
||||||
import "swiper/scss/virtual";
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
tag?: string;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const tabs = ["explore", "liked", "my"];
|
|
||||||
let tab = $ref(tabs[0]);
|
|
||||||
watch($$(tab), () => syncSlide(tabs.indexOf(tab)));
|
|
||||||
|
|
||||||
let tagsRef = $ref();
|
|
||||||
|
|
||||||
const recentPostsPagination = {
|
|
||||||
endpoint: "gallery/posts" as const,
|
|
||||||
limit: 6,
|
|
||||||
};
|
|
||||||
const popularPostsPagination = {
|
|
||||||
endpoint: "gallery/featured" as const,
|
|
||||||
limit: 5,
|
|
||||||
};
|
|
||||||
const myPostsPagination = {
|
|
||||||
endpoint: "i/gallery/posts" as const,
|
|
||||||
limit: 5,
|
|
||||||
};
|
|
||||||
const likedPostsPagination = {
|
|
||||||
endpoint: "i/gallery/likes" as const,
|
|
||||||
limit: 5,
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => props.tag,
|
|
||||||
() => {
|
|
||||||
if (tagsRef) tagsRef.tags.toggleContent(props.tag == null);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const headerActions = $computed(() => [
|
|
||||||
{
|
|
||||||
icon: "ph-plus ph-bold ph-lg",
|
|
||||||
text: i18n.ts.create,
|
|
||||||
handler: () => {
|
|
||||||
router.push("/gallery/new");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const headerTabs = $computed(() => [
|
|
||||||
{
|
|
||||||
key: "explore",
|
|
||||||
title: i18n.ts.gallery,
|
|
||||||
icon: "ph-image-square ph-bold ph-lg",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "liked",
|
|
||||||
title: i18n.ts._gallery.liked,
|
|
||||||
icon: "ph-heart ph-bold ph-lg",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "my",
|
|
||||||
title: i18n.ts._gallery.my,
|
|
||||||
icon: "ph-crown-simple ph-bold ph-lg",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
definePageMetadata({
|
|
||||||
title: i18n.ts.gallery,
|
|
||||||
icon: "ph-image-square ph-bold ph-lg",
|
|
||||||
});
|
|
||||||
|
|
||||||
let swiperRef = null;
|
|
||||||
|
|
||||||
function setSwiperRef(swiper) {
|
|
||||||
swiperRef = swiper;
|
|
||||||
syncSlide(tabs.indexOf(tab));
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSlideChange() {
|
|
||||||
tab = tabs[swiperRef.activeIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
function syncSlide(index) {
|
|
||||||
swiperRef.slideTo(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
syncSlide(tabs.indexOf(swiperRef.activeIndex));
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.vfpdbgtk {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
||||||
grid-gap: 12px;
|
|
||||||
margin: 0 var(--margin);
|
|
||||||
|
|
||||||
> .post {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,360 +0,0 @@
|
||||||
<template>
|
|
||||||
<MkStickyContainer>
|
|
||||||
<template #header
|
|
||||||
><MkPageHeader :actions="headerActions" :tabs="headerTabs"
|
|
||||||
/></template>
|
|
||||||
<MkSpacer :content-max="1000" :margin-min="16" :margin-max="32">
|
|
||||||
<div class="_root">
|
|
||||||
<transition
|
|
||||||
:name="$store.state.animation ? 'fade' : ''"
|
|
||||||
mode="out-in"
|
|
||||||
>
|
|
||||||
<div v-if="post" class="rkxwuolj">
|
|
||||||
<div class="files">
|
|
||||||
<div
|
|
||||||
v-for="file in post.files"
|
|
||||||
:key="file.id"
|
|
||||||
class="file"
|
|
||||||
>
|
|
||||||
<img :src="file.url" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="body _block">
|
|
||||||
<div class="title">{{ post.title }}</div>
|
|
||||||
<div class="description">
|
|
||||||
<Mfm :text="post.description" />
|
|
||||||
</div>
|
|
||||||
<div class="info">
|
|
||||||
<i class="ph-clock ph-bold ph-lg"></i>
|
|
||||||
<MkTime :time="post.createdAt" mode="detail" />
|
|
||||||
</div>
|
|
||||||
<div class="actions">
|
|
||||||
<div class="like">
|
|
||||||
<MkButton
|
|
||||||
v-if="post.isLiked"
|
|
||||||
v-tooltip="i18n.ts._gallery.unlike"
|
|
||||||
class="button"
|
|
||||||
primary
|
|
||||||
@click="unlike()"
|
|
||||||
><i class="ph-heart ph-fill ph-lg"></i
|
|
||||||
><span
|
|
||||||
v-if="post.likedCount > 0"
|
|
||||||
class="count"
|
|
||||||
>{{ post.likedCount }}</span
|
|
||||||
></MkButton
|
|
||||||
>
|
|
||||||
<MkButton
|
|
||||||
v-else
|
|
||||||
v-tooltip="i18n.ts._gallery.like"
|
|
||||||
class="button"
|
|
||||||
@click="like()"
|
|
||||||
><i class="ph-heart ph-bold"></i
|
|
||||||
><span
|
|
||||||
v-if="post.likedCount > 0"
|
|
||||||
class="count"
|
|
||||||
>{{ post.likedCount }}</span
|
|
||||||
></MkButton
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="other">
|
|
||||||
<button
|
|
||||||
v-if="$i && $i.id === post.user.id"
|
|
||||||
v-tooltip="i18n.ts.edit"
|
|
||||||
class="_button"
|
|
||||||
@click="edit"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="ph-pencil ph-bold ph-lg ph-fw ph-lg"
|
|
||||||
></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
v-tooltip="i18n.ts.shareWithNote"
|
|
||||||
class="_button"
|
|
||||||
@click="shareWithNote"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="ph-repeat ph-bold ph-lg ph-fw ph-lg"
|
|
||||||
></i>
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
v-if="shareAvailable()"
|
|
||||||
v-tooltip="i18n.ts.share"
|
|
||||||
class="_button"
|
|
||||||
@click="share"
|
|
||||||
>
|
|
||||||
<i
|
|
||||||
class="ph-share-network ph-bold ph-lg ph-fw ph-lg"
|
|
||||||
></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="user">
|
|
||||||
<MagAvatarResolvingProxy
|
|
||||||
:user="post.user"
|
|
||||||
class="avatar"
|
|
||||||
/>
|
|
||||||
<div class="name">
|
|
||||||
<MkUserName
|
|
||||||
:user="post.user"
|
|
||||||
style="display: block"
|
|
||||||
/>
|
|
||||||
<MkAcct :user="post.user" />
|
|
||||||
</div>
|
|
||||||
<MkFollowButton
|
|
||||||
v-if="!$i || $i.id != post.user.id"
|
|
||||||
:user="post.user"
|
|
||||||
:inline="true"
|
|
||||||
:transparent="false"
|
|
||||||
:full="true"
|
|
||||||
large
|
|
||||||
class="koudoku"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<MkContainer
|
|
||||||
:max-height="300"
|
|
||||||
:foldable="true"
|
|
||||||
class="other"
|
|
||||||
>
|
|
||||||
<template #header
|
|
||||||
><i class="ph-clock ph-bold ph-lg"></i>
|
|
||||||
{{ i18n.ts.recentPosts }}</template
|
|
||||||
>
|
|
||||||
<MkPagination
|
|
||||||
v-slot="{ items }"
|
|
||||||
:pagination="otherPostsPagination"
|
|
||||||
>
|
|
||||||
<div class="sdrarzaf">
|
|
||||||
<MkGalleryPostPreview
|
|
||||||
v-for="post in items"
|
|
||||||
:key="post.id"
|
|
||||||
:post="post"
|
|
||||||
class="post"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</MkPagination>
|
|
||||||
</MkContainer>
|
|
||||||
</div>
|
|
||||||
<MkError v-else-if="error" @retry="fetch()" />
|
|
||||||
<MkLoading v-else />
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
</MkSpacer>
|
|
||||||
</MkStickyContainer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { computed, watch } from "vue";
|
|
||||||
import MkButton from "@/components/MkButton.vue";
|
|
||||||
import * as os from "@/os";
|
|
||||||
import MkContainer from "@/components/MkContainer.vue";
|
|
||||||
import MkPagination from "@/components/MkPagination.vue";
|
|
||||||
import MkGalleryPostPreview from "@/components/MkGalleryPostPreview.vue";
|
|
||||||
import MkFollowButton from "@/components/MkFollowButton.vue";
|
|
||||||
import { url } from "@/config";
|
|
||||||
import { useRouter } from "@/router";
|
|
||||||
import { i18n } from "@/i18n";
|
|
||||||
import { definePageMetadata } from "@/scripts/page-metadata";
|
|
||||||
import { shareAvailable } from "@/scripts/share-available";
|
|
||||||
import { $i } from "@/account";
|
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const props = defineProps<{
|
|
||||||
postId: string;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
let post = $ref(null);
|
|
||||||
let error = $ref(null);
|
|
||||||
const otherPostsPagination = {
|
|
||||||
endpoint: "users/gallery/posts" as const,
|
|
||||||
limit: 6,
|
|
||||||
params: computed(() => ({
|
|
||||||
userId: post.user.id,
|
|
||||||
})),
|
|
||||||
};
|
|
||||||
|
|
||||||
function fetchPost() {
|
|
||||||
post = null;
|
|
||||||
os.api("gallery/posts/show", {
|
|
||||||
postId: props.postId,
|
|
||||||
})
|
|
||||||
.then((_post) => {
|
|
||||||
post = _post;
|
|
||||||
})
|
|
||||||
.catch((_error) => {
|
|
||||||
error = _error;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function share() {
|
|
||||||
navigator.share({
|
|
||||||
title: post.title,
|
|
||||||
text: post.description,
|
|
||||||
url: `${url}/gallery/${post.id}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function shareWithNote() {
|
|
||||||
os.post({
|
|
||||||
initialText: `${post.title} ${url}/gallery/${post.id}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function like() {
|
|
||||||
os.api("gallery/posts/like", {
|
|
||||||
postId: props.postId,
|
|
||||||
}).then(() => {
|
|
||||||
post.isLiked = true;
|
|
||||||
post.likedCount++;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function unlike() {
|
|
||||||
os.api("gallery/posts/unlike", {
|
|
||||||
postId: props.postId,
|
|
||||||
}).then(() => {
|
|
||||||
post.isLiked = false;
|
|
||||||
post.likedCount--;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function edit() {
|
|
||||||
router.push(`/gallery/${post.id}/edit`);
|
|
||||||
}
|
|
||||||
|
|
||||||
watch(() => props.postId, fetchPost, { immediate: true });
|
|
||||||
|
|
||||||
const headerActions = $computed(() => [
|
|
||||||
{
|
|
||||||
icon: "ph-pencil ph-bold ph-lg",
|
|
||||||
text: i18n.ts.edit,
|
|
||||||
handler: edit,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const headerTabs = $computed(() => []);
|
|
||||||
|
|
||||||
definePageMetadata(
|
|
||||||
computed(() =>
|
|
||||||
post
|
|
||||||
? {
|
|
||||||
title: post.title,
|
|
||||||
avatar: post.user,
|
|
||||||
}
|
|
||||||
: null
|
|
||||||
)
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.fade-enter-active,
|
|
||||||
.fade-leave-active {
|
|
||||||
transition: opacity 0.125s ease;
|
|
||||||
}
|
|
||||||
.fade-enter-from,
|
|
||||||
.fade-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rkxwuolj {
|
|
||||||
> .files {
|
|
||||||
> .file {
|
|
||||||
> img {
|
|
||||||
display: block;
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 500px;
|
|
||||||
margin: 0 auto;
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& + .file {
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .body {
|
|
||||||
padding: 32px;
|
|
||||||
|
|
||||||
> .title {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.2em;
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .info {
|
|
||||||
margin-top: 16px;
|
|
||||||
font-size: 90%;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .actions {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-top: 16px;
|
|
||||||
padding: 16px 0 0 0;
|
|
||||||
border-top: solid 0.5px var(--divider);
|
|
||||||
|
|
||||||
> .like {
|
|
||||||
> .button {
|
|
||||||
--accent: #eb6f92;
|
|
||||||
--X8: #eb6f92;
|
|
||||||
--buttonBg: rgb(216 71 106 / 5%);
|
|
||||||
--buttonHoverBg: rgb(216 71 106 / 10%);
|
|
||||||
color: #eb6f92;
|
|
||||||
|
|
||||||
::v-deep(.count) {
|
|
||||||
margin-left: 0.5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .other {
|
|
||||||
margin-left: auto;
|
|
||||||
|
|
||||||
> button {
|
|
||||||
padding: 8px;
|
|
||||||
margin: 0 8px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--fgHighlighted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> .user {
|
|
||||||
margin-top: 16px;
|
|
||||||
padding: 16px 0 0 0;
|
|
||||||
border-top: solid 0.5px var(--divider);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
> .avatar {
|
|
||||||
width: 52px;
|
|
||||||
height: 52px;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .name {
|
|
||||||
margin: 0 0 0 12px;
|
|
||||||
font-size: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .koudoku {
|
|
||||||
margin-left: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sdrarzaf {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
||||||
grid-gap: 12px;
|
|
||||||
margin: var(--margin);
|
|
||||||
|
|
||||||
> .post {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,45 +0,0 @@
|
||||||
<template>
|
|
||||||
<MkSpacer :content-max="800">
|
|
||||||
<MkPagination v-slot="{ items }" :pagination="pagination">
|
|
||||||
<div class="jrnovfpt">
|
|
||||||
<MkGalleryPostPreview
|
|
||||||
v-for="post in items"
|
|
||||||
:key="post.id"
|
|
||||||
:post="post"
|
|
||||||
class="post"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</MkPagination>
|
|
||||||
</MkSpacer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
import { computed } from "vue";
|
|
||||||
import MkGalleryPostPreview from "@/components/MkGalleryPostPreview.vue";
|
|
||||||
import MkPagination from "@/components/MkPagination.vue";
|
|
||||||
import { packed } from "magnetar-common";
|
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
user: packed.PackUserBase;
|
|
||||||
}>(),
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
|
|
||||||
const pagination = {
|
|
||||||
endpoint: "users/gallery/posts" as const,
|
|
||||||
limit: 6,
|
|
||||||
params: computed(() => ({
|
|
||||||
userId: props.user.id,
|
|
||||||
})),
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.jrnovfpt {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
||||||
grid-gap: 12px;
|
|
||||||
margin: var(--margin);
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -18,7 +18,6 @@
|
||||||
/>
|
/>
|
||||||
<XReactions v-else-if="tab === 'reactions'" :user="user" />
|
<XReactions v-else-if="tab === 'reactions'" :user="user" />
|
||||||
<XClips v-else-if="tab === 'clips'" :user="user" />
|
<XClips v-else-if="tab === 'clips'" :user="user" />
|
||||||
<XGallery v-else-if="tab === 'gallery'" :user="user" />
|
|
||||||
</div>
|
</div>
|
||||||
<MkError v-else-if="error" @retry="fetchUser()" />
|
<MkError v-else-if="error" @retry="fetchUser()" />
|
||||||
<MkLoading v-else />
|
<MkLoading v-else />
|
||||||
|
@ -41,7 +40,6 @@ import * as Acct from "calckey-js/built/acct";
|
||||||
const XHome = defineAsyncComponent(() => import("./home.vue"));
|
const XHome = defineAsyncComponent(() => import("./home.vue"));
|
||||||
const XReactions = defineAsyncComponent(() => import("./reactions.vue"));
|
const XReactions = defineAsyncComponent(() => import("./reactions.vue"));
|
||||||
const XClips = defineAsyncComponent(() => import("./clips.vue"));
|
const XClips = defineAsyncComponent(() => import("./clips.vue"));
|
||||||
const XGallery = defineAsyncComponent(() => import("./gallery.vue"));
|
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
|
@ -142,11 +140,6 @@ const headerTabs = $computed(() =>
|
||||||
title: i18n.ts.clips,
|
title: i18n.ts.clips,
|
||||||
icon: "ph-paperclip ph-bold ph-lg",
|
icon: "ph-paperclip ph-bold ph-lg",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
key: "gallery",
|
|
||||||
title: i18n.ts.gallery,
|
|
||||||
icon: "ph-image-square ph-bold ph-lg",
|
|
||||||
},
|
|
||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
]
|
]
|
||||||
|
|
|
@ -364,24 +364,6 @@ export const routes = [
|
||||||
path: "/tags/:tag",
|
path: "/tags/:tag",
|
||||||
component: page(() => import("./pages/tag.vue")),
|
component: page(() => import("./pages/tag.vue")),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/gallery/:postId/edit",
|
|
||||||
component: page(() => import("./pages/gallery/edit.vue")),
|
|
||||||
loginRequired: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/gallery/new",
|
|
||||||
component: page(() => import("./pages/gallery/edit.vue")),
|
|
||||||
loginRequired: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/gallery/:postId",
|
|
||||||
component: page(() => import("./pages/gallery/post.vue")),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/gallery",
|
|
||||||
component: page(() => import("./pages/gallery/index.vue")),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/registry/keys/system/:path(*)?",
|
path: "/registry/keys/system/:path(*)?",
|
||||||
component: page(() => import("./pages/registry.keys.vue")),
|
component: page(() => import("./pages/registry.keys.vue")),
|
||||||
|
|
|
@ -47,10 +47,6 @@
|
||||||
><i class="ph-compass ph-bold ph-lg icon"></i
|
><i class="ph-compass ph-bold ph-lg icon"></i
|
||||||
>{{ i18n.ts.explore }}</MkA
|
>{{ i18n.ts.explore }}</MkA
|
||||||
>
|
>
|
||||||
<MkA to="/gallery" class="link" active-class="active"
|
|
||||||
><i class="ph-image-square ph-bold ph-lg icon"></i
|
|
||||||
>{{ i18n.ts.gallery }}</MkA
|
|
||||||
>
|
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<button class="_buttonPrimary" @click="signup()">
|
<button class="_buttonPrimary" @click="signup()">
|
||||||
{{ i18n.ts.signup }}
|
{{ i18n.ts.signup }}
|
||||||
|
|
|
@ -18,10 +18,6 @@
|
||||||
><i class="ph-compass ph-bold ph-lg icon"></i
|
><i class="ph-compass ph-bold ph-lg icon"></i
|
||||||
>{{ i18n.ts.explore }}</MkA
|
>{{ i18n.ts.explore }}</MkA
|
||||||
>
|
>
|
||||||
<MkA to="/gallery" class="link" active-class="active"
|
|
||||||
><i class="ph-image-square ph-bold ph-lg icon"></i
|
|
||||||
>{{ i18n.ts.gallery }}</MkA
|
|
||||||
>
|
|
||||||
<div v-if="info" class="page active link">
|
<div v-if="info" class="page active link">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<i v-if="info.icon" class="icon" :class="info.icon"></i>
|
<i v-if="info.icon" class="icon" :class="info.icon"></i>
|
||||||
|
|
Loading…
Reference in New Issue