From 622dbde258dcb01ba1e7fe5879880898c18ff193 Mon Sep 17 00:00:00 2001 From: Steve Genoud Date: Tue, 2 Apr 2019 12:05:27 +0200 Subject: [PATCH] feat: Adds a basic conversations timeline (#1137) fixes #639 --- src/routes/_actions/streaming.js | 15 ++++++++- src/routes/_api/TimelineStream.js | 2 ++ src/routes/_api/timelines.js | 7 +++- src/routes/_components/NavShortcuts.html | 1 + src/routes/_components/ShortcutHelpInfo.html | 1 + src/routes/_components/status/Status.html | 5 --- src/routes/_pages/community/index.html | 5 +++ src/routes/_pages/conversations.html | 32 +++++++++++++++++++ .../_store/computations/navComputations.js | 7 ++++ .../_store/observers/timelineObservers.js | 1 + src/routes/conversations.html | 20 ++++++++++++ 11 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 src/routes/_pages/conversations.html create mode 100644 src/routes/conversations.html diff --git a/src/routes/_actions/streaming.js b/src/routes/_actions/streaming.js index 72b9f26..3bd6f29 100644 --- a/src/routes/_actions/streaming.js +++ b/src/routes/_actions/streaming.js @@ -16,6 +16,14 @@ function processMessage (instanceName, timelineName, message) { case 'notification': addStatusOrNotification(instanceName, 'notifications', JSON.parse(payload)) break + case 'conversation': + // This is a hack in order to mostly fit the conversation model into + // a timeline of statuses. To have a clean implementation we would need to + // reproduce what is done for statuses for the conversation. + // + // It will add new DMs as new conversations intead of updating existing threads + addStatusOrNotification(instanceName, timelineName, JSON.parse(payload).last_status) + break } stop('processMessage') } @@ -24,7 +32,12 @@ export function createStream (streamingApi, instanceName, accessToken, timelineName, onOpenStream) { return new TimelineStream(streamingApi, accessToken, timelineName, { onMessage (msg) { - if (msg.event !== 'update' && msg.event !== 'delete' && msg.event !== 'notification') { + if ( + msg.event !== 'update' && + msg.event !== 'delete' && + msg.event !== 'notification' && + msg.event !== 'conversation' + ) { console.error("don't know how to handle event", msg) return } diff --git a/src/routes/_api/TimelineStream.js b/src/routes/_api/TimelineStream.js index 4c6e73d..1baef00 100644 --- a/src/routes/_api/TimelineStream.js +++ b/src/routes/_api/TimelineStream.js @@ -12,6 +12,8 @@ function getStreamName (timeline) { return 'user' case 'notifications': return 'user:notification' + case 'conversations': + return 'direct' } if (timeline.startsWith('tag/')) { return 'hashtag' diff --git a/src/routes/_api/timelines.js b/src/routes/_api/timelines.js index 7fc1c72..25e9f5c 100644 --- a/src/routes/_api/timelines.js +++ b/src/routes/_api/timelines.js @@ -12,6 +12,8 @@ function getTimelineUrlPath (timeline) { return 'notifications' case 'favorites': return 'favourites' + case 'conversations': + return 'conversations' } if (timeline.startsWith('tag/')) { return 'timelines/tag' @@ -61,5 +63,8 @@ export function getTimeline (instanceName, accessToken, timeline, maxId, since, url += '?' + paramsString(params) - return get(url, auth(accessToken), { timeout: DEFAULT_TIMEOUT }) + const timelineRequest = get(url, auth(accessToken), { timeout: DEFAULT_TIMEOUT }) + + if (timeline !== 'conversations') return timelineRequest + return timelineRequest.then(items => items.map(item => item.last_status)) } diff --git a/src/routes/_components/NavShortcuts.html b/src/routes/_components/NavShortcuts.html index a2aed5b..edbeb59 100644 --- a/src/routes/_components/NavShortcuts.html +++ b/src/routes/_components/NavShortcuts.html @@ -4,6 +4,7 @@ + diff --git a/src/routes/_components/ShortcutHelpInfo.html b/src/routes/_components/ShortcutHelpInfo.html index c939e92..39abc9e 100644 --- a/src/routes/_components/ShortcutHelpInfo.html +++ b/src/routes/_components/ShortcutHelpInfo.html @@ -13,6 +13,7 @@
  • g + l to go to the local timeline
  • g + t to go to the federated timeline
  • g + c to go to the community page
  • +
  • g + d to go to the conversations page
  • h or ? to toggle the help dialog
  • Backspace to go back, close dialogs
  • diff --git a/src/routes/_components/status/Status.html b/src/routes/_components/status/Status.html index 03c155d..ef40955 100644 --- a/src/routes/_components/status/Status.html +++ b/src/routes/_components/status/Status.html @@ -73,10 +73,6 @@ border-bottom: 1px solid var(--main-border); } - .status-article.status-direct { - background-color: var(--status-direct-background); - } - .status-article:focus { outline: none; /* focus is on the parent instead */ } @@ -288,7 +284,6 @@ className: ({ visibility, timelineType, isStatusInOwnThread, $underlineLinks, $disableTapOnStatus }) => (classname( 'status-article', 'shortcut-list-item', - visibility === 'direct' && 'status-direct', timelineType !== 'search' && 'status-in-timeline', isStatusInOwnThread && 'status-in-own-thread', $underlineLinks && 'underline-links', diff --git a/src/routes/_pages/community/index.html b/src/routes/_pages/community/index.html index a2bf9cf..565e4be 100644 --- a/src/routes/_pages/community/index.html +++ b/src/routes/_pages/community/index.html @@ -21,6 +21,11 @@ icon="#fa-star" pinnable="true" /> + {#if $lists.length} diff --git a/src/routes/_pages/conversations.html b/src/routes/_pages/conversations.html new file mode 100644 index 0000000..a1d801d --- /dev/null +++ b/src/routes/_pages/conversations.html @@ -0,0 +1,32 @@ +{#if $isUserLoggedIn} + + {#if $pinnedPage !== '/conversations'} + + {/if} + +{:else} + + +

    Conversations

    + +

    Your conversations will appear here when logged in.

    +
    +
    +{/if} + diff --git a/src/routes/_store/computations/navComputations.js b/src/routes/_store/computations/navComputations.js index e1f249c..8cdf608 100644 --- a/src/routes/_store/computations/navComputations.js +++ b/src/routes/_store/computations/navComputations.js @@ -24,6 +24,13 @@ export function navComputations (store) { svg: '#fa-globe', label: 'Federated' } + } else if (pinnedPage === '/conversations') { + pinnedPageObject = { + name: 'conversations', + href: '/conversations', + svg: '#fa-envelope', + label: 'Conversations' + } } else if (pinnedPage === '/favorites') { pinnedPageObject = { name: 'favorites', diff --git a/src/routes/_store/observers/timelineObservers.js b/src/routes/_store/observers/timelineObservers.js index 69e7755..08da923 100644 --- a/src/routes/_store/observers/timelineObservers.js +++ b/src/routes/_store/observers/timelineObservers.js @@ -26,6 +26,7 @@ export function timelineObservers () { !( timeline !== 'local' && timeline !== 'federated' && + timeline !== 'conversations' && !timeline.startsWith('list/') && !timeline.startsWith('tag/') ) diff --git a/src/routes/conversations.html b/src/routes/conversations.html new file mode 100644 index 0000000..b9ca42b --- /dev/null +++ b/src/routes/conversations.html @@ -0,0 +1,20 @@ + + + <LazyPage {pageComponent} {params} /> + +<script> + import Title from './_components/Title.html' + import LazyPage from './_components/LazyPage.html' + import pageComponent from './_pages/conversations.html' + + export default { + components: { + + Title, + LazyPage + }, + data: () => ({ + pageComponent + }) + } +</script>