integrate conversations in DMs

This commit is contained in:
Nicolas Constant 2019-08-02 20:56:52 -04:00
parent ba1d965c2f
commit 97808aacd1
No known key found for this signature in database
GPG Key ID: 1E9F677FB01A5688
6 changed files with 108 additions and 21 deletions

View File

@ -1,3 +1,23 @@
<p>
direct-messages works!
</p>
<div class="stream-toots flexcroll" #statusstream (scroll)="onScroll()">
<div class="stream-toots__remove-cw" *ngIf="isThread && hasContentWarnings">
<button class="stream-toots__remove-cw--button" (click)="removeCw()" title="remove content warnings">Remove
CWs</button>
</div>
<div *ngIf="displayError" class="stream-toots__error">{{displayError}}</div>
<!-- data-simplebar -->
<div class="stream-toots__status" *ngFor="let conversationWrapper of conversations">
<div class="conversation__participants" title="participants">
<fa-icon [icon]="faUserFriends" class="conversation__icon"></fa-icon>
<img class="conversation__avatar" src="{{ conversationWrapper.userAvatar }}" title="me" />
<div *ngFor="let acc of conversationWrapper.conversation.accounts">
<img class="conversation__avatar" src="{{ acc.avatar }}" title="{{ acc.acct }}" />
</div>
</div>
<app-status [statusWrapper]="conversationWrapper.lastStatus" [isThreadDisplay]="isThread"
(browseAccountEvent)="browseAccount($event)" (browseHashtagEvent)="browseHashtag($event)"
(browseThreadEvent)="browseThread($event)"></app-status>
</div>
<app-waiting-animation *ngIf="isLoading" class="waiting-icon"></app-waiting-animation>
</div>

View File

@ -0,0 +1,31 @@
.conversation {
&__participants {
padding: 10px 0 0 10px;
height: 40px;
}
&__icon {
display: block;
margin-right: 10px;
margin-left: 31px;
padding-top: 3px;
float: left;
color: #5098eb;
}
&__avatar {
width: 30px;
height: 30px;
border-radius: 2px;
margin-right: 5px;
float: left;
}
}
.stream-toots__status {
&:not(:last-child) {
border-bottom: 1px solid #4e5572;
border-bottom: 1px solid #2f3444;
border-bottom: 1px solid #232733;
}
}

View File

@ -1,4 +1,5 @@
import { Component, OnInit, Input, Output, EventEmitter, ViewChild, ElementRef } from '@angular/core';
import { faUserFriends } from "@fortawesome/free-solid-svg-icons";
import { AccountWrapper } from '../../../../models/account.models';
import { OpenThreadEvent } from '../../../../services/tools.service';
@ -6,15 +7,18 @@ import { StatusWrapper } from '../../../../models/common.model';
import { NotificationService } from '../../../../services/notification.service';
import { MastodonService } from '../../../../services/mastodon.service';
import { StreamTypeEnum } from '../../../../states/streams.state';
import { Status } from '../../../../services/models/mastodon.interfaces';
import { Status, Conversation } from '../../../../services/models/mastodon.interfaces';
import { AccountInfo } from '../../../../states/accounts.state';
@Component({
selector: 'app-direct-messages',
templateUrl: '../../../stream/stream-statuses/stream-statuses.component.html',
templateUrl: './direct-messages.component.html',
styleUrls: ['../../../stream/stream-statuses/stream-statuses.component.scss', './direct-messages.component.scss']
})
export class DirectMessagesComponent implements OnInit {
statuses: StatusWrapper[] = [];
faUserFriends = faUserFriends;
conversations: ConversationWrapper[] = [];
displayError: string;
isLoading = true;
isThread = false;
@ -47,19 +51,18 @@ export class DirectMessagesComponent implements OnInit {
private reset() {
this.isLoading = true;
this.statuses.length = 0;
this.conversations.length = 0;
this.maxReached = false;
}
private getDirectMessages() {
this.reset();
this.mastodonService.getTimeline(this.account.info, StreamTypeEnum.directmessages)
.then((statuses: Status[]) => {
//this.maxId = statuses[statuses.length - 1].id;
for (const s of statuses) {
const wrapper = new StatusWrapper(s, this.account.info);
this.statuses.push(wrapper);
this.mastodonService.getConversations(this.account.info)
.then((conversations: Conversation[]) => {
for (const c of conversations) {
const wrapper = new ConversationWrapper(c, this.account.info, this.account.avatar);
this.conversations.push(wrapper);
}
})
.catch(err => {
@ -82,18 +85,18 @@ export class DirectMessagesComponent implements OnInit {
private scrolledToBottom() {
if (this.isLoading || this.maxReached) return;
const maxId = this.statuses[this.statuses.length - 1].status.id;
const maxId = this.conversations[this.conversations.length - 1].conversation.id;
this.isLoading = true;
this.mastodonService.getTimeline(this.account.info, StreamTypeEnum.directmessages, maxId)
.then((statuses: Status[]) => {
if (statuses.length === 0) {
this.mastodonService.getConversations(this.account.info, maxId)
.then((conversations: Conversation[]) => {
if (conversations.length === 0) {
this.maxReached = true;
return;
}
for (const s of statuses) {
const wrapper = new StatusWrapper(s, this.account.info);
this.statuses.push(wrapper);
for (const c of conversations) {
const wrapper = new ConversationWrapper(c, this.account.info, this.account.avatar);
this.conversations.push(wrapper);
}
})
.catch(err => {
@ -116,3 +119,16 @@ export class DirectMessagesComponent implements OnInit {
this.browseThreadEvent.next(openThreadEvent);
}
}
class ConversationWrapper {
constructor(
public conversation: Conversation,
public provider: AccountInfo,
public userAvatar: string
) {
this.lastStatus = new StatusWrapper(conversation.last_status, provider);
}
lastStatus: StatusWrapper;
}

View File

@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
import { HttpHeaders, HttpClient, HttpResponse } from '@angular/common/http';
import { ApiRoutes } from './models/api.settings';
import { Account, Status, Results, Context, Relationship, Instance, Attachment, Notification, List, Poll, Emoji } from "./models/mastodon.interfaces";
import { Account, Status, Results, Context, Relationship, Instance, Attachment, Notification, List, Poll, Emoji, Conversation } from "./models/mastodon.interfaces";
import { AccountInfo } from '../states/accounts.state';
import { StreamTypeEnum, StreamElement } from '../states/streams.state';
@ -28,6 +28,18 @@ export class MastodonService {
return this.httpClient.get<Status[]>(route, { headers: headers }).toPromise();
}
getConversations(account: AccountInfo, max_id: string = null, since_id: string = null, min_id = null, limit: number = 20,): Promise<Conversation[]> {
let params = `?limit=${limit}`;
if (max_id) params += `&max_id=${max_id}`;
if (since_id) params += `&since_id=${since_id}`;
if (min_id) params += `&since_id=${min_id}`;
const route = `https://${account.instance}${this.apiRoutes.getConversations}${params}`;
const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` });
return this.httpClient.get<Conversation[]>(route, { headers: headers }).toPromise();
}
private getTimelineRoute(type: StreamTypeEnum, max_id: string, since_id: string, limit: number, tag: string, listId: string): string {
let route: string;
switch (type) {

View File

@ -66,4 +66,5 @@ export class ApiRoutes {
removeAccountFromList = '/api/v1/lists/{0}/accounts';
voteOnPoll = '/api/v1/polls/{0}/votes';
getPoll = '/api/v1/polls/{0}';
getConversations = '/api/v1/conversations';
}

View File

@ -193,6 +193,13 @@ export interface Status {
pleroma: PleromaStatusInfo;
}
export interface Conversation {
id: string;
accounts: Account[];
last_status: Status;
unread: boolean;
}
export interface PleromaStatusInfo {
conversation_id: number;
local: boolean;