From 88dc4c83cbde7960c280ae359569cfbaa120ae69 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 16 Feb 2019 10:58:44 +0900 Subject: Improve UI --- .../app/common/views/components/user-list.vue | 3 +- src/client/app/common/views/pages/followers.vue | 30 ++ src/client/app/common/views/pages/following.vue | 27 ++ src/client/app/desktop/script.ts | 16 +- .../desktop/views/deck/deck.user-column.home.vue | 244 ++++++++++++++ .../app/desktop/views/deck/deck.user-column.vue | 234 +------------- src/client/app/desktop/views/home/user/index.vue | 82 +++++ .../app/desktop/views/home/user/user.header.vue | 2 +- .../app/desktop/views/home/user/user.home.vue | 63 ++++ src/client/app/desktop/views/home/user/user.vue | 109 ------- .../views/pages/user-following-or-followers.vue | 120 ------- src/client/app/mobile/script.ts | 10 +- src/client/app/mobile/views/components/index.ts | 2 - .../app/mobile/views/components/users-list.vue | 135 -------- src/client/app/mobile/views/pages/followers.vue | 70 ----- src/client/app/mobile/views/pages/following.vue | 69 ---- src/client/app/mobile/views/pages/user.vue | 347 -------------------- src/client/app/mobile/views/pages/user/index.vue | 350 +++++++++++++++++++++ src/server/api/endpoints/users/followers.ts | 23 +- src/server/api/endpoints/users/following.ts | 23 +- 20 files changed, 855 insertions(+), 1104 deletions(-) create mode 100644 src/client/app/common/views/pages/followers.vue create mode 100644 src/client/app/common/views/pages/following.vue create mode 100644 src/client/app/desktop/views/deck/deck.user-column.home.vue create mode 100644 src/client/app/desktop/views/home/user/index.vue create mode 100644 src/client/app/desktop/views/home/user/user.home.vue delete mode 100644 src/client/app/desktop/views/home/user/user.vue delete mode 100644 src/client/app/desktop/views/pages/user-following-or-followers.vue delete mode 100644 src/client/app/mobile/views/components/users-list.vue delete mode 100644 src/client/app/mobile/views/pages/followers.vue delete mode 100644 src/client/app/mobile/views/pages/following.vue delete mode 100644 src/client/app/mobile/views/pages/user.vue create mode 100644 src/client/app/mobile/views/pages/user/index.vue (limited to 'src') diff --git a/src/client/app/common/views/components/user-list.vue b/src/client/app/common/views/components/user-list.vue index 9fcb80f8ad..5d851002d2 100644 --- a/src/client/app/common/views/components/user-list.vue +++ b/src/client/app/common/views/components/user-list.vue @@ -12,7 +12,7 @@

@{{ user | acct }}

-
+
@@ -137,5 +137,6 @@ export default Vue.extend({ overflow hidden text-overflow ellipsis opacity 0.7 + font-size 14px diff --git a/src/client/app/common/views/pages/followers.vue b/src/client/app/common/views/pages/followers.vue new file mode 100644 index 0000000000..94d9c9b13c --- /dev/null +++ b/src/client/app/common/views/pages/followers.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/client/app/common/views/pages/following.vue b/src/client/app/common/views/pages/following.vue new file mode 100644 index 0000000000..39739fa3da --- /dev/null +++ b/src/client/app/common/views/pages/following.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts index 1ec7de0cc5..4c5b29d1f4 100644 --- a/src/client/app/desktop/script.ts +++ b/src/client/app/desktop/script.ts @@ -130,7 +130,11 @@ init(async (launch, os) => { routes: [ os.store.getters.isSignedIn && os.store.state.device.deckMode ? { path: '/', name: 'index', component: MkDeck, children: [ - { path: '/@:user', name: 'user', component: () => import('./views/deck/deck.user-column.vue').then(m => m.default) }, + { path: '/@:user', name: 'user', component: () => import('./views/deck/deck.user-column.vue').then(m => m.default), children: [ + { path: '', name: 'user', component: () => import('./views/deck/deck.user-column.home.vue').then(m => m.default) }, + { path: 'following', component: () => import('../common/views/pages/following.vue').then(m => m.default) }, + { path: 'followers', component: () => import('../common/views/pages/followers.vue').then(m => m.default) }, + ]}, { path: '/notes/:note', name: 'note', component: () => import('./views/deck/deck.note-column.vue').then(m => m.default) }, { path: '/search', component: () => import('./views/deck/deck.search-column.vue').then(m => m.default) }, { path: '/tags/:tag', name: 'tag', component: () => import('./views/deck/deck.hashtag-column.vue').then(m => m.default) }, @@ -140,13 +144,17 @@ init(async (launch, os) => { ]} : { path: '/', component: MkHome, children: [ { path: '', name: 'index', component: MkHomeTimeline }, - { path: '/@:user', name: 'user', component: () => import('./views/home/user/user.vue').then(m => m.default) }, + { path: '/@:user', component: () => import('./views/home/user/index.vue').then(m => m.default), children: [ + { path: '', name: 'user', component: () => import('./views/home/user/user.home.vue').then(m => m.default) }, + { path: 'following', component: () => import('../common/views/pages/following.vue').then(m => m.default) }, + { path: 'followers', component: () => import('../common/views/pages/followers.vue').then(m => m.default) }, + ]}, { path: '/notes/:note', name: 'note', component: () => import('./views/home/note.vue').then(m => m.default) }, { path: '/search', component: () => import('./views/home/search.vue').then(m => m.default) }, { path: '/tags/:tag', name: 'tag', component: () => import('./views/home/tag.vue').then(m => m.default) }, { path: '/featured', component: () => import('./views/home/featured.vue').then(m => m.default) }, { path: '/explore', component: () => import('../common/views/pages/explore.vue').then(m => m.default) }, - { path: '/i/favorites', component: () => import('./views/home/favorites.vue').then(m => m.default) } + { path: '/i/favorites', component: () => import('./views/home/favorites.vue').then(m => m.default) }, ]}, { path: '/i/messaging/:user', component: MkMessagingRoom }, { path: '/i/drive', component: MkDrive }, @@ -155,8 +163,6 @@ init(async (launch, os) => { { path: '/selectdrive', component: MkSelectDrive }, { path: '/share', component: MkShare }, { path: '/games/reversi/:game?', component: MkReversi }, - { path: '/@:user/following', name: 'userFollowing', component: MkUserFollowingOrFollowers }, - { path: '/@:user/followers', name: 'userFollowers', component: MkUserFollowingOrFollowers }, { path: '/authorize-follow', component: MkFollow }, { path: '/deck', redirect: '/' }, { path: '*', component: MkNotFound } diff --git a/src/client/app/desktop/views/deck/deck.user-column.home.vue b/src/client/app/desktop/views/deck/deck.user-column.home.vue new file mode 100644 index 0000000000..966c5bdb1b --- /dev/null +++ b/src/client/app/desktop/views/deck/deck.user-column.home.vue @@ -0,0 +1,244 @@ + + + + + diff --git a/src/client/app/desktop/views/deck/deck.user-column.vue b/src/client/app/desktop/views/deck/deck.user-column.vue index 16a7aa5b35..d6618c5716 100644 --- a/src/client/app/desktop/views/deck/deck.user-column.vue +++ b/src/client/app/desktop/views/deck/deck.user-column.vue @@ -39,8 +39,10 @@
- {{ user.notesCount | number }} - {{ $t('posts') }} + + {{ user.notesCount | number }} + {{ $t('posts') }} +
@@ -56,35 +58,7 @@
- - {{ $t('pinned-notes') }} -
- -
-
- - {{ $t('images') }} -
- -
-
- - {{ $t('activity') }} -
-
-
-
- - {{ $t('timeline') }} -
- -
-
+ @@ -94,30 +68,18 @@ import Vue from 'vue'; import i18n from '../../../i18n'; import parseAcct from '../../../../../misc/acct/parse'; import XColumn from './deck.column.vue'; -import XNotes from './deck.notes.vue'; -import XNote from '../components/note.vue'; import XUserMenu from '../../../common/views/components/user-menu.vue'; -import { concat } from '../../../../../prelude/array'; -import ApexCharts from 'apexcharts'; - -const fetchLimit = 10; export default Vue.extend({ i18n: i18n('deck/deck.user-column.vue'), components: { XColumn, - XNotes, - XNote }, data() { return { user: null, fetching: true, - existMore: false, - moreFetching: false, - withFiles: false, - images: [], }; }, @@ -146,160 +108,9 @@ export default Vue.extend({ this.$root.api('users/show', parseAcct(this.$route.params.user)).then(user => { this.user = user; this.fetching = false; - - this.$nextTick(() => { - (this.$refs.timeline as any).init(() => this.initTl()); - }); - - const image = [ - 'image/jpeg', - 'image/png', - 'image/gif' - ]; - - this.$root.api('users/notes', { - userId: this.user.id, - fileType: image, - excludeNsfw: !this.$store.state.device.alwaysShowNsfw, - limit: 9, - untilDate: new Date().getTime() + 1000 * 86400 * 365 - }).then(notes => { - for (const note of notes) { - for (const file of note.files) { - file._note = note; - } - } - const files = concat(notes.map((n: any): any[] => n.files)); - this.images = files.filter(f => image.includes(f.type)).slice(0, 9); - }); - - this.$root.api('charts/user/notes', { - userId: this.user.id, - span: 'day', - limit: 21 - }).then(stats => { - const normal = []; - const reply = []; - const renote = []; - - const now = new Date(); - const y = now.getFullYear(); - const m = now.getMonth(); - const d = now.getDate(); - - for (let i = 0; i < 21; i++) { - const x = new Date(y, m, d - i); - normal.push([ - x, - stats.diffs.normal[i] - ]); - reply.push([ - x, - stats.diffs.reply[i] - ]); - renote.push([ - x, - stats.diffs.renote[i] - ]); - } - - const chart = new ApexCharts(this.$refs.chart, { - chart: { - type: 'bar', - stacked: true, - height: 100, - sparkline: { - enabled: true - }, - }, - plotOptions: { - bar: { - columnWidth: '90%' - } - }, - grid: { - clipMarkers: false, - padding: { - top: 16, - right: 16, - bottom: 16, - left: 16 - } - }, - tooltip: { - shared: true, - intersect: false - }, - series: [{ - name: 'Normal', - data: normal - }, { - name: 'Reply', - data: reply - }, { - name: 'Renote', - data: renote - }], - xaxis: { - type: 'datetime', - crosshairs: { - width: 1, - opacity: 1 - } - } - }); - - chart.render(); - }); - }); - }, - - initTl() { - return new Promise((res, rej) => { - this.$root.api('users/notes', { - userId: this.user.id, - limit: fetchLimit + 1, - untilDate: new Date().getTime() + 1000 * 86400 * 365, - withFiles: this.withFiles, - includeMyRenotes: this.$store.state.settings.showMyRenotes, - includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes, - includeLocalRenotes: this.$store.state.settings.showLocalRenotes - }).then(notes => { - if (notes.length == fetchLimit + 1) { - notes.pop(); - this.existMore = true; - } - res(notes); - }, rej); }); }, - fetchMoreNotes() { - this.moreFetching = true; - - const promise = this.$root.api('users/notes', { - userId: this.user.id, - limit: fetchLimit + 1, - untilDate: new Date((this.$refs.timeline as any).tail().createdAt).getTime(), - withFiles: this.withFiles, - includeMyRenotes: this.$store.state.settings.showMyRenotes, - includeRenotedMyNotes: this.$store.state.settings.showRenotedMyNotes, - includeLocalRenotes: this.$store.state.settings.showLocalRenotes - }); - - promise.then(notes => { - if (notes.length == fetchLimit + 1) { - notes.pop(); - } else { - this.existMore = false; - } - for (const n of notes) (this.$refs.timeline as any).append(n); - this.moreFetching = false; - }); - - return promise; - }, - menu() { this.$root.new(XUserMenu, { source: this.$refs.menu, @@ -439,34 +250,13 @@ export default Vue.extend({ > a color var(--text) - >>> b - display block - font-size 110% - - >>> span - display block - font-size 80% - opacity 0.7 + > b + display block + font-size 110% - .sainvnaq - display grid - grid-template-columns 1fr 1fr 1fr - gap 8px - padding 16px - - > * - height 70px - background-position center center - background-size cover - background-clip content-box - border-radius 4px - - > .activity - > div - background var(--face) - - > .tl - > div - background var(--face) + > span + display block + font-size 80% + opacity 0.7 diff --git a/src/client/app/desktop/views/home/user/index.vue b/src/client/app/desktop/views/home/user/index.vue new file mode 100644 index 0000000000..24abeadd6a --- /dev/null +++ b/src/client/app/desktop/views/home/user/index.vue @@ -0,0 +1,82 @@ + + + + + diff --git a/src/client/app/desktop/views/home/user/user.header.vue b/src/client/app/desktop/views/home/user/user.header.vue index 05d3674996..debfb24393 100644 --- a/src/client/app/desktop/views/home/user/user.header.vue +++ b/src/client/app/desktop/views/home/user/user.header.vue @@ -40,7 +40,7 @@ {{ user.profile.birthday.replace('-', $t('year')).replace('-', $t('month')) + $t('day') }} ({{ $t('years-old', { age }) }})
- {{ user.notesCount | number }}{{ $t('posts') }} + {{ user.notesCount | number }}{{ $t('posts') }} {{ user.followingCount | number }}{{ $t('following') }} {{ user.followersCount | number }}{{ $t('followers') }}
diff --git a/src/client/app/desktop/views/home/user/user.home.vue b/src/client/app/desktop/views/home/user/user.home.vue new file mode 100644 index 0000000000..b4426ac755 --- /dev/null +++ b/src/client/app/desktop/views/home/user/user.home.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/src/client/app/desktop/views/home/user/user.vue b/src/client/app/desktop/views/home/user/user.vue deleted file mode 100644 index 6a827f4beb..0000000000 --- a/src/client/app/desktop/views/home/user/user.vue +++ /dev/null @@ -1,109 +0,0 @@ - - - - - diff --git a/src/client/app/desktop/views/pages/user-following-or-followers.vue b/src/client/app/desktop/views/pages/user-following-or-followers.vue deleted file mode 100644 index fd842cbcd4..0000000000 --- a/src/client/app/desktop/views/pages/user-following-or-followers.vue +++ /dev/null @@ -1,120 +0,0 @@ - - - - - diff --git a/src/client/app/mobile/script.ts b/src/client/app/mobile/script.ts index 1feff3d5eb..ad37ba70ab 100644 --- a/src/client/app/mobile/script.ts +++ b/src/client/app/mobile/script.ts @@ -21,8 +21,6 @@ import MkMessagingRoom from './views/pages/messaging-room.vue'; import MkReceivedFollowRequests from './views/pages/received-follow-requests.vue'; import MkNote from './views/pages/note.vue'; import MkSearch from './views/pages/search.vue'; -import MkFollowers from './views/pages/followers.vue'; -import MkFollowing from './views/pages/following.vue'; import MkFavorites from './views/pages/favorites.vue'; import MkUserLists from './views/pages/user-lists.vue'; import MkUserList from './views/pages/user-list.vue'; @@ -137,9 +135,11 @@ init((launch) => { { path: '/explore', name: 'explore', component: () => import('./views/pages/explore.vue').then(m => m.default) }, { path: '/share', component: MkShare }, { path: '/games/reversi/:game?', name: 'reversi', component: MkReversi }, - { path: '/@:user', component: () => import('./views/pages/user.vue').then(m => m.default) }, - { path: '/@:user/followers', component: MkFollowers }, - { path: '/@:user/following', component: MkFollowing }, + { path: '/@:user', component: () => import('./views/pages/user/index.vue').then(m => m.default), children: [ + { path: '', name: 'user', component: () => import('./views/pages/user/home.vue').then(m => m.default) }, + { path: 'following', component: () => import('../common/views/pages/following.vue').then(m => m.default) }, + { path: 'followers', component: () => import('../common/views/pages/followers.vue').then(m => m.default) }, + ]}, { path: '/notes/:note', component: MkNote }, { path: '/authorize-follow', component: MkFollow }, { path: '*', component: MkNotFound } diff --git a/src/client/app/mobile/views/components/index.ts b/src/client/app/mobile/views/components/index.ts index 94bc8d23fd..864098640b 100644 --- a/src/client/app/mobile/views/components/index.ts +++ b/src/client/app/mobile/views/components/index.ts @@ -13,7 +13,6 @@ import friendsMaker from './friends-maker.vue'; import notification from './notification.vue'; import notifications from './notifications.vue'; import notificationPreview from './notification-preview.vue'; -import usersList from './users-list.vue'; import userPreview from './user-preview.vue'; import userTimeline from './user-timeline.vue'; import userListTimeline from './user-list-timeline.vue'; @@ -33,7 +32,6 @@ Vue.component('mk-friends-maker', friendsMaker); Vue.component('mk-notification', notification); Vue.component('mk-notifications', notifications); Vue.component('mk-notification-preview', notificationPreview); -Vue.component('mk-users-list', usersList); Vue.component('mk-user-preview', userPreview); Vue.component('mk-user-timeline', userTimeline); Vue.component('mk-user-list-timeline', userListTimeline); diff --git a/src/client/app/mobile/views/components/users-list.vue b/src/client/app/mobile/views/components/users-list.vue deleted file mode 100644 index 0c5c934dcf..0000000000 --- a/src/client/app/mobile/views/components/users-list.vue +++ /dev/null @@ -1,135 +0,0 @@ - - - - - diff --git a/src/client/app/mobile/views/pages/followers.vue b/src/client/app/mobile/views/pages/followers.vue deleted file mode 100644 index f5ac8ef195..0000000000 --- a/src/client/app/mobile/views/pages/followers.vue +++ /dev/null @@ -1,70 +0,0 @@ - - - diff --git a/src/client/app/mobile/views/pages/following.vue b/src/client/app/mobile/views/pages/following.vue deleted file mode 100644 index d603532498..0000000000 --- a/src/client/app/mobile/views/pages/following.vue +++ /dev/null @@ -1,69 +0,0 @@ - - - diff --git a/src/client/app/mobile/views/pages/user.vue b/src/client/app/mobile/views/pages/user.vue deleted file mode 100644 index 5d15a9718a..0000000000 --- a/src/client/app/mobile/views/pages/user.vue +++ /dev/null @@ -1,347 +0,0 @@ - - - - - diff --git a/src/client/app/mobile/views/pages/user/index.vue b/src/client/app/mobile/views/pages/user/index.vue new file mode 100644 index 0000000000..48b65624ef --- /dev/null +++ b/src/client/app/mobile/views/pages/user/index.vue @@ -0,0 +1,350 @@ + + + + + diff --git a/src/server/api/endpoints/users/followers.ts b/src/server/api/endpoints/users/followers.ts index 2a39da4064..2f7f1af6a5 100644 --- a/src/server/api/endpoints/users/followers.ts +++ b/src/server/api/endpoints/users/followers.ts @@ -16,7 +16,7 @@ export const meta = { params: { userId: { - validator: $.type(ID), + validator: $.optional.type(ID), transform: transform, desc: { 'ja-JP': '対象のユーザーのID', @@ -24,6 +24,14 @@ export const meta = { } }, + username: { + validator: $.optional.str + }, + + host: { + validator: $.optional.nullable.str + }, + limit: { validator: $.optional.num.range(1, 100), default: 10 @@ -43,14 +51,11 @@ export const meta = { }; export default define(meta, (ps, me) => new Promise(async (res, rej) => { - // Lookup user - const user = await User.findOne({ - _id: ps.userId - }, { - fields: { - _id: true - } - }); + const q: any = ps.userId != null + ? { _id: ps.userId } + : { usernameLower: ps.username.toLowerCase(), host: ps.host }; + + const user = await User.findOne(q); if (user === null) { return rej('user not found'); diff --git a/src/server/api/endpoints/users/following.ts b/src/server/api/endpoints/users/following.ts index 4ccc13f633..1485a63f24 100644 --- a/src/server/api/endpoints/users/following.ts +++ b/src/server/api/endpoints/users/following.ts @@ -16,7 +16,7 @@ export const meta = { params: { userId: { - validator: $.type(ID), + validator: $.optional.type(ID), transform: transform, desc: { 'ja-JP': '対象のユーザーのID', @@ -24,6 +24,14 @@ export const meta = { } }, + username: { + validator: $.optional.str + }, + + host: { + validator: $.optional.nullable.str + }, + limit: { validator: $.optional.num.range(1, 100), default: 10 @@ -43,14 +51,11 @@ export const meta = { }; export default define(meta, (ps, me) => new Promise(async (res, rej) => { - // Lookup user - const user = await User.findOne({ - _id: ps.userId - }, { - fields: { - _id: true - } - }); + const q: any = ps.userId != null + ? { _id: ps.userId } + : { usernameLower: ps.username.toLowerCase(), host: ps.host }; + + const user = await User.findOne(q); if (user === null) { return rej('user not found'); -- cgit v1.2.3-freya