diff --git a/locales/en-US.yml b/locales/en-US.yml index 1f8adba0b0..7df10c5ccf 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -5,6 +5,7 @@ introMisskey: "Welcome! Calckey is an open source, decentralized social media pl that's free forever! 🚀" monthAndDay: "{month}/{day}" search: "Search" +advancedSearch: "Advanced Search" searchPlaceholder: "Search Calckey" notifications: "Notifications" username: "Username" diff --git a/packages/client/src/components/MkButton.vue b/packages/client/src/components/MkButton.vue index 43aabccc84..440db30f09 100644 --- a/packages/client/src/components/MkButton.vue +++ b/packages/client/src/components/MkButton.vue @@ -18,6 +18,7 @@ :class="{ inline, primary, gradate, danger, rounded, full, mini }" :to="to" :behavior="behavior" + :external="external" @mousedown="onMousedown" > <div ref="ripples" class="ripples"></div> @@ -44,6 +45,7 @@ const props = defineProps<{ full?: boolean; mini?: boolean; chip?: boolean; + external?: boolean; behavior?: null | "window" | "browser" | "modalWindow"; }>(); diff --git a/packages/client/src/components/global/MkA.vue b/packages/client/src/components/global/MkA.vue index d276a4d9ac..d3138a8f4f 100644 --- a/packages/client/src/components/global/MkA.vue +++ b/packages/client/src/components/global/MkA.vue @@ -2,6 +2,7 @@ <a :href="to" :class="active ? activeClass : null" + :target="external ? '_blank' : ''" @contextmenu.prevent.stop="onContextmenu" @click.stop="nav" > @@ -22,6 +23,7 @@ const props = withDefaults( defineProps<{ to: string; activeClass?: null | string; + external?: boolean; behavior?: null | "window" | "browser" | "modalWindow"; }>(), { diff --git a/packages/client/src/components/global/MkPageHeader.vue b/packages/client/src/components/global/MkPageHeader.vue index 385e85cfc3..74e5226de8 100644 --- a/packages/client/src/components/global/MkPageHeader.vue +++ b/packages/client/src/components/global/MkPageHeader.vue @@ -101,6 +101,15 @@ </nav> </template> <div class="buttons right"> + <MkButton + v-if="!$i && displayHomeButton" + :to="'/'" + link + rounded + > + <i class="ph-house ph-bold ph-lg"></i> + {{ i18n.ts.home }} + </MkButton> <template v-if="metadata && metadata.avatar && $i"> <MkFollowButton v-if="narrow" diff --git a/packages/client/src/pages/welcome.entrance.a.vue b/packages/client/src/pages/welcome.entrance.a.vue index 87d4c8b7a6..9c0c97d934 100644 --- a/packages/client/src/pages/welcome.entrance.a.vue +++ b/packages/client/src/pages/welcome.entrance.a.vue @@ -1,5 +1,5 @@ <template> - <MkStickyContainer> + <MkStickyContainer id="visitor-view"> <template #header ><MkPageHeader v-model:tab="tab" @@ -8,109 +8,107 @@ :noTabCollapse="true" :displayHomeButton="false" /></template> - <div id="visitor-view"> - <swiper - class="swiper" - :round-lengths="true" - :touch-angle="25" - :threshold="10" - :centeredSlides="true" - :space-between="20" - :allow-touch-move=" - !( - deviceKind === 'desktop' && - !defaultStore.state.swipeOnDesktop - ) - " - :set-wrapper-size="true" - @swiper="setSwiperRef" - @slide-change="onSlideChange" - > - <swiper-slide v-slot="{ isActive }"> - <XKanban v-if="isActive" /> - </swiper-slide> - <swiper-slide v-slot="{ isActive }"> - <MkSpacer :content-max="800" v-if="isActive"> - <XNotes :pagination="paginationForLocal" /> - </MkSpacer> - </swiper-slide> - <swiper-slide v-slot="{ isActive }"> - <MkSpacer :content-max="800" v-if="isActive"> - <XNotes :pagination="paginationForRemote" /> - </MkSpacer> - </swiper-slide> - <swiper-slide v-slot="{ isActive }"> - <MkSpacer :content-max="800" v-if="isActive"> - <XChannelList - key="featured" - :pagination="featuredPagination" + <swiper + class="swiper" + :round-lengths="true" + :touch-angle="25" + :threshold="10" + :centeredSlides="true" + :space-between="20" + :allow-touch-move=" + !( + deviceKind === 'desktop' && + !defaultStore.state.swipeOnDesktop + ) + " + :set-wrapper-size="true" + @swiper="setSwiperRef" + @slide-change="onSlideChange" + > + <swiper-slide v-slot="{ isActive }"> + <XKanban v-if="isActive" /> + </swiper-slide> + <swiper-slide v-slot="{ isActive }"> + <MkSpacer :content-max="800" v-if="isActive"> + <XNotes :pagination="paginationForLocal" /> + </MkSpacer> + </swiper-slide> + <swiper-slide v-slot="{ isActive }"> + <MkSpacer :content-max="800" v-if="isActive"> + <XNotes :pagination="paginationForRemote" /> + </MkSpacer> + </swiper-slide> + <swiper-slide v-slot="{ isActive }"> + <MkSpacer :content-max="800" v-if="isActive"> + <XChannelList + key="featured" + :pagination="featuredPagination" + /> + </MkSpacer> + </swiper-slide> + <swiper-slide v-slot="{ isActive }"> + <MkSpacer :content-max="800" v-if="isActive"> + <MkPagination + v-slot="{ items }" + :pagination="featuredPagesPagination" + > + <MkPagePreview + v-for="page in items" + :key="page.id" + class="ckltabjg" + :page="page" /> - </MkSpacer> - </swiper-slide> - <swiper-slide v-slot="{ isActive }"> - <MkSpacer :content-max="800" v-if="isActive"> + </MkPagination> + </MkSpacer> + </swiper-slide> + <swiper-slide v-slot="{ isActive }"> + <MkSpacer :content-max="1200" v-if="isActive"> + <MkFolder class="_gap"> + <template #header + ><i class="ph-clock ph-bold ph-lg"></i> + {{ i18n.ts.recentPosts }}</template + > <MkPagination v-slot="{ items }" - :pagination="featuredPagesPagination" + :pagination="recentPostsPagination" + :disable-auto-load="true" > - <MkPagePreview - v-for="page in items" - :key="page.id" - class="ckltabjg" - :page="page" - /> + <div class="vfpdbgtk"> + <MkGalleryPostPreview + v-for="post in items" + :key="post.id" + :post="post" + class="post" + /> + </div> </MkPagination> - </MkSpacer> - </swiper-slide> - <swiper-slide v-slot="{ isActive }"> - <MkSpacer :content-max="1200" v-if="isActive"> - <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> - </MkSpacer> - </swiper-slide> - <swiper-slide v-slot="{ isActive }"> - <XUsers v-if="isActive" /> - </swiper-slide> - </swiper> - </div> + </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> + </MkSpacer> + </swiper-slide> + <swiper-slide v-slot="{ isActive }"> + <XUsers v-if="isActive" /> + </swiper-slide> + </swiper> </MkStickyContainer> </template> @@ -125,6 +123,7 @@ import XChannelList from "@/components/MkChannelList.vue"; import MkFolder from "@/components/MkFolder.vue"; import MkPagination from "@/components/MkPagination.vue"; import MkGalleryPostPreview from "@/components/MkGalleryPostPreview.vue"; +import { mainRouter } from "@/router"; import { definePageMetadata } from "@/scripts/page-metadata"; import { deviceKind } from "@/scripts/device-kind"; import { i18n } from "@/i18n"; @@ -200,6 +199,7 @@ definePageMetadata( icon: "ph-compass ph-bold ph-lg", })) ); +provide("shouldOmitHeaderTitle", true); let swiperRef = null; @@ -266,8 +266,6 @@ const popularPostsPagination = { </script> <style lang="scss" scoped> #visitor-view { - margin-top: -55px; - padding-top: 55px; .swiper { margin-top: -55px; padding-top: 55px; @@ -276,27 +274,26 @@ const popularPostsPagination = { mask: unset; -webkit-mask: unset; } - @media (min-width: 1100px) { - .swiper { - mask: linear-gradient(to bottom, black 70%, transparent 97%); - -webkit-mask: linear-gradient(to bottom, black 70%, transparent 97%); - padding-block: calc(2.5vw + 55px) 30vh; - margin-top: -55px; - max-height: 100vh; - box-sizing: border-box; - overflow: hidden auto !important; - } - &::before { - content: ""; - position: fixed; - inset: 0; - background-repeat: no-repeat; - background-size: cover; - background-position: center; - opacity: .8; - // filter: blur(4px); - background-image: v-bind("wallpaper"); - } - } + // @media (min-width: 1100px) { + // .swiper { + // mask: linear-gradient(to bottom, black 70%, transparent 97%); + // -webkit-mask: linear-gradient(to bottom, black 70%, transparent 97%); + // padding-block: calc(2.5vw + 55px) 30vh; + // margin-top: -55px; + // max-height: 100vh; + // box-sizing: border-box; + // overflow: hidden auto !important; + // } + // &::before { + // content: ""; + // position: fixed; + // inset: 0; + // background-repeat: no-repeat; + // background-size: cover; + // background-position: center; + // background-image: v-bind("wallpaper"); + // z-index: -1; + // } + // } } </style> diff --git a/packages/client/src/ui/visitor/kanban.vue b/packages/client/src/ui/visitor/kanban.vue index 0fed3b85ef..7f25deba1c 100644 --- a/packages/client/src/ui/visitor/kanban.vue +++ b/packages/client/src/ui/visitor/kanban.vue @@ -17,7 +17,7 @@ {{ i18n.ts.home }} </MkButton> </header> - <div class="instance-info-container" v-else :class="{ sticky }"> + <div class="instance-info-container" v-else :class="{ sticky, wallpaper: meta.backgroundImageUrl }"> <header id="instance-info" v-on:scroll.passive="onScroll"> <div class="banner" v-if="meta.bannerUrl"> <img :src="meta.bannerUrl" /> @@ -78,6 +78,7 @@ :link="true" :behavior="'browser'" rounded + external to="https://calckey.org/join/" > <i class="ph-airplane-tilt ph-bold"></i> @@ -159,34 +160,36 @@ </FormLink> --> </div> </FormSection> - <!-- <FormSection> - <div class="_formLinksGridFlex"> - <FormLink> - {{ i18n.ts.timelines }} - <template #suffix> - {{ - `${ i18n.ts._timelines.home },` + - meta.disableLocalTimeline ? null : `${ i18n.ts._timelines.local },` + - meta.disableLocalTimeline ? null : `${ i18n.ts._timelines.social },` + - meta.disableRecommendedTimeline ? null : `${ i18n.ts._timelines.recommended },` + - meta.disableGlobalTimeline ? null : `${ i18n.ts._timelines.global }` - }} + <FormSection> + <div class="_formLinksGrid"> + <MkKeyValue :text="i18n.t('_cw.chars', { count: meta.maxNoteTextLength })"> + <template #key> + {{ i18n.ts.characterLimit }} </template> - </FormLink> - <FormLink> - {{ i18n.ts.driveCapacityPerLocalAccount }} - <template #suffix> - {{ meta.driveCapacityPerLocalUserMb }}MB + </MkKeyValue> + <MkKeyValue :text="meta.features.searchFilters ? i18n.ts.yes : i18n.ts.no"> + <template #key> + {{ i18n.ts.advancedSearch }} </template> - </FormLink> - <FormLink> - {{ i18n.ts.characterLimit }} - <template #suffix> - {{ i18n.t("_cw.chars", { count: meta.maxNoteTextLength }) }} + </MkKeyValue> + <MkKeyValue + :text="`${ i18n.ts._timelines.home },` + + (meta.disableLocalTimeline ? '' : ` ${ i18n.ts._timelines.local },`) + + (meta.disableLocalTimeline ? '' : ` ${ i18n.ts._timelines.social },`) + + (meta.disableRecommendedTimeline ? '' : ` ${ i18n.ts._timelines.recommended },`) + + (meta.disableGlobalTimeline ? '' : ` ${ i18n.ts._timelines.global }`)" + > + <template #key> + {{ i18n.ts.timelines }} </template> - </FormLink> + </MkKeyValue> + <MkKeyValue :text="meta.driveCapacityPerLocalUserMb + 'MB'"> + <template #key> + {{ i18n.ts.driveCapacityPerLocalAccount }} + </template> + </MkKeyValue> </div> - </FormSection> --> + </FormSection> </footer> </div> </header> @@ -219,12 +222,15 @@ let meta = $ref<DetailedInstanceMetadata>(); let isLong = $ref(false); let collapsed = $ref(!isLong); const accentColor = getComputedStyle(document.documentElement).getPropertyValue("--accent");; -let themeColor = $ref(accentColor); +let wallpaper = $ref(); os.api("meta", { detail: true }).then((res) => { meta = res; isLong = meta.description && meta.description.length > 500; - themeColor = meta.themeColor ?? accentColor; + wallpaper = + meta.backgroundImageUrl ? `url(${meta.backgroundImageUrl})` + : meta.themeColor ?? accentColor; + // wallpaper = meta.backgroundImageUrl ? null : meta.themeColor ?? accentColor; }); let announcement = $ref(); @@ -298,6 +304,9 @@ function showMenu(ev) { .content { max-width: 450px; } + &.wallpaper { + width: 500px; + } } margin-left: -1px; box-shadow: 0 0 48px -24px rgba(0, 0, 0, 0.1); @@ -307,7 +316,10 @@ function showMenu(ev) { display: flex; flex-direction: column; height: 100%; - background: v-bind('themeColor'); + background: v-bind('wallpaper'); + background-position: center; + background-size: cover; + background-attachment: fixed; height: max-content; min-height: 100%; transition: transform 0.4s cubic-bezier(0.5, 0, 0, 1); @@ -317,7 +329,7 @@ function showMenu(ev) { width: calc(100% + 2px); margin-inline: -1px; padding-top: min(56.25%, 70vh); - margin-bottom: calc(-100px - var(--radius)); + margin-bottom: calc(-120px - var(--radius)); mask: linear-gradient(to bottom, black, calc(100% - 50px), transparent); -webkit-mask: linear-gradient(to bottom, black, calc(100% - 50px), transparent); transition: min-height 0.4s, max-height 0.4s, filter 0.7s; @@ -354,6 +366,10 @@ function showMenu(ev) { margin-inline: auto; width: 100%; box-sizing: border-box; + // &.wallpaper { + // flex-grow: 0; + // border-radius: var(--radius); + // } @media (max-width: 1100px) { &:first-child { margin-top: 140px; @@ -380,7 +396,7 @@ function showMenu(ev) { height: 80px; min-width: 80px; max-width: 100%; - border-radius: var(--radius); + border-radius: 6px; margin-top: -5px; transition: transform 0.4s cubic-bezier(0.5, 0, 0, 1); &:last-child {