diff --git a/src/boot/routes.js b/src/boot/routes.js index 2dc900e7..84acfa8e 100644 --- a/src/boot/routes.js +++ b/src/boot/routes.js @@ -2,6 +2,7 @@ import PublicTimeline from 'components/public_timeline/public_timeline.vue' import PublicAndExternalTimeline from 'components/public_and_external_timeline/public_and_external_timeline.vue' import FriendsTimeline from 'components/friends_timeline/friends_timeline.vue' import TagTimeline from 'components/tag_timeline/tag_timeline.vue' +import BubbleTimeline from 'components/bubble_timeline/bubble_timeline.vue' import BookmarkTimeline from 'components/bookmark_timeline/bookmark_timeline.vue' import ConversationPage from 'components/conversation-page/conversation-page.vue' import Interactions from 'components/interactions/interactions.vue' @@ -47,6 +48,7 @@ export default (store) => { }, { name: 'public-external-timeline', path: '/main/all', component: PublicAndExternalTimeline }, { name: 'public-timeline', path: '/main/public', component: PublicTimeline }, + { name: 'bubble-timeline', path: '/main/bubble', component: BubbleTimeline }, { name: 'friends', path: '/main/friends', component: FriendsTimeline, beforeEnter: validateAuthenticatedRoute }, { name: 'tag-timeline', path: '/tag/:tag', component: TagTimeline }, { name: 'bookmarks', path: '/bookmarks', component: BookmarkTimeline }, diff --git a/src/components/bubble_timeline/bubble_timeline.js b/src/components/bubble_timeline/bubble_timeline.js new file mode 100644 index 00000000..514f8a59 --- /dev/null +++ b/src/components/bubble_timeline/bubble_timeline.js @@ -0,0 +1,18 @@ +import Timeline from '../timeline/timeline.vue' +const PublicTimeline = { + components: { + Timeline + }, + computed: { + timeline () { return this.$store.state.statuses.timelines.bubble } + }, + created () { + this.$store.dispatch('startFetchingTimeline', { timeline: 'bubble' }) + }, + unmounted () { + this.$store.dispatch('stopFetchingTimeline', 'bubble') + } + +} + +export default PublicTimeline diff --git a/src/components/bubble_timeline/bubble_timeline.vue b/src/components/bubble_timeline/bubble_timeline.vue new file mode 100644 index 00000000..27e6ba32 --- /dev/null +++ b/src/components/bubble_timeline/bubble_timeline.vue @@ -0,0 +1,9 @@ + + + diff --git a/src/components/nav_panel/nav_panel.js b/src/components/nav_panel/nav_panel.js index fd65509a..5eba981d 100644 --- a/src/components/nav_panel/nav_panel.js +++ b/src/components/nav_panel/nav_panel.js @@ -19,7 +19,8 @@ import { faInfoCircle, faStream, faList, - faBullhorn + faBullhorn, + faCircle } from '@fortawesome/free-solid-svg-icons' library.add( @@ -34,7 +35,8 @@ library.add( faInfoCircle, faStream, faList, - faBullhorn + faBullhorn, + faCircle ) const NavPanel = { props: ['forceExpand', 'forceEditMode'], diff --git a/src/components/navigation/navigation.js b/src/components/navigation/navigation.js index 7f096316..b4434edc 100644 --- a/src/components/navigation/navigation.js +++ b/src/components/navigation/navigation.js @@ -22,6 +22,13 @@ export const TIMELINES = { label: 'nav.public_tl', criteria: ['!private'] }, + bubble: { + route: 'bubble-timeline', + anon: true, + icon: 'circle', + label: 'nav.bubble_timeline', + criteria: ['!private', 'federating'] + }, twkn: { route: 'public-external-timeline', anon: true, diff --git a/src/components/navigation/navigation_pins.js b/src/components/navigation/navigation_pins.js index 9dd795aa..76fcd57b 100644 --- a/src/components/navigation/navigation_pins.js +++ b/src/components/navigation/navigation_pins.js @@ -58,6 +58,7 @@ const NavPanel = { if (!this.currentUser) { return filterNavigation([ { ...TIMELINES.public, name: 'public' }, + { ...TIMELINES.bubble, name: 'bubble' }, { ...TIMELINES.twkn, name: 'twkn' }, { ...ROOT_ITEMS.about, name: 'about' } ], diff --git a/src/components/timeline_menu/timeline_menu.js b/src/components/timeline_menu/timeline_menu.js index 5a2a86c2..00ed9c23 100644 --- a/src/components/timeline_menu/timeline_menu.js +++ b/src/components/timeline_menu/timeline_menu.js @@ -19,7 +19,8 @@ export const timelineNames = () => { bookmarks: 'nav.bookmarks', dms: 'nav.dms', 'public-timeline': 'nav.public_tl', - 'public-external-timeline': 'nav.twkn' + 'public-external-timeline': 'nav.twkn', + 'bubble-timeline': 'nav.bubble_timeline' } } diff --git a/src/components/timeline_menu/timeline_menu.vue b/src/components/timeline_menu/timeline_menu.vue index 5f1da1f7..ead4b1a5 100644 --- a/src/components/timeline_menu/timeline_menu.vue +++ b/src/components/timeline_menu/timeline_menu.vue @@ -66,6 +66,7 @@ padding: 0 0.65em; height: 3.5em; line-height: 3.5em; + padding-bottom: 0; &:hover { background-color: $fallback--lightBg; diff --git a/src/i18n/en.json b/src/i18n/en.json index 5eef37b1..759eaaac 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -170,9 +170,14 @@ "interactions": "Interactions", "dms": "Direct messages", "public_tl": "Public timeline", + "public_timeline_description": "Public posts from this instance", "timeline": "Timeline", "home_timeline": "Home timeline", + "home_timeline_description": "Posts from people you follow", + "bubble_timeline": "Bubble timeline", + "bubble_timeline_description": "Posts from instances close to yours, as recommended by the admin(s)", "twkn": "Known Network", + "twkn_timeline_description": "Posts from the entire network", "bookmarks": "Bookmarks", "user_search": "User Search", "search": "Search", diff --git a/src/i18n/ja_pedantic.json b/src/i18n/ja_pedantic.json index fddf24db..496bf7ac 100644 --- a/src/i18n/ja_pedantic.json +++ b/src/i18n/ja_pedantic.json @@ -90,8 +90,12 @@ "interactions": "インタラクション", "dms": "ダイレクトメッセージ", "public_tl": "公開タイムライン", + "public_timeline_description": "このインスタンスからの公開投稿", "timeline": "タイムライン", "twkn": "すべてのネットワーク", + "twkn_timeline_description": "全連合からの投稿", + "bubble_timeline": "バブルタイムライン", + "bubble_timeline_description": "管理者がおすすめしているインスタンスからの投稿", "user_search": "ユーザーを探す", "search": "検索", "who_to_follow": "おすすめユーザー", @@ -100,7 +104,9 @@ "bookmarks": "ブックマーク", "timelines": "タイムライン", "chats": "チャット", - "home_timeline": "ホームタイムライン" + "home_timeline": "ホームタイムライン", + "home_timeline_description": "フォローしているユーザーからの投稿", + "announcements": "お知らせ" }, "notifications": { "broken_favorite": "ステータスが見つかりません。探しています…", diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 9230be12..381c3218 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -63,7 +63,8 @@ export const defaultState = () => ({ tag: emptyTl(), dms: emptyTl(), bookmarks: emptyTl(), - list: emptyTl() + list: emptyTl(), + bubble: emptyTl() } }) diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index 857ab24d..c9704b5b 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -47,6 +47,7 @@ const MASTODON_DENY_USER_URL = id => `/api/v1/follow_requests/${id}/reject` const MASTODON_DIRECT_MESSAGES_TIMELINE_URL = '/api/v1/timelines/direct' const MASTODON_PUBLIC_TIMELINE = '/api/v1/timelines/public' const MASTODON_USER_HOME_TIMELINE_URL = '/api/v1/timelines/home' +const AKKOMA_BUBBLE_TIMELINE_URL = '/api/v1/timelines/bubble' const MASTODON_STATUS_URL = id => `/api/v1/statuses/${id}` const MASTODON_STATUS_CONTEXT_URL = id => `/api/v1/statuses/${id}/context` const MASTODON_STATUS_SOURCE_URL = id => `/api/v1/statuses/${id}/source` @@ -675,6 +676,7 @@ const fetchTimeline = ({ }) => { const timelineUrls = { public: MASTODON_PUBLIC_TIMELINE, + bubble: AKKOMA_BUBBLE_TIMELINE_URL, friends: MASTODON_USER_HOME_TIMELINE_URL, dms: MASTODON_DIRECT_MESSAGES_TIMELINE_URL, notifications: MASTODON_USER_NOTIFICATIONS_URL, @@ -1488,7 +1490,15 @@ export const ProcessedWS = ({ } socket.addEventListener('open', (wsEvent) => { console.debug(`[WS][${id}] Socket connected`, wsEvent) + setInterval(() => { + try { + socket.send('ping') + } catch (e) { + clearInterval(this) + } + }, 30000) }) + socket.addEventListener('error', (wsEvent) => { console.debug(`[WS][${id}] Socket errored`, wsEvent) })