diff options
Diffstat (limited to 'packages/client/src/pages/explore.vue')
| -rw-r--r-- | packages/client/src/pages/explore.vue | 303 |
1 files changed, 68 insertions, 235 deletions
diff --git a/packages/client/src/pages/explore.vue b/packages/client/src/pages/explore.vue index 04cc3662a7..c0b9438a50 100644 --- a/packages/client/src/pages/explore.vue +++ b/packages/client/src/pages/explore.vue @@ -1,261 +1,94 @@ <template> -<div> - <MkSpacer :content-max="1200"> - <div class="lznhrdub"> - <div v-if="tab === 'local'"> - <div v-if="meta && stats && tag == null" class="localfedi7 _block _isolated" :style="{ backgroundImage: meta.bannerUrl ? `url(${meta.bannerUrl})` : null }"> - <header><span>{{ $t('explore', { host: meta.name || 'Misskey' }) }}</span></header> - <div><span>{{ $t('exploreUsersCount', { count: num(stats.originalUsersCount) }) }}</span></div> - </div> - - <template v-if="tag == null"> - <MkFolder class="_gap" persist-key="explore-pinned-users"> - <template #header><i class="fas fa-bookmark fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.pinnedUsers }}</template> - <XUserList :pagination="pinnedUsers"/> - </MkFolder> - <MkFolder class="_gap" persist-key="explore-popular-users"> - <template #header><i class="fas fa-chart-line fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.popularUsers }}</template> - <XUserList :pagination="popularUsers"/> - </MkFolder> - <MkFolder class="_gap" persist-key="explore-recently-updated-users"> - <template #header><i class="fas fa-comment-alt fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.recentlyUpdatedUsers }}</template> - <XUserList :pagination="recentlyUpdatedUsers"/> - </MkFolder> - <MkFolder class="_gap" persist-key="explore-recently-registered-users"> - <template #header><i class="fas fa-plus fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.recentlyRegisteredUsers }}</template> - <XUserList :pagination="recentlyRegisteredUsers"/> - </MkFolder> - </template> - </div> - <div v-else-if="tab === 'remote'"> - <div v-if="tag == null" class="localfedi7 _block _isolated" :style="{ backgroundImage: `url(/client-assets/fedi.jpg)` }"> - <header><span>{{ $ts.exploreFediverse }}</span></header> - </div> - - <MkFolder ref="tags" :foldable="true" :expanded="false" class="_gap"> - <template #header><i class="fas fa-hashtag fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.popularTags }}</template> - - <div class="vxjfqztj"> - <MkA v-for="tag in tagsLocal" :key="'local:' + tag.tag" :to="`/explore/tags/${tag.tag}`" class="local">{{ tag.tag }}</MkA> - <MkA v-for="tag in tagsRemote" :key="'remote:' + tag.tag" :to="`/explore/tags/${tag.tag}`">{{ tag.tag }}</MkA> - </div> - </MkFolder> - - <MkFolder v-if="tag != null" :key="`${tag}`" class="_gap"> - <template #header><i class="fas fa-hashtag fa-fw" style="margin-right: 0.5em;"></i>{{ tag }}</template> - <XUserList :pagination="tagUsers"/> - </MkFolder> - - <template v-if="tag == null"> - <MkFolder class="_gap"> - <template #header><i class="fas fa-chart-line fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.popularUsers }}</template> - <XUserList :pagination="popularUsersF"/> - </MkFolder> - <MkFolder class="_gap"> - <template #header><i class="fas fa-comment-alt fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.recentlyUpdatedUsers }}</template> - <XUserList :pagination="recentlyUpdatedUsersF"/> - </MkFolder> - <MkFolder class="_gap"> - <template #header><i class="fas fa-rocket fa-fw" style="margin-right: 0.5em;"></i>{{ $ts.recentlyDiscoveredUsers }}</template> - <XUserList :pagination="recentlyRegisteredUsersF"/> - </MkFolder> - </template> - </div> - <div v-else-if="tab === 'search'"> - <div class="_isolated"> - <MkInput v-model="searchQuery" :debounce="true" type="search"> +<MkStickyContainer> + <template #header><MkPageHeader v-model:tab="tab" :actions="headerActions" :tabs="headerTabs"/></template> + <div class="lznhrdub"> + <div v-if="tab === 'featured'"> + <XFeatured/> + </div> + <div v-else-if="tab === 'localUsers'"> + <XUsers origin="local"/> + </div> + <div v-else-if="tab === 'remoteUsers'"> + <XUsers origin="remote"/> + </div> + <div v-else-if="tab === 'search'"> + <MkSpacer :content-max="1200"> + <div> + <MkInput v-model="searchQuery" :debounce="true" type="search" class="_formBlock"> <template #prefix><i class="fas fa-search"></i></template> <template #label>{{ $ts.searchUser }}</template> </MkInput> - <MkRadios v-model="searchOrigin"> + <MkRadios v-model="searchOrigin" class="_formBlock"> <option value="combined">{{ $ts.all }}</option> <option value="local">{{ $ts.local }}</option> <option value="remote">{{ $ts.remote }}</option> </MkRadios> </div> - <XUserList v-if="searchQuery" ref="search" class="_gap" :pagination="searchPagination"/> - </div> + <XUserList v-if="searchQuery" ref="searchEl" class="_gap" :pagination="searchPagination"/> + </MkSpacer> </div> - </MkSpacer> -</div> + </div> +</MkStickyContainer> </template> -<script lang="ts"> -import { computed, defineComponent } from 'vue'; -import XUserList from '@/components/user-list.vue'; +<script lang="ts" setup> +import { computed, watch } from 'vue'; +import XFeatured from './explore.featured.vue'; +import XUsers from './explore.users.vue'; import MkFolder from '@/components/ui/folder.vue'; import MkInput from '@/components/form/input.vue'; import MkRadios from '@/components/form/radios.vue'; import number from '@/filters/number'; import * as os from '@/os'; -import * as symbols from '@/symbols'; - -export default defineComponent({ - components: { - XUserList, - MkFolder, - MkInput, - MkRadios, - }, - - props: { - tag: { - type: String, - required: false - } - }, - - data() { - return { - [symbols.PAGE_INFO]: computed(() => ({ - title: this.$ts.explore, - icon: 'fas fa-hashtag', - bg: 'var(--bg)', - tabs: [{ - active: this.tab === 'local', - title: this.$ts.local, - onClick: () => { this.tab = 'local'; }, - }, { - active: this.tab === 'remote', - title: this.$ts.remote, - onClick: () => { this.tab = 'remote'; }, - }, { - active: this.tab === 'search', - title: this.$ts.search, - onClick: () => { this.tab = 'search'; }, - },] - })), - tab: 'local', - pinnedUsers: { endpoint: 'pinned-users' }, - popularUsers: { endpoint: 'users', limit: 10, noPaging: true, params: { - state: 'alive', - origin: 'local', - sort: '+follower', - } }, - recentlyUpdatedUsers: { endpoint: 'users', limit: 10, noPaging: true, params: { - origin: 'local', - sort: '+updatedAt', - } }, - recentlyRegisteredUsers: { endpoint: 'users', limit: 10, noPaging: true, params: { - origin: 'local', - state: 'alive', - sort: '+createdAt', - } }, - popularUsersF: { endpoint: 'users', limit: 10, noPaging: true, params: { - state: 'alive', - origin: 'remote', - sort: '+follower', - } }, - recentlyUpdatedUsersF: { endpoint: 'users', limit: 10, noPaging: true, params: { - origin: 'combined', - sort: '+updatedAt', - } }, - recentlyRegisteredUsersF: { endpoint: 'users', limit: 10, noPaging: true, params: { - origin: 'combined', - sort: '+createdAt', - } }, - searchPagination: { - endpoint: 'users/search' as const, - limit: 10, - params: computed(() => (this.searchQuery && this.searchQuery !== '') ? { - query: this.searchQuery, - origin: this.searchOrigin, - } : null) - }, - tagsLocal: [], - tagsRemote: [], - stats: null, - searchQuery: null, - searchOrigin: 'combined', - num: number, - }; - }, +import { definePageMetadata } from '@/scripts/page-metadata'; +import { i18n } from '@/i18n'; +import { instance } from '@/instance'; +import XUserList from '@/components/user-list.vue'; - computed: { - meta() { - return this.$instance; - }, - tagUsers(): any { - return { - endpoint: 'hashtags/users' as const, - limit: 30, - params: { - tag: this.tag, - origin: 'combined', - sort: '+follower', - } - }; - }, - }, +const props = defineProps<{ + tag?: string; +}>(); - watch: { - tag() { - if (this.$refs.tags) this.$refs.tags.toggleContent(this.tag == null); - }, - }, +let tab = $ref('featured'); +let tagsEl = $ref<InstanceType<typeof MkFolder>>(); +let searchQuery = $ref(null); +let searchOrigin = $ref('combined'); - created() { - os.api('hashtags/list', { - sort: '+attachedLocalUsers', - attachedToLocalUserOnly: true, - limit: 30 - }).then(tags => { - this.tagsLocal = tags; - }); - os.api('hashtags/list', { - sort: '+attachedRemoteUsers', - attachedToRemoteUserOnly: true, - limit: 30 - }).then(tags => { - this.tagsRemote = tags; - }); - os.api('stats').then(stats => { - this.stats = stats; - }); - }, +watch(() => props.tag, () => { + if (tagsEl) tagsEl.toggleContent(props.tag == null); }); -</script> - -<style lang="scss" scoped> -.localfedi7 { - color: #fff; - padding: 16px; - height: 80px; - background-position: 50%; - background-size: cover; - margin-bottom: var(--margin); - - > * { - &:not(:last-child) { - margin-bottom: 8px; - } - > span { - display: inline-block; - padding: 6px 8px; - background: rgba(0, 0, 0, 0.7); - } - } +const searchPagination = { + endpoint: 'users/search' as const, + limit: 10, + params: computed(() => (searchQuery && searchQuery !== '') ? { + query: searchQuery, + origin: searchOrigin, + } : null), +}; - > header { - font-size: 20px; - font-weight: bold; - } +const headerActions = $computed(() => []); - > div { - font-size: 14px; - opacity: 0.8; - } -} +const headerTabs = $computed(() => [{ + key: 'featured', + icon: 'fas fa-bolt', + title: i18n.ts.featured, +}, { + key: 'localUsers', + icon: 'fas fa-users', + title: i18n.ts.users, +}, { + key: 'remoteUsers', + icon: 'fas fa-users', + title: i18n.ts.remote, +}, { + key: 'search', + title: i18n.ts.search, +}]); -.vxjfqztj { - > * { - margin-right: 16px; - - &.local { - font-weight: bold; - } - } -} -</style> +definePageMetadata(computed(() => ({ + title: i18n.ts.explore, + icon: 'fas fa-hashtag', +}))); +</script> |