commit
54355b5eb1
@ -1,3 +1,8 @@
|
||||
<app-media-viewer
|
||||
id="media-viewer"
|
||||
*ngIf="openedMediaEvent"
|
||||
[openedMediaEvent]="openedMediaEvent" (closeSubject)="closeMedia()"></app-media-viewer>
|
||||
|
||||
<app-left-side-bar>
|
||||
</app-left-side-bar>
|
||||
|
||||
|
@ -24,6 +24,15 @@
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#media-viewer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
z-index: 99999999;
|
||||
}
|
||||
|
||||
app-streams-selection-footer {
|
||||
position: absolute;
|
||||
height: 30px;
|
||||
|
@ -5,18 +5,23 @@ import { Select } from '@ngxs/store';
|
||||
|
||||
import { NavigationService, LeftPanelType } from './services/navigation.service';
|
||||
import { StreamElement } from './states/streams.state';
|
||||
import { OpenMediaEvent } from './models/common.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.scss']
|
||||
})
|
||||
export class AppComponent implements OnInit, OnDestroy {
|
||||
export class AppComponent implements OnInit, OnDestroy {
|
||||
title = 'Sengi';
|
||||
|
||||
floatingColumnActive: boolean;
|
||||
tutorialActive: boolean;
|
||||
// mediaViewerActive: boolean = false;
|
||||
openedMediaEvent: OpenMediaEvent
|
||||
|
||||
private columnEditorSub: Subscription;
|
||||
private openMediaSub: Subscription;
|
||||
private streamSub: Subscription;
|
||||
|
||||
@Select(state => state.streamsstatemodel.streams) streamElements$: Observable<StreamElement[]>;
|
||||
|
||||
@ -24,8 +29,8 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.streamElements$.subscribe((streams: StreamElement[]) => {
|
||||
if(streams && streams.length === 0){
|
||||
this.streamSub = this.streamElements$.subscribe((streams: StreamElement[]) => {
|
||||
if (streams && streams.length === 0) {
|
||||
this.tutorialActive = true;
|
||||
} else {
|
||||
this.tutorialActive = false;
|
||||
@ -39,10 +44,25 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
this.floatingColumnActive = true;
|
||||
}
|
||||
});
|
||||
|
||||
this.openMediaSub = this.navigationService.activatedMediaSubject.subscribe((openedMediaEvent: OpenMediaEvent) => {
|
||||
if (openedMediaEvent) {
|
||||
this.openedMediaEvent = openedMediaEvent;
|
||||
// this.mediaViewerActive = true;
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.streamSub.unsubscribe();
|
||||
this.columnEditorSub.unsubscribe();
|
||||
this.openMediaSub.unsubscribe();
|
||||
}
|
||||
|
||||
closeMedia(){
|
||||
console.warn('closeMedia()');
|
||||
this.openedMediaEvent = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ import { StreamEditionComponent } from './components/stream/stream-edition/strea
|
||||
import { TutorialComponent } from './components/tutorial/tutorial.component';
|
||||
import { NotificationHubComponent } from './components/notification-hub/notification-hub.component';
|
||||
import { NotificationService } from "./services/notification.service";
|
||||
import { MediaViewerComponent } from './components/media-viewer/media-viewer.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: "", redirectTo: "home", pathMatch: "full" },
|
||||
@ -85,7 +86,8 @@ const routes: Routes = [
|
||||
StreamStatusesComponent,
|
||||
StreamEditionComponent,
|
||||
TutorialComponent,
|
||||
NotificationHubComponent
|
||||
NotificationHubComponent,
|
||||
MediaViewerComponent
|
||||
],
|
||||
imports: [
|
||||
FontAwesomeModule,
|
||||
|
12
src/app/components/media-viewer/media-viewer.component.html
Normal file
12
src/app/components/media-viewer/media-viewer.component.html
Normal file
@ -0,0 +1,12 @@
|
||||
<div class="media-viewer-canvas" (click)="close()">
|
||||
<button class="media-viewer-canvas__close" title="close">
|
||||
<fa-icon [icon]="faTimes"></fa-icon>
|
||||
</button>
|
||||
<img class="media-viewer-canvas__image" *ngIf="imageUrl" src="{{imageUrl}}" (click)="blockClick($event)"/>
|
||||
<video class="media-viewer-canvas__image" *ngIf="gifvUrl" role="application" loop autoplay (click)="blockClick($event)">
|
||||
<source src="{{ gifvUrl }}" type="video/mp4">
|
||||
</video>
|
||||
<video class="media-viewer-canvas__image" *ngIf="videoUrl" role="application" loop controls="controls" (click)="blockClick($event)">
|
||||
<source src="{{ videoUrl }}" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
30
src/app/components/media-viewer/media-viewer.component.scss
Normal file
30
src/app/components/media-viewer/media-viewer.component.scss
Normal file
@ -0,0 +1,30 @@
|
||||
@import "variables";
|
||||
@import "mixins";
|
||||
|
||||
.media-viewer-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
&__close {
|
||||
@include clearButton;
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 20px;
|
||||
font-size: 24px;
|
||||
color: $font-link-primary;
|
||||
&:hover {
|
||||
color: $font-link-primary-hover;
|
||||
}
|
||||
}
|
||||
|
||||
&__image {
|
||||
max-width: 95%;
|
||||
max-height: calc(100% - 120px);
|
||||
margin-top: 50vh;
|
||||
margin-left: 50vw;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MediaViewerComponent } from './media-viewer.component';
|
||||
|
||||
xdescribe('MediaViewerComponent', () => {
|
||||
let component: MediaViewerComponent;
|
||||
let fixture: ComponentFixture<MediaViewerComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ MediaViewerComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MediaViewerComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
61
src/app/components/media-viewer/media-viewer.component.ts
Normal file
61
src/app/components/media-viewer/media-viewer.component.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import { Component, OnInit, Input, Output } from '@angular/core';
|
||||
import { faChevronLeft, faChevronRight, faTimes } from "@fortawesome/free-solid-svg-icons";
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import { OpenMediaEvent } from '../../models/common.model';
|
||||
import { Attachment } from '../../services/models/mastodon.interfaces';
|
||||
|
||||
@Component({
|
||||
selector: 'app-media-viewer',
|
||||
templateUrl: './media-viewer.component.html',
|
||||
styleUrls: ['./media-viewer.component.scss']
|
||||
})
|
||||
export class MediaViewerComponent implements OnInit {
|
||||
private _mediaEvent: OpenMediaEvent;
|
||||
|
||||
faChevronLeft = faChevronLeft;
|
||||
faChevronRight = faChevronRight;
|
||||
faTimes = faTimes;
|
||||
|
||||
imageUrl: string;
|
||||
gifvUrl: string;
|
||||
videoUrl: string;
|
||||
|
||||
@Input('openedMediaEvent')
|
||||
set openedMediaEvent(value: OpenMediaEvent) {
|
||||
this._mediaEvent = value;
|
||||
|
||||
const attachment = value.attachments[value.selectedIndex];
|
||||
this.loadAttachment(attachment);
|
||||
}
|
||||
get openedMediaEvent(): OpenMediaEvent {
|
||||
return this._mediaEvent;
|
||||
}
|
||||
|
||||
@Output() closeSubject = new Subject<boolean>();
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
private loadAttachment(attachment: Attachment) {
|
||||
if (attachment.type === 'image') {
|
||||
this.imageUrl = attachment.url;
|
||||
} else if (attachment.type === 'gifv'){
|
||||
this.gifvUrl = attachment.url;
|
||||
} else if (attachment.type === 'video'){
|
||||
this.videoUrl = attachment.url;
|
||||
}
|
||||
}
|
||||
|
||||
close(): boolean {
|
||||
this.closeSubject.next(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
blockClick(event: any): boolean{
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
@ -4,18 +4,34 @@
|
||||
</a>
|
||||
<ion-icon *ngIf="isLocked" class="action-bar__lock" name="lock" title="Account can't access this post"></ion-icon>
|
||||
|
||||
<a *ngIf="!(isBoostLocked || isLocked)" href class="action-bar__link" title="Boost" [class.boosted]="isBoosted" (click)="boost()">
|
||||
<a *ngIf="!(isBoostLocked || isLocked)" href class="action-bar__link" title="Boost" [class.boosted]="isBoosted"
|
||||
(click)="boost()">
|
||||
<ion-icon name="md-swap"></ion-icon>
|
||||
</a>
|
||||
<ion-icon *ngIf="isBoostLocked && !isLocked" class="action-bar__lock" name="lock" title="This post cannot be boosted"></ion-icon>
|
||||
<ion-icon *ngIf="isBoostLocked && !isLocked" class="action-bar__lock" name="lock"
|
||||
title="This post cannot be boosted"></ion-icon>
|
||||
<ion-icon *ngIf="isLocked" class="action-bar__lock" name="lock" title="Account can't access this post"></ion-icon>
|
||||
|
||||
<a *ngIf="!isLocked" href class="action-bar__link" title="Favourite" [class.favorited]="isFavorited" (click)="favorite()">
|
||||
<a *ngIf="!isLocked" href class="action-bar__link" title="Favourite" [class.favorited]="isFavorited"
|
||||
(click)="favorite()">
|
||||
<ion-icon name="md-star"></ion-icon>
|
||||
</a>
|
||||
<ion-icon *ngIf="isLocked" class="action-bar__lock" name="lock" title="Account can't access this post"></ion-icon>
|
||||
|
||||
<a href class="action-bar__link" title="More" (click)="more()">
|
||||
<ion-icon name="ios-more"></ion-icon>
|
||||
<a href class="action-bar__link action-bar__link--cw"
|
||||
title="show content" (click)="showContent()"
|
||||
*ngIf="isContentWarningActive">
|
||||
<fa-icon class="action-bar__cw" [icon]="faWindowClose"></fa-icon>
|
||||
</a>
|
||||
<a href class="action-bar__link action-bar__link--cw"
|
||||
title="hide content" (click)="hideContent()"
|
||||
*ngIf="!isContentWarningActive">
|
||||
<fa-icon class="action-bar__cw" [icon]="faWindowCloseRegular"></fa-icon>
|
||||
</a>
|
||||
|
||||
<a href class="action-bar__link action-bar__link--more" title="More" (click)="more()">
|
||||
<ion-icon name="ios-more"></ion-icon>
|
||||
</a>
|
||||
|
||||
|
||||
</div>
|
@ -5,6 +5,8 @@
|
||||
padding: 0;
|
||||
font-size: 24px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
|
||||
&__link {
|
||||
color: $status-secondary-color;
|
||||
&:hover {
|
||||
@ -13,6 +15,18 @@
|
||||
&:not(:last-child) {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
&--cw {
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
&--more {
|
||||
position: absolute;
|
||||
left: 155px;
|
||||
bottom: -6px;
|
||||
}
|
||||
}
|
||||
|
||||
&__lock {
|
||||
@ -23,6 +37,15 @@
|
||||
margin-right: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
// &_cw {
|
||||
// // width: 18px;
|
||||
// font-size: 10px;
|
||||
|
||||
// &:not(:last-child) {
|
||||
// margin-right: 15px;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
.boosted {
|
||||
|
@ -2,14 +2,15 @@ import { Component, OnInit, OnDestroy, Input, Output, EventEmitter } from '@angu
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { Store } from '@ngxs/store';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { faWindowClose, faReply, faRetweet, faStar } from "@fortawesome/free-solid-svg-icons";
|
||||
import { faWindowClose as faWindowCloseRegular } from "@fortawesome/free-regular-svg-icons";
|
||||
|
||||
import { StatusWrapper } from '../../stream.component';
|
||||
import { MastodonService } from '../../../../services/mastodon.service';
|
||||
import { AccountInfo } from '../../../../states/accounts.state';
|
||||
import { Status, Results } from '../../../../services/models/mastodon.interfaces';
|
||||
import { Status } from '../../../../services/models/mastodon.interfaces';
|
||||
import { ToolsService } from '../../../../services/tools.service';
|
||||
import { NotificationService } from '../../../../services/notification.service';
|
||||
// import { map } from "rxjs/operators";
|
||||
|
||||
@Component({
|
||||
selector: 'app-action-bar',
|
||||
@ -17,9 +18,15 @@ import { NotificationService } from '../../../../services/notification.service';
|
||||
styleUrls: ['./action-bar.component.scss']
|
||||
})
|
||||
export class ActionBarComponent implements OnInit, OnDestroy {
|
||||
faWindowClose = faWindowClose;
|
||||
faReply = faReply;
|
||||
faRetweet = faRetweet;
|
||||
faStar = faStar;
|
||||
faWindowCloseRegular = faWindowCloseRegular;
|
||||
|
||||
@Input() statusWrapper: StatusWrapper;
|
||||
@Output() replyEvent = new EventEmitter();
|
||||
@Output() cwIsActiveEvent = new EventEmitter<boolean>();
|
||||
|
||||
isFavorited: boolean;
|
||||
isBoosted: boolean;
|
||||
@ -27,6 +34,8 @@ export class ActionBarComponent implements OnInit, OnDestroy {
|
||||
isBoostLocked: boolean;
|
||||
isLocked: boolean;
|
||||
|
||||
isContentWarningActive: boolean = false;
|
||||
|
||||
private isProviderSelected: boolean;
|
||||
private selectedAccounts: AccountInfo[];
|
||||
|
||||
@ -78,10 +87,26 @@ export class ActionBarComponent implements OnInit, OnDestroy {
|
||||
this.isLocked = false;
|
||||
}
|
||||
|
||||
if(status.sensitive || status.spoiler_text){
|
||||
this.isContentWarningActive = true;
|
||||
}
|
||||
|
||||
this.checkIfFavorited();
|
||||
this.checkIfBoosted();
|
||||
}
|
||||
|
||||
showContent(): boolean {
|
||||
this.isContentWarningActive = false;
|
||||
this.cwIsActiveEvent.next(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
hideContent(): boolean {
|
||||
this.isContentWarningActive = true;
|
||||
this.cwIsActiveEvent.next(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
reply(): boolean {
|
||||
this.replyEvent.emit();
|
||||
return false;
|
||||
|
@ -1,48 +1,79 @@
|
||||
<div class="galery" *ngIf="isImage">
|
||||
<div class="galery__image">
|
||||
|
||||
<a *ngIf="attachments.length === 1" href="{{ attachments[0].url }}" title="{{ attachments[0].text_url }}"
|
||||
target="_blank">
|
||||
<img class="galery__image--1" src="{{ attachments[0].url }}" />
|
||||
<a *ngIf="attachments.length === 1" class="galery__image--link" title="{{ attachments[0].description }}"
|
||||
(click)="attachmentSelected(0)">
|
||||
<img class="galery__image--1" src="{{ attachments[0].preview_url }}" />
|
||||
</a>
|
||||
|
||||
<a *ngIf="attachments.length === 2" class="galery__image--link-2" href="{{ attachments[0].url }}" title="{{ attachments[0].text_url }}"
|
||||
target="_blank">
|
||||
<img src="{{ attachments[0].url }}" />
|
||||
<a *ngIf="attachments.length === 2" class="galery__image--link galery__image--link-2"
|
||||
title="{{ attachments[0].description }}" (click)="attachmentSelected(0)">
|
||||
<img src="{{ attachments[0].preview_url }}" />
|
||||
</a>
|
||||
<a *ngIf="attachments.length === 2" class="galery__image--link-2" href="{{ attachments[1].url }}" title="{{ attachments[1].text_url }}"
|
||||
target="_blank">
|
||||
<img src="{{ attachments[1].url }}" />
|
||||
<a *ngIf="attachments.length === 2" class="galery__image--link galery__image--link-2"
|
||||
title="{{ attachments[1].description }}" (click)="attachmentSelected(1)">
|
||||
<img src="{{ attachments[1].preview_url }}" />
|
||||
</a>
|
||||
|
||||
<a *ngIf="attachments.length === 3" class="galery__image--link-3-1" href="{{ attachments[0].url }}" title="{{ attachments[0].text_url }}"
|
||||
target="_blank">
|
||||
<img src="{{ attachments[0].url }}" />
|
||||
<a *ngIf="attachments.length === 3" class="galery__image--link galery__image--link-3-1"
|
||||
title="{{ attachments[0].text_url }}" (click)="attachmentSelected(0)">
|
||||
<img src="{{ attachments[0].preview_url }}" />
|
||||
</a>
|
||||
<a *ngIf="attachments.length === 3" class="galery__image--link-3-2" href="{{ attachments[1].url }}" title="{{ attachments[1].text_url }}"
|
||||
target="_blank">
|
||||
<img src="{{ attachments[1].url }}" />
|
||||
<a *ngIf="attachments.length === 3" class="galery__image--link galery__image--link-3-2"
|
||||
title="{{ attachments[1].description }}" (click)="attachmentSelected(1)">
|
||||
<img src="{{ attachments[1].preview_url }}" />
|
||||
</a>
|
||||
<a *ngIf="attachments.length === 3" class="galery__image--link-3-2" href="{{ attachments[2].url }}" title="{{ attachments[2].text_url }}"
|
||||
target="_blank">
|
||||
<img src="{{ attachments[2].url }}" />
|
||||
<a *ngIf="attachments.length === 3" class="galery__image--link galery__image--link-3-2"
|
||||
title="{{ attachments[2].description }}" (click)="attachmentSelected(2)">
|
||||
<img src="{{ attachments[2].preview_url }}" />
|
||||
</a>
|
||||
|
||||
<a *ngIf="attachments.length === 4" class="galery__image--link-4" href="{{ attachments[0].url }}" title="{{ attachments[0].text_url }}"
|
||||
target="_blank">
|
||||
<img src="{{ attachments[0].url }}" />
|
||||
<a *ngIf="attachments.length === 4" class="galery__image--link galery__image--link-4"
|
||||
title="{{ attachments[0].text_url }}" (click)="attachmentSelected(0)">
|
||||
<img src="{{ attachments[0].preview_url }}" />
|
||||
</a>
|
||||
<a *ngIf="attachments.length === 4" class="galery__image--link-4" href="{{ attachments[1].url }}" title="{{ attachments[1].text_url }}"
|
||||
target="_blank">
|
||||
<img src="{{ attachments[1].url }}" />
|
||||
<a *ngIf="attachments.length === 4" class="galery__image--link galery__image--link-4"
|
||||
title="{{ attachments[1].description }}" (click)="attachmentSelected(1)">
|
||||
<img src="{{ attachments[1].preview_url }}" />
|
||||
</a>
|
||||
<a *ngIf="attachments.length === 4" class="galery__image--link-4" href="{{ attachments[2].url }}" title="{{ attachments[2].text_url }}"
|
||||
target="_blank">
|
||||
<img src="{{ attachments[2].url }}" />
|
||||
<a *ngIf="attachments.length === 4" class="galery__image--link galery__image--link-4"
|
||||
title="{{ attachments[2].description }}" (click)="attachmentSelected(2)">
|
||||
<img src="{{ attachments[2].preview_url }}" />
|
||||
</a>
|
||||
<a *ngIf="attachments.length === 4" class="galery__image--link-4" href="{{ attachments[3].url }}" title="{{ attachments[3].text_url }}"
|
||||
target="_blank">
|
||||
<img src="{{ attachments[3].url }}" />
|
||||
<a *ngIf="attachments.length === 4" class="galery__image--link galery__image--link-4"
|
||||
title="{{ attachments[3].description }}" (click)="attachmentSelected(3)">
|
||||
<img src="{{ attachments[3].preview_url }}" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="galery" *ngIf="isGifv">
|
||||
<!-- <video width="480" height="320" controls="controls"> -->
|
||||
<video class="galery__gifv" role="application" loop autoplay (click)="attachmentSelected(0)">
|
||||
<source src="{{ attachments[0].url }}" type="video/mp4">
|
||||
</video>
|
||||
</div>
|
||||
<div class="galery galery__hover" *ngIf="isVideo">
|
||||
<!-- <video width="480" height="320" controls="controls"> -->
|
||||
<video #videoPlayer class="galery__video" role="application" loop>
|
||||
<source src="{{ attachments[0].url }}" type="video/mp4">
|
||||
</video>
|
||||
<div class="galery__play-control">
|
||||
<button type="button" id="play-pause" class="galery__control--button" (click)="onPlay()">
|
||||
<fa-icon [icon]="faPlay" *ngIf="!isPlaying"></fa-icon>
|
||||
<fa-icon [icon]="faPause" *ngIf="isPlaying"></fa-icon>
|
||||
</button>
|
||||
<!-- <button type="button" id="play-pause" class="galery__control--button">
|
||||
<fa-icon [icon]="faPause"></fa-icon>
|
||||
</button> -->
|
||||
</div>
|
||||
<div class="galery__control">
|
||||
<!-- <input type="range" id="seek-bar" class="video-control__button" value="0"> -->
|
||||
<button type="button" class="galery__control--button galery__control--expand" (click)="onExpand()">
|
||||
<fa-icon [icon]="faExpand"></fa-icon>
|
||||
</button>
|
||||
<!-- <input type="range" id="volume-bar" class="video-control__button" min="0" max="1" step="0.1" value="1"> -->
|
||||
<button type="button" class="galery__control--button galery__control--mute" (click)="onMute()">
|
||||
<fa-icon [icon]="faVolumeUp" *ngIf="!isMuted"></fa-icon>
|
||||
<fa-icon [icon]="faVolumeMute" *ngIf="isMuted"></fa-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
@ -1,11 +1,18 @@
|
||||
@import "variables";
|
||||
@import "mixins";
|
||||
.galery {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
overflow: hidden;
|
||||
border-radius: 2px;
|
||||
position : relative;
|
||||
|
||||
&__image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
&--link {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
&--1 {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@ -34,7 +41,6 @@
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: 50% 50%;
|
||||
|
||||
}
|
||||
}
|
||||
&--link-3-2 {
|
||||
@ -67,4 +73,64 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
&__gifv {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
cursor: zoom-in;
|
||||
border-radius: 2px;
|
||||
}
|
||||
&__video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
background-color: black;
|
||||
border-radius: 2px;
|
||||
}
|
||||
&__play-control{
|
||||
z-index: 2;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 5px;
|
||||
// outline: 1px greenyellow solid;
|
||||
}
|
||||
&__control {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
opacity: 0;
|
||||
transition: all .2s;
|
||||
height: 100px;
|
||||
padding-top: 55px;
|
||||
|
||||
&--button {
|
||||
@include clearButton;
|
||||
color: rgb(211, 211, 211);
|
||||
font-size: 16px;
|
||||
padding: 10px 15px;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&--expand {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&--mute {
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .1), rgba(0, 0, 0, .6), rgba(0, 0, 0, 1));
|
||||
}
|
||||
&__hover {
|
||||
&:hover .galery__control {
|
||||
opacity: 100;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Component, OnInit, Input, ViewChild, ElementRef } from '@angular/core';
|
||||
|
||||
import { Attachment } from '../../../../services/models/mastodon.interfaces';
|
||||
import { NavigationService } from '../../../../services/navigation.service';
|
||||
import { OpenMediaEvent } from '../../../../models/common.model';
|
||||
import { faPlay, faPause, faExpand, faVolumeUp, faVolumeMute } from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
@Component({
|
||||
selector: 'app-attachements',
|
||||
@ -7,26 +11,80 @@ import { Attachment } from '../../../../services/models/mastodon.interfaces';
|
||||
styleUrls: ['./attachements.component.scss']
|
||||
})
|
||||
export class AttachementsComponent implements OnInit {
|
||||
private _attachments: Attachment[];
|
||||
private _attachments: Attachment[];
|
||||
isImage: boolean;
|
||||
imageUrls: string[];
|
||||
isGifv: boolean;
|
||||
isVideo: boolean;
|
||||
|
||||
faPlay = faPlay;
|
||||
faPause = faPause;
|
||||
faExpand = faExpand;
|
||||
faVolumeUp = faVolumeUp;
|
||||
faVolumeMute = faVolumeMute;
|
||||
|
||||
isPlaying: boolean = false;
|
||||
isMuted: boolean = false;
|
||||
|
||||
// imageUrls: string[];
|
||||
|
||||
@Input('attachments')
|
||||
set attachments(value: Attachment[]) {
|
||||
this._attachments = value;
|
||||
|
||||
if(this._attachments[0].type === 'image'){
|
||||
if (this._attachments[0].type === 'image') {
|
||||
this.isImage = true;
|
||||
// this.imageUrls = this._attachments.map(x => x.url);
|
||||
} else if (this._attachments[0].type === 'gifv') {
|
||||
this.isGifv = true;
|
||||
} else if (this._attachments[0].type === 'video') {
|
||||
this.isVideo = true;
|
||||
}
|
||||
}
|
||||
get attachments(): Attachment[] {
|
||||
return this._attachments;
|
||||
}
|
||||
|
||||
constructor() { }
|
||||
@ViewChild('videoPlayer') videoplayer: ElementRef;
|
||||
|
||||
constructor(private readonly navigationService: NavigationService) { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
attachmentSelected(index: number): boolean {
|
||||
let openMediaEvent = new OpenMediaEvent(index, this.attachments);
|
||||
this.navigationService.openMedia(openMediaEvent);
|
||||
return false;
|
||||
}
|
||||
|
||||
private getVideo(): HTMLVideoElement {
|
||||
return this.videoplayer.nativeElement;
|
||||
}
|
||||
|
||||
onPlay() {
|
||||
if (!this.isPlaying) {
|
||||
this.getVideo().play();
|
||||
} else {
|
||||
this.getVideo().pause();
|
||||
}
|
||||
|
||||
this.isPlaying = !this.isPlaying;
|
||||
|
||||
}
|
||||
|
||||
onExpand() {
|
||||
if (!this.isMuted) {
|
||||
this.onMute();
|
||||
}
|
||||
|
||||
if (this.isPlaying) {
|
||||
this.onPlay();
|
||||
}
|
||||
|
||||
this.attachmentSelected(0);
|
||||
}
|
||||
|
||||
onMute() {
|
||||
this.isMuted = !this.isMuted;
|
||||
this.getVideo().muted = this.isMuted;
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,10 @@
|
||||
</div>
|
||||
<div class="status">
|
||||
|
||||
<a href class="status__profile-link" title="{{displayedStatus.account.acct}}" (click)="openAccount(displayedStatus.account)">
|
||||
<img [class.status__avatar--boosted]="reblog" class="status__avatar" src="{{ displayedStatus.account.avatar }}" />
|
||||
<a href class="status__profile-link" title="{{displayedStatus.account.acct}}"
|
||||
(click)="openAccount(displayedStatus.account)">
|
||||
<img [class.status__avatar--boosted]="reblog" class="status__avatar"
|
||||
src="{{ displayedStatus.account.avatar }}" />
|
||||
<!-- <img *ngIf="reblog" class="status__avatar--reblog" src="{{ status.account.avatar }}" /> -->
|
||||
<span class="status__name">
|
||||
<span class="status__name--displayname" innerHTML="{{displayedStatus.account.display_name}}"></span><span
|
||||
@ -17,15 +19,39 @@
|
||||
{{ status.created_at | timeAgo | async }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="status__labels">
|
||||
<div class="status__labels--label status__labels--bot" title="bot"
|
||||
*ngIf="status.account.bot">
|
||||
bot
|
||||
</div>
|
||||
<div class="status__labels--label status__labels--xpost" title="cross-poster"
|
||||
*ngIf="isCrossPoster">
|
||||
x-post
|
||||
</div>
|
||||
<div class="status__labels--label status__labels--thread" title="thread"
|
||||
*ngIf="isThread">
|
||||
thread
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div #content class="status__content" innerHTML="{{displayedStatus.content}}"></div> -->
|
||||
|
||||
<app-databinded-text class="status__content" [text]="displayedStatus.content" (accountSelected)="accountSelected($event)"
|
||||
(hashtagSelected)="hashtagSelected($event)" (textSelected)="textSelected()"></app-databinded-text>
|
||||
<a href class="status__content-warning" *ngIf="isContentWarned" title="show content" (click)="removeContentWarning()">
|
||||
<span class="status__content-warning--title">sensitive content</span>
|
||||
{{ contentWarningText }}
|
||||
</a>
|
||||
<app-databinded-text class="status__content" *ngIf="!isContentWarned"
|
||||
[text]="displayedStatus.content"
|
||||
(accountSelected)="accountSelected($event)"
|
||||
(hashtagSelected)="hashtagSelected($event)"
|
||||
(textSelected)="textSelected()"></app-databinded-text>
|
||||
<app-attachements *ngIf="!isContentWarned && hasAttachments" class="attachments" [attachments]="displayedStatus.media_attachments">
|
||||
</app-attachements>
|
||||
|
||||
<app-action-bar #appActionBar
|
||||
[statusWrapper]="statusWrapper"
|
||||
(cwIsActiveEvent)="changeCw($event)"
|
||||
(replyEvent)="openReply()"></app-action-bar>
|
||||
|
||||
<app-attachements *ngIf="hasAttachments" class="attachments" [attachments]="displayedStatus.media_attachments"></app-attachements>
|
||||
|
||||
<app-action-bar [statusWrapper]="statusWrapper" (replyEvent)="openReply()"></app-action-bar>
|
||||
|
||||
<app-reply-to-status *ngIf="replyingToStatus" [statusReplyingToWrapper]="statusWrapper" (onClose)="closeReply()"></app-reply-to-status>
|
||||
<app-reply-to-status *ngIf="replyingToStatus" [statusReplyingToWrapper]="statusWrapper" (onClose)="closeReply()">
|
||||
</app-reply-to-status>
|
||||
</div>
|
@ -1,5 +1,4 @@
|
||||
@import "variables";
|
||||
|
||||
.reblog {
|
||||
position: relative;
|
||||
margin: 5px 0 0 10px;
|
||||
@ -48,6 +47,36 @@
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
&__labels {
|
||||
position: absolute;
|
||||
top: 65px;
|
||||
left: 10px;
|
||||
width: 50px;
|
||||
cursor: default;
|
||||
&--label {
|
||||
text-transform: uppercase;
|
||||
text-align: center;
|
||||
font-size: 7px;
|
||||
margin-bottom: 3px; // color: #000;
|
||||
border-radius: 2px; //border: 1px solid greenyellow;
|
||||
padding-top: 1px;
|
||||
}
|
||||
&--bot {
|
||||
background-color: rgb(0, 225, 255);
|
||||
background-color: rgb(0, 159, 180);
|
||||
background-color: rgb(0, 114, 129);
|
||||
}
|
||||
&--xpost {
|
||||
background-color: rgb(255, 153, 0);
|
||||
background-color: rgb(189, 113, 0);
|
||||
background-color: rgb(156, 94, 0);
|
||||
}
|
||||
&--thread {
|
||||
background-color: rgb(0, 187, 84);
|
||||
background-color: rgb(0, 136, 61);
|
||||
background-color: rgb(0, 114, 51);
|
||||
}
|
||||
}
|
||||
&__name {
|
||||
display: inline-block;
|
||||
width: calc(100% - 40px);
|
||||
@ -74,24 +103,42 @@
|
||||
}
|
||||
}
|
||||
&__content {
|
||||
/*width: calc(100% - 50px);*/
|
||||
word-wrap: break-word;
|
||||
margin: 0 10px 0 $avatar-column-space;
|
||||
display: block;
|
||||
display: block;
|
||||
}
|
||||
// &__content p {
|
||||
// margin: 0 !important;
|
||||
// font-size: 0.85em;
|
||||
// }
|
||||
&__created-at {
|
||||
&__content-warning {
|
||||
min-height: 80px;
|
||||
display: block; // border: 1px solid greenyellow;
|
||||
margin: 0 10px 0 $avatar-column-space;
|
||||
padding: 3px 5px 3px 5px;
|
||||
background-color: $content-warning-background-color;
|
||||
color: $content-warning-font-color;
|
||||
border-radius: 3px;
|
||||
text-decoration: none;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
font-size: 13px;
|
||||
&--title {
|
||||
// padding-top: 3px;
|
||||
color: whitesmoke;
|
||||
font-size: 11px;
|
||||
//font-weight: bold;
|
||||
// outline: 1px solid greenyellow;
|
||||
display: block;
|
||||
width: calc(100%);
|
||||
text-align: center;
|
||||
// position: absolute;
|
||||
// bottom: 5px;
|
||||
}
|
||||
}
|
||||
&__created-at {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
right: 5px;
|
||||
|
||||
&--link {
|
||||
color: $status-secondary-color;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: lighten($status-secondary-color, 20);
|
||||
}
|
||||
@ -100,7 +147,6 @@
|
||||
}
|
||||
|
||||
.attachments {
|
||||
display: block;
|
||||
// width: calc(100% - 80px);
|
||||
display: block; // width: calc(100% - 80px);
|
||||
margin: 10px 10px 0 $avatar-column-space;
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import { Component, OnInit, Input, Output, EventEmitter } from "@angular/core";
|
||||
import { Component, OnInit, Input, Output, EventEmitter, ViewChild } from "@angular/core";
|
||||
import { Status, Account } from "../../../services/models/mastodon.interfaces";
|
||||
import { StatusWrapper } from "../stream.component";
|
||||
import { OpenThreadEvent } from "../../../services/tools.service";
|
||||
import { ActionBarComponent } from "./action-bar/action-bar.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-status",
|
||||
@ -13,10 +14,15 @@ export class StatusComponent implements OnInit {
|
||||
reblog: boolean;
|
||||
hasAttachments: boolean;
|
||||
replyingToStatus: boolean;
|
||||
isCrossPoster: boolean;
|
||||
isThread: boolean;
|
||||
isContentWarned: boolean;
|
||||
contentWarningText: string;
|
||||
|
||||
@Output() browseAccountEvent = new EventEmitter<string>();
|
||||
@Output() browseHashtagEvent = new EventEmitter<string>();
|
||||
@Output() browseThreadEvent = new EventEmitter<OpenThreadEvent>();
|
||||
@ViewChild('appActionBar') appActionBar: ActionBarComponent;
|
||||
|
||||
private _statusWrapper: StatusWrapper;
|
||||
status: Status;
|
||||
@ -25,6 +31,9 @@ export class StatusComponent implements OnInit {
|
||||
this._statusWrapper = value;
|
||||
this.status = value.status;
|
||||
|
||||
this.checkLabels(this.status);
|
||||
this.checkContentWarning(this.status);
|
||||
|
||||
if (this.status.reblog) {
|
||||
this.reblog = true;
|
||||
this.displayedStatus = this.status.reblog;
|
||||
@ -49,6 +58,40 @@ export class StatusComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
private checkContentWarning(status: Status) {
|
||||
if (status.sensitive || status.spoiler_text) {
|
||||
this.isContentWarned = true;
|
||||
this.contentWarningText = status.spoiler_text;
|
||||
}
|
||||
}
|
||||
|
||||
removeContentWarning(): boolean {
|
||||
this.isContentWarned = false;
|
||||
this.appActionBar.showContent();
|
||||
return false;
|
||||
}
|
||||
|
||||
changeCw(cwIsActive: boolean){
|
||||
this.isContentWarned = cwIsActive;
|
||||
}
|
||||
|
||||
private checkLabels(status: Status) {
|
||||
//since API is limited with federated status...
|
||||
if (status.uri.includes('birdsite.link')) {
|
||||
this.isCrossPoster = true;
|
||||
}
|
||||
else if (status.application) {
|
||||
const usedApp = status.application.name.toLowerCase();
|
||||
if (usedApp && (usedApp.includes('moa') || usedApp.includes('birdsite') || usedApp.includes('twitter'))) {
|
||||
this.isCrossPoster = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.status.in_reply_to_account_id && this.status.in_reply_to_account_id === this.status.account.id) {
|
||||
this.isThread = true;
|
||||
}
|
||||
}
|
||||
|
||||
openAccount(account: Account): boolean {
|
||||
let accountName = account.acct;
|
||||
if (!accountName.includes('@'))
|
||||
@ -82,8 +125,8 @@ export class StatusComponent implements OnInit {
|
||||
const accountInfo = this._statusWrapper.provider;
|
||||
|
||||
let openThread: OpenThreadEvent;
|
||||
if (status.reblog) {
|
||||
openThread = new OpenThreadEvent(status.reblog, accountInfo);
|
||||
if (status.reblog) {
|
||||
openThread = new OpenThreadEvent(status.reblog, accountInfo);
|
||||
} else {
|
||||
openThread = new OpenThreadEvent(status, accountInfo);
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
<div class="stream-toots flexcroll" #statusstream (scroll)="onScroll()">
|
||||
<app-waiting-animation *ngIf="statuses.length === 0" class="waiting-icon"></app-waiting-animation>
|
||||
|
||||
<div *ngIf="displayError" class="stream-toots__error">{{displayError}}</div>
|
||||
|
||||
<!-- data-simplebar -->
|
||||
@ -10,4 +8,6 @@
|
||||
(browseHashtagEvent)="browseHashtag($event)"
|
||||
(browseThreadEvent)="browseThread($event)"></app-status>
|
||||
</div>
|
||||
|
||||
<app-waiting-animation *ngIf="isLoading" class="waiting-icon"></app-waiting-animation>
|
||||
</div>
|
@ -18,8 +18,7 @@ import { OpenThreadEvent, ToolsService } from '../../../services/tools.service';
|
||||
styleUrls: ['./stream-statuses.component.scss']
|
||||
})
|
||||
export class StreamStatusesComponent implements OnInit, OnDestroy {
|
||||
|
||||
isLoading = false; //TODO
|
||||
isLoading = true;
|
||||
displayError: string;
|
||||
|
||||
private _streamElement: StreamElement;
|
||||
@ -113,7 +112,6 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ViewChild('statusstream') public statustream: ElementRef;
|
||||
private applyGoToTop(): boolean {
|
||||
this.loadBuffer();
|
||||
@ -181,6 +179,9 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
private scrolledToBottom() {
|
||||
if(this.isLoading) return;
|
||||
|
||||
this.isLoading = true;
|
||||
this.isProcessingInfiniteScroll = true;
|
||||
|
||||
const lastStatus = this.statuses[this.statuses.length - 1];
|
||||
@ -195,6 +196,7 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
|
||||
this.notificationService.notifyHttpError(err);
|
||||
})
|
||||
.then(() => {
|
||||
this.isLoading = false;
|
||||
this.isProcessingInfiniteScroll = false;
|
||||
});
|
||||
}
|
||||
@ -208,6 +210,7 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
|
||||
private retrieveToots(): void {
|
||||
this.mastodonService.getTimeline(this.account, this._streamElement.type, null, null, this.streamingService.nbStatusPerIteration, this._streamElement.tag, this._streamElement.list)
|
||||
.then((results: Status[]) => {
|
||||
this.isLoading = false;
|
||||
for (const s of results) {
|
||||
const wrapper = new StatusWrapper(s, this.account);
|
||||
this.statuses.push(wrapper);
|
||||
@ -227,6 +230,6 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
|
||||
this.bufferWasCleared = true;
|
||||
this.bufferStream.length = 2 * this.streamingService.nbStatusPerIteration;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,12 +19,10 @@
|
||||
<app-stream-edition class="stream-edition" *ngIf="editionPanelIsOpen" [streamElement]="streamElement">
|
||||
</app-stream-edition>
|
||||
|
||||
<app-stream-statuses class="stream-statuses" [streamElement]="streamElement"
|
||||
[goToTop]="goToTopSubject.asObservable()" (browseAccountEvent)="browseAccount($event)"
|
||||
(browseHashtagEvent)="browseHashtag($event)" (browseThreadEvent)="browseThread($event)"></app-stream-statuses>
|
||||
<!-- <div class="stream-toots flexcroll" #statusstream (scroll)="onScroll()">
|
||||
<div class="stream-toots__status" *ngFor="let statusWrapper of statuses">
|
||||
<app-status [statusWrapper]="statusWrapper" (browseAccount)="browseAccount($event)" (browseHashtag)="browseHashtag($event)"></app-status>
|
||||
</div>
|
||||
</div> -->
|
||||
<app-stream-statuses class="stream-statuses"
|
||||
[streamElement]="streamElement"
|
||||
[goToTop]="goToTopSubject.asObservable()"
|
||||
(browseAccountEvent)="browseAccount($event)"
|
||||
(browseHashtagEvent)="browseHashtag($event)"
|
||||
(browseThreadEvent)="browseThread($event)"></app-stream-statuses>
|
||||
</div>
|
@ -7,6 +7,7 @@ import { ToolsService, OpenThreadEvent } from '../../../services/tools.service';
|
||||
import { Results, Context, Status } from '../../../services/models/mastodon.interfaces';
|
||||
import { NotificationService } from '../../../services/notification.service';
|
||||
import { AccountInfo } from '../../../states/accounts.state';
|
||||
import { StreamStatusesComponent } from '../stream-statuses/stream-statuses.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-thread',
|
||||
@ -15,8 +16,8 @@ import { AccountInfo } from '../../../states/accounts.state';
|
||||
})
|
||||
export class ThreadComponent implements OnInit {
|
||||
statuses: StatusWrapper[] = [];
|
||||
isLoading: boolean;
|
||||
displayError: string;
|
||||
isLoading = true;
|
||||
|
||||
private lastThreadEvent: OpenThreadEvent;
|
||||
|
||||
@ -27,7 +28,6 @@ export class ThreadComponent implements OnInit {
|
||||
@Input('currentThread')
|
||||
set currentThread(thread: OpenThreadEvent) {
|
||||
if (thread) {
|
||||
this.isLoading = true;
|
||||
this.lastThreadEvent = thread;
|
||||
this.getThread(thread);
|
||||
}
|
||||
@ -43,6 +43,7 @@ export class ThreadComponent implements OnInit {
|
||||
|
||||
private getThread(openThreadEvent: OpenThreadEvent) {
|
||||
this.statuses.length = 0;
|
||||
this.displayError = null;
|
||||
|
||||
let currentAccount = this.toolsService.getSelectedAccounts()[0];
|
||||
|
||||
@ -66,10 +67,8 @@ export class ThreadComponent implements OnInit {
|
||||
this.retrieveThread(currentAccount, statusPromise);
|
||||
|
||||
} else if (sourceAccount.id === currentAccount.id) {
|
||||
|
||||
var statusPromise = Promise.resolve(status);
|
||||
this.retrieveThread(currentAccount, statusPromise);
|
||||
|
||||
} else {
|
||||
this.isLoading = false;
|
||||
this.displayError = `You need to use your account ${sourceAccount.username}@${sourceAccount.instance} to show this thread`;
|
||||
@ -79,25 +78,28 @@ export class ThreadComponent implements OnInit {
|
||||
private retrieveThread(currentAccount: AccountInfo, pipeline: Promise<Status>) {
|
||||
pipeline
|
||||
.then((status: Status) => {
|
||||
this.mastodonService.getStatusContext(currentAccount, status.id)
|
||||
return this.mastodonService.getStatusContext(currentAccount, status.id)
|
||||
.then((context: Context) => {
|
||||
this.isLoading = false;
|
||||
let contextStatuses = [...context.ancestors, status, ...context.descendants]
|
||||
|
||||
for (const s of contextStatuses) {
|
||||
const wrapper = new StatusWrapper(s, currentAccount);
|
||||
this.statuses.push(wrapper);
|
||||
}
|
||||
})
|
||||
.catch((err: HttpErrorResponse) => {
|
||||
this.isLoading = false;
|
||||
this.notificationService.notifyHttpError(err);
|
||||
});
|
||||
|
||||
})
|
||||
.catch((err: HttpErrorResponse) => {
|
||||
this.notificationService.notifyHttpError(err);
|
||||
})
|
||||
.then(() => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
refresh(): any {
|
||||
this.isLoading = true;
|
||||
this.displayError = null;
|
||||
this.statuses.length = 0;
|
||||
this.getThread(this.lastThreadEvent);
|
||||
}
|
||||
|
8
src/app/models/common.model.ts
Normal file
8
src/app/models/common.model.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { Attachment } from "../services/models/mastodon.interfaces";
|
||||
|
||||
export class OpenMediaEvent {
|
||||
constructor(
|
||||
public selectedIndex: number,
|
||||
public attachments: Attachment[]) {
|
||||
}
|
||||
}
|
@ -127,7 +127,7 @@ export interface Status {
|
||||
url: string;
|
||||
account: Account;
|
||||
in_reply_to_id: string;
|
||||
in_reply_to_account_id: string;
|
||||
in_reply_to_account_id: number;
|
||||
reblog: Status;
|
||||
content: string;
|
||||
created_at: string;
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
|
||||
import { AccountWrapper } from '../models/account.models';
|
||||
import { OpenMediaEvent } from '../models/common.model';
|
||||
|
||||
@Injectable()
|
||||
export class NavigationService {
|
||||
|
||||
|
||||
private accountToManage: AccountWrapper;
|
||||
activatedPanelSubject = new BehaviorSubject<LeftPanelType>(LeftPanelType.Closed);
|
||||
// openColumnEditorSubject = new BehaviorSubject<AccountWrapper>(null);
|
||||
columnSelectedSubject = new BehaviorSubject<number>(-1);
|
||||
activatedMediaSubject: Subject<OpenMediaEvent> = new Subject<OpenMediaEvent>();
|
||||
columnSelectedSubject = new BehaviorSubject<number>(-1);
|
||||
|
||||
constructor() { }
|
||||
|
||||
@ -34,6 +34,10 @@ export class NavigationService {
|
||||
getAccountToManage(): AccountWrapper {
|
||||
return this.accountToManage;
|
||||
}
|
||||
|
||||
openMedia(openMediaEvent: OpenMediaEvent): void{
|
||||
this.activatedMediaSubject.next(openMediaEvent);
|
||||
}
|
||||
}
|
||||
|
||||
export enum LeftPanelType {
|
||||
|
@ -8,6 +8,10 @@ $color-secondary: #090b10;
|
||||
$column-color: #0f111a;
|
||||
$column-header-background-color: #0c0c10;
|
||||
|
||||
$content-warning-background-color: #0a0c13;
|
||||
$content-warning-background-color: black;
|
||||
$content-warning-font-color: $font-link-primary-hover;
|
||||
|
||||
|
||||
|
||||
$default-font-size: 15px;
|
||||
|
Loading…
x
Reference in New Issue
Block a user