Merge pull request #262 from NicolasConstant/topic_enhance-timelines

Topic enhance timelines
This commit is contained in:
Nicolas Constant 2020-04-20 23:41:24 -04:00 committed by GitHub
commit f1ec2a9068
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 245 additions and 43 deletions

View File

@ -7,6 +7,7 @@ import { FavoriteResult, BookmarkResult } from '../../../../services/mastodon.se
import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service';
import { Status } from '../../../../services/models/mastodon.interfaces';
import { NotificationService } from '../../../../services/notification.service';
import { TimeLineModeEnum } from '../../../../states/settings.state';
@Component({
selector: 'app-bookmarks',
@ -21,6 +22,8 @@ export class BookmarksComponent implements OnInit {
hasContentWarnings = false;
bufferStream: Status[] = []; //html compatibility only
streamPositionnedAtTop: boolean = true; //html compatibility only
timelineLoadingMode: TimeLineModeEnum = TimeLineModeEnum.OnTop; //html compatibility only
@Output() browseAccountEvent = new EventEmitter<string>();
@Output() browseHashtagEvent = new EventEmitter<string>();

View File

@ -7,6 +7,7 @@ import { FavoriteResult } from '../../../../services/mastodon.service';
import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service';
import { Status } from '../../../../services/models/mastodon.interfaces';
import { NotificationService } from '../../../../services/notification.service';
import { TimeLineModeEnum } from '../../../../states/settings.state';
@Component({
selector: 'app-favorites',
@ -21,6 +22,8 @@ export class FavoritesComponent implements OnInit {
hasContentWarnings = false;
bufferStream: Status[] = []; //html compatibility only
streamPositionnedAtTop: boolean = true; //html compatibility only
timelineLoadingMode: TimeLineModeEnum = TimeLineModeEnum.OnTop; //html compatibility only
@Output() browseAccountEvent = new EventEmitter<string>();
@Output() browseHashtagEvent = new EventEmitter<string>();

View File

@ -8,6 +8,7 @@ import { Status, Notification } from '../../../../services/models/mastodon.inter
import { MastodonWrapperService } from '../../../../services/mastodon-wrapper.service';
import { NotificationService } from '../../../../services/notification.service';
import { OpenThreadEvent, ToolsService } from '../../../../services/tools.service';
import { TimeLineModeEnum } from '../../../../states/settings.state';
@Component({
@ -23,6 +24,8 @@ export class MentionsComponent implements OnInit, OnDestroy {
hasContentWarnings = false;
bufferStream: Status[] = []; //html compatibility only
streamPositionnedAtTop: boolean = true; //html compatibility only
timelineLoadingMode: TimeLineModeEnum = TimeLineModeEnum.OnTop; //html compatibility only
@Output() browseAccountEvent = new EventEmitter<string>();
@Output() browseHashtagEvent = new EventEmitter<string>();

View File

@ -91,15 +91,69 @@
[(ngModel)]="setContentHidedCompletely" placeholder="example;other example" />
</div>
<span class="sub-section__title" *ngIf="contentWarningPolicyChanged"><br/>this settings needs a <a href (click)="reload()">reload</a> to be effective.</span>
<span class="sub-section__title" *ngIf="contentWarningPolicyChanged"><br />this settings needs a <a href
(click)="reload()">reload</a> to be effective.</span>
</div>
<h4 class="panel__subtitle">Timelines</h4>
<div class="sub-section">
<span class="sub-section__title">header display:</span><br />
<input class="sub-section__checkbox" [checked]="timeLineHeader === 1" (change)="onTimeLineHeaderChange(1)"
type="radio" name="timelineheader-1" value="timelineheader-1" id="timelineheader-1">
<label class="noselect sub-section__label" for="timelineheader-1">Title - Domain Name</label>
<br>
<input class="sub-section__checkbox" [checked]="timeLineHeader === 2" (change)="onTimeLineHeaderChange(2)"
type="radio" name="timelineheader-2" value="timelineheader-2" id="timelineheader-2">
<label class="noselect sub-section__label" for="timelineheader-2">Title - Username - Domain Name</label>
<br>
<input class="sub-section__checkbox" [checked]="timeLineHeader === 3" (change)="onTimeLineHeaderChange(3)"
type="radio" name="timelineheader-3" value="timelineheader-3" id="timelineheader-3">
<label class="noselect sub-section__label" for="timelineheader-3">Title - Account Icon - Domain Name</label>
<br>
<input class="sub-section__checkbox" [checked]="timeLineHeader === 4" (change)="onTimeLineHeaderChange(4)"
type="radio" name="timelineheader-4" value="timelineheader-4" id="timelineheader-4">
<label class="noselect sub-section__label" for="timelineheader-4">Title - Account Icon</label>
<br>
<input class="sub-section__checkbox" [checked]="timeLineHeader === 5" (change)="onTimeLineHeaderChange(5)"
type="radio" name="timelineheader-5" value="timelineheader-5" id="timelineheader-5">
<label class="noselect sub-section__label" for="timelineheader-5">Title</label>
<br>
<span class="sub-section__title" *ngIf="timeLineHeaderChanged">this settings needs a <a href
(click)="reload()">reload</a> to be effective.</span>
<span class="sub-section__title">loading behavior:</span><br />
<input class="sub-section__checkbox" [checked]="timeLineMode === 1" (change)="onTimeLineModeChange(1)"
type="radio" name="timelinemode-1" value="timelinemode-1" id="timelinemode-1">
<label class="noselect sub-section__label" for="timelinemode-1">Load new statuses only on top</label>
<br>
<input class="sub-section__checkbox" [checked]="timeLineMode === 2" (change)="onTimeLineModeChange(2)"
type="radio" name="timelinemode-2" value="timelinemode-2" id="timelinemode-2">
<label class="noselect sub-section__label" for="timelinemode-2">Continuously loading new statuses</label>
<br>
<input class="sub-section__checkbox" [checked]="timeLineMode === 3" (change)="onTimeLineModeChange(3)"
type="radio" name="timelinemode-3" value="timelinemode-3" id="timelinemode-3">
<label class="noselect sub-section__label" for="timelinemode-3">Slow mode (manual loading)</label>
<br>
<span class="sub-section__title" *ngIf="timeLineModeChanged">this settings needs a <a href
(click)="reload()">reload</a> to be effective.</span>
</div>
<h4 class="panel__subtitle">Other</h4>
<div class="sub-section">
<input class="sub-section__checkbox" [(ngModel)]="disableRemoteStatusFetchingEnabled"
(change)="onDisableRemoteStatusFetchingChanged()" type="checkbox" name="disableRemoteFetching" value="disableRemoteFetching"
id="disableRemoteFetching">
<label class="noselect sub-section__label" for="disableRemoteFetching">disable remote status fetching</label>
(change)="onDisableRemoteStatusFetchingChanged()" type="checkbox" name="disableRemoteFetching"
value="disableRemoteFetching" id="disableRemoteFetching">
<label class="noselect sub-section__label" for="disableRemoteFetching">disable remote status
fetching</label>
<br>
</div>
@ -128,7 +182,7 @@
(click)="cancelClearAll()">
Cancel
</a>
<br/>
<br />
</div>
</div>

View File

@ -6,7 +6,7 @@ import { environment } from '../../../../environments/environment';
import { ToolsService } from '../../../services/tools.service';
import { UserNotificationService, NotificationSoundDefinition } from '../../../services/user-notification.service';
import { ServiceWorkerService } from '../../../services/service-worker.service';
import { ContentWarningPolicy, ContentWarningPolicyEnum } from '../../../states/settings.state';
import { ContentWarningPolicy, ContentWarningPolicyEnum, TimeLineModeEnum, TimeLineHeaderEnum } from '../../../states/settings.state';
@Component({
selector: 'app-settings',
@ -29,6 +29,12 @@ export class SettingsComponent implements OnInit {
columnShortcutEnabled: ColumnShortcut = ColumnShortcut.Ctrl;
columnShortcutChanged = false;
timeLineHeader: TimeLineHeaderEnum = TimeLineHeaderEnum.Title_DomainName;
timeLineHeaderChanged = false;
timeLineMode: TimeLineModeEnum = TimeLineModeEnum.OnTop;
timeLineModeChanged = false;
contentWarningPolicy: ContentWarningPolicyEnum = ContentWarningPolicyEnum.None;
contentWarningPolicyChanged = false;
@ -91,6 +97,9 @@ export class SettingsComponent implements OnInit {
this.addCwOnContent = settings.contentWarningPolicy.addCwOnContent.join(';');
this.removeCwOnContent = settings.contentWarningPolicy.removeCwOnContent.join(';');
this.contentHidedCompletely = settings.contentWarningPolicy.hideCompletlyContent.join(';');
this.timeLineHeader = settings.timelineHeader;
this.timeLineMode = settings.timelineMode;
}
onShortcutChange(id: ColumnShortcut) {
@ -102,6 +111,24 @@ export class SettingsComponent implements OnInit {
this.toolsService.saveSettings(settings);
}
onTimeLineHeaderChange(id: TimeLineHeaderEnum){
this.timeLineHeader = id;
this.timeLineHeaderChanged = true;
let settings = this.toolsService.getSettings();
settings.timelineHeader = id;
this.toolsService.saveSettings(settings);
}
onTimeLineModeChange(id: TimeLineModeEnum){
this.timeLineMode = id;
this.timeLineModeChanged = true;
let settings = this.toolsService.getSettings();
settings.timelineMode = id;
this.toolsService.saveSettings(settings);
}
onCwPolicyChange(id: ContentWarningPolicyEnum) {
this.contentWarningPolicy = id;
this.contentWarningPolicyChanged = true;

View File

@ -6,12 +6,15 @@
</div>
<div class="stream-toots__new-notification"
[class.stream-toots__new-notification--display]="bufferStream && bufferStream.length > 0"></div>
[class.stream-toots__new-notification--display]="bufferStream && bufferStream.length > 0 && !streamPositionnedAtTop"></div>
<div class="stream-toots__content flexcroll" #statusstream (scroll)="onScroll()" tabindex="0">
<div *ngIf="displayError" class="stream-toots__error">{{displayError}}</div>
<!-- data-simplebar -->
<div *ngIf="timelineLoadingMode === 3 && bufferStream && bufferStream.length > 0">
<a href (click)="loadBuffer()" class="stream-toots__load-buffer" title="load new items">{{ bufferStream.length }} new item<span *ngIf="bufferStream.length > 1">s</span></a>
</div>
<div class="stream-toots__status" *ngFor="let statusWrapper of statuses" #status>
<app-status
[statusWrapper]="statusWrapper" [isThreadDisplay]="isThread"

View File

@ -8,6 +8,25 @@
overflow: auto;
position: relative;
&__load-buffer {
position: relative;
z-index: 1;
display: inline-block;
border-bottom: 1px solid black;
padding: 10px;
margin: 0;
text-align: center;
width: 100%;
// border: 1px dotted greenyellow ;
transition: all .2s;
color: $status-secondary-color;
&:hover {
color: white;
text-decoration: none;
}
}
&__error {
padding: 20px 20px 0 20px;
color: rgb(255, 113, 113);

View File

@ -11,6 +11,7 @@ import { MastodonWrapperService } from '../../../services/mastodon-wrapper.servi
import { NotificationService } from '../../../services/notification.service';
import { OpenThreadEvent, ToolsService } from '../../../services/tools.service';
import { StatusWrapper } from '../../../models/common.model';
import { TimeLineModeEnum } from '../../../states/settings.state';
@Component({
selector: 'app-stream-statuses',
@ -24,6 +25,8 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
displayError: string;
hasContentWarnings = false;
timelineLoadingMode: TimeLineModeEnum;
private _streamElement: StreamElement;
private account: AccountInfo;
private websocketStreaming: StreamingWrapper;
@ -31,6 +34,8 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
statuses: StatusWrapper[] = [];
bufferStream: Status[] = [];
private bufferWasCleared: boolean;
streamPositionnedAtTop: boolean = true;
private isProcessingInfiniteScroll: boolean;
private hideBoosts: boolean;
private hideReplies: boolean;
@ -75,6 +80,9 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
}
ngOnInit() {
let settings = this.toolsService.getSettings();
this.timelineLoadingMode = settings.timelineMode;
this.goToTopSubscription = this.goToTop.subscribe(() => {
this.applyGoToTop();
});
@ -112,7 +120,7 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
this.deleteStatusSubscription = this.notificationService.deletedStatusStream.subscribe((status: StatusWrapper) => {
if (status) {
this.statuses = this.statuses.filter(x => {
this.statuses = this.statuses.filter(x => {
return !(x.status.url.replace('https://', '').split('/')[0] === status.provider.instance && x.status.id === status.status.id);
});
}
@ -158,7 +166,9 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
if (update) {
if (update.type === EventEnum.update) {
if (!this.statuses.find(x => x.status.id == update.status.id)) {
if (this.streamPositionnedAtTop) {
if ((this.streamPositionnedAtTop || this.timelineLoadingMode === TimeLineModeEnum.Continuous)
&& this.timelineLoadingMode !== TimeLineModeEnum.SlowMode) {
if (this.isFiltered(update.status)) {
return;
}
@ -198,9 +208,6 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
return false;
}
private streamPositionnedAtTop: boolean = true;
private isProcessingInfiniteScroll: boolean;
onScroll() {
var element = this.statustream.nativeElement as HTMLElement;
const atBottom = element.scrollHeight <= element.clientHeight + element.scrollTop + 1000;
@ -233,10 +240,12 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
private scrolledToTop() {
this.streamPositionnedAtTop = true;
this.loadBuffer();
if (this.timelineLoadingMode !== TimeLineModeEnum.SlowMode) {
this.loadBuffer();
}
}
private loadBuffer() {
loadBuffer(): boolean {
if (this.bufferWasCleared) {
this.statuses.length = 0;
this.bufferWasCleared = false;
@ -253,6 +262,7 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
}
this.bufferStream.length = 0;
return false;
}
private scrolledToBottom() {
@ -274,7 +284,7 @@ export class StreamStatusesComponent implements OnInit, OnDestroy {
this.statuses.push(wrapper);
}
if(!status || status.length === 0){
if (!status || status.length === 0) {
this.lastInfinityFetchReturnedNothing = true;
}
})

View File

@ -7,19 +7,20 @@
<!-- <div> -->
<div class="stream-column__stream-header">
<a class="stream-column__stream-selector" href title="return to top" (click)="goToTop()">
<img *ngIf="timelineHeader === 3 || timelineHeader === 4" class="stream-column__stream-selector--avatar" src="{{avatar}}" />
<fa-icon class="stream-column__stream-selector--icon" [icon]="columnFaIcon"></fa-icon>
<h1 class="stream-column__stream-selector--title">{{ streamElement.name.toUpperCase() }}</h1>
<span class="stream-column__stream-selector--subtitle"
*ngIf="streamElement.instance">{{ streamElement.instance.toLowerCase() }}</span>
<span class="stream-column__stream-selector--text">
<h1 class="stream-column__stream-selector--title" [class.stream-column__stream-selector--title--only]="timelineHeader === 4 || timelineHeader === 5">{{ streamElement.name.toUpperCase() }}</h1>
<span class="stream-column__stream-selector--subtitle" *ngIf="streamElement.instance && timelineHeader !== 4 && timelineHeader !== 5"><span *ngIf="timelineHeader === 2">{{account.username}}@</span>{{ streamElement.instance.toLowerCase() }}</span>
</span>
</a>
<a class="stream-column__open-menu" href title="edit column" (click)="openEditionMenu()">
<fa-icon class="stream-column__open-menu--icon" [icon]="menuFaIcon"></fa-icon>
</a>
</div>
<app-stream-edition class="stream-edition" *ngIf="editionPanelIsOpen"
[streamElement]="streamElement" [displayingNotifications]="displayingNotifications"
(closed)="streamEditionClosed()">
<app-stream-edition class="stream-edition" *ngIf="editionPanelIsOpen" [streamElement]="streamElement"
[displayingNotifications]="displayingNotifications" (closed)="streamEditionClosed()">
</app-stream-edition>
<app-stream-statuses *ngIf="!displayingNotifications" class="stream-statuses" [streamElement]="streamElement"
@ -27,9 +28,10 @@
(browseHashtagEvent)="browseHashtag($event)" (browseThreadEvent)="browseThread($event)">
</app-stream-statuses>
<app-stream-notifications *ngIf="displayingNotifications" class="stream-statuses" [streamElement]="streamElement"
[goToTop]="goToTopSubject.asObservable()" (browseAccountEvent)="browseAccount($event)"
(browseHashtagEvent)="browseHashtag($event)" (browseThreadEvent)="browseThread($event)">
<app-stream-notifications *ngIf="displayingNotifications" class="stream-statuses"
[streamElement]="streamElement" [goToTop]="goToTopSubject.asObservable()"
(browseAccountEvent)="browseAccount($event)" (browseHashtagEvent)="browseHashtag($event)"
(browseThreadEvent)="browseThread($event)">
</app-stream-notifications>
<!-- </div> -->

View File

@ -3,6 +3,7 @@
@import "panel";
.stream-edition {
display: block;
width: $stream-column-width;
position: absolute;
z-index: 50;
@ -48,27 +49,58 @@
text-decoration: none;
color: whitesmoke;
position: relative;
&--avatar {
width: 20px;
float: left;
margin-left: 11px;
position: relative;
// left: 11px;
top: 9px;
}
&--icon {
float: left;
margin-left: 11px;
position: relative;
left: 11px;
// left: 11px;
top: 9px;
}
&--text {
float: left;
margin-left: 9px;
}
&--title {
font-size: 0.8em;
font-weight: normal;
position: absolute;
// float: left;
// margin-left: 10px;
// position: absolute;
position: relative;
top: 9px;
left: 35px;
}
// left: 35px;
&--only {
top: 13px;
}
}
&--subtitle {
color: $font-link-primary-hover;
font-size: 0.7em;
font-weight: normal;
font-style: italic;
position: absolute;
top: 21px;
left: 35px;;
// position: absolute;
position: relative;
top: -2px;
// top: 21px;
// top: 10px;
// left: 35px;;
// outline: 1px solid greenyellow;
display: inline-block;
white-space: nowrap;
max-width: 240px;
text-overflow: ellipsis;
overflow: hidden;
padding-right: 5px;
}
}
}

View File

@ -3,9 +3,11 @@ import { Subject } from "rxjs";
import { faHome, faGlobe, faUser, faHashtag, faListUl, faBars, IconDefinition, faBell } from "@fortawesome/free-solid-svg-icons";
import { StreamElement, StreamTypeEnum } from "../../states/streams.state";
import { OpenThreadEvent } from "../../services/tools.service";
import { OpenThreadEvent, ToolsService } from "../../services/tools.service";
import { StreamStatusesComponent } from './stream-statuses/stream-statuses.component';
import { StreamNotificationsComponent } from './stream-notifications/stream-notifications.component';
import { TimeLineHeaderEnum } from '../../states/settings.state';
import { AccountInfo } from '../../states/accounts.state';
@Component({
selector: "app-stream",
@ -21,6 +23,10 @@ export class StreamComponent implements OnInit {
overlayHashtagToBrowse: string;
overlayThreadToBrowse: OpenThreadEvent;
timelineHeader: TimeLineHeaderEnum;
account: AccountInfo;
avatar: string;
displayingNotifications: boolean;
goToTopSubject: Subject<void> = new Subject<void>();
@ -48,26 +54,33 @@ export class StreamComponent implements OnInit {
case StreamTypeEnum.list:
this.columnFaIcon = faListUl;
break;
case StreamTypeEnum.activity:
case StreamTypeEnum.activity:
this.columnFaIcon = faBell;
this.displayingNotifications = true;
break;
}
this._streamElement = stream;
this.account = this.toolsService.getAccountById(stream.accountId);
this.toolsService.getAvatar(this.account)
.then(a => {
this.avatar = a;
})
.catch(err => { });
}
get streamElement(): StreamElement {
return this._streamElement;
}
constructor() { }
constructor(private toolsService: ToolsService) { }
ngOnInit() {
let settings = this.toolsService.getSettings();
this.timelineHeader = settings.timelineHeader;
}
focus(): boolean {
if(this.overlayActive) return false;
if (this.overlayActive) return false;
if (!this.displayingNotifications) {
this.streamStatusesComponent.focus();

View File

@ -11,6 +11,7 @@ import { StatusWrapper } from '../../../models/common.model';
import { StatusComponent } from '../status/status.component';
import scrollIntoView from 'scroll-into-view-if-needed';
import { UserNotificationService, UserNotification } from '../../../services/user-notification.service';
import { TimeLineModeEnum } from '../../../states/settings.state';
@Component({
selector: 'app-thread',
@ -26,6 +27,8 @@ export class ThreadComponent implements OnInit, OnDestroy {
private remoteStatusFetchingDisabled = false;
bufferStream: Status[] = []; //html compatibility only
streamPositionnedAtTop: boolean = true; //html compatibility only
timelineLoadingMode: TimeLineModeEnum = TimeLineModeEnum.OnTop; //html compatibility only
private lastThreadEvent: OpenThreadEvent;

View File

@ -30,6 +30,7 @@ export class StreamingWrapper {
private apiRoutes = new ApiRoutes();
private errorClosing: boolean;
private since_id: string;
private since_id_notifications: string;
private disposed: boolean;
constructor(
@ -67,7 +68,7 @@ export class StreamingWrapper {
});
}
private webSocketGotError(x: Event) {
private webSocketGotError(x: Event) {
this.errorClosing = true;
}
@ -76,6 +77,7 @@ export class StreamingWrapper {
setTimeout(() => {
if (stream.type === StreamTypeEnum.personnal) {
this.pullNewNotifications();
this.pullNewStatuses();
} else {
this.pullNewStatuses();
}
@ -87,10 +89,10 @@ export class StreamingWrapper {
}
private pullNewNotifications() {
this.mastodonService.getNotifications(this.account, null, null, this.since_id, 10)
this.mastodonService.getNotifications(this.account, null, null, this.since_id_notifications, 10)
.then((notifications: Notification[]) => {
//notifications = notifications.sort((a, b) => a.id.localeCompare(b.id));
let soundMuted = !this.since_id;
let soundMuted = !this.since_id_notifications;
notifications = notifications.reverse();
for (const n of notifications) {
@ -100,7 +102,7 @@ export class StreamingWrapper {
update.type = EventEnum.notification;
update.muteSound = soundMuted;
this.since_id = n.id;
this.since_id_notifications = n.id;
this.statusUpdateSubjet.next(update);
}
})

View File

@ -5,8 +5,7 @@ import { AccountInfo } from '../states/accounts.state';
import { MastodonWrapperService } from './mastodon-wrapper.service';
import { Account, Results, Status, Emoji } from "./models/mastodon.interfaces";
import { StatusWrapper } from '../models/common.model';
import { AccountSettings, SaveAccountSettings, GlobalSettings, SaveSettings, ContentWarningPolicy, SaveContentWarningPolicy, ContentWarningPolicyEnum } from '../states/settings.state';
import { AppInfo, RegisteredAppsStateModel } from '../states/registered-apps.state';
import { AccountSettings, SaveAccountSettings, GlobalSettings, SaveSettings, ContentWarningPolicy, SaveContentWarningPolicy, ContentWarningPolicyEnum, TimeLineModeEnum, TimeLineHeaderEnum } from '../states/settings.state';
@Injectable({
providedIn: 'root'
@ -155,6 +154,16 @@ export class ToolsService {
return <GlobalSettings>this.store.snapshot().globalsettings.settings;
}
if(!settings.timelineMode){
settings.timelineMode = TimeLineModeEnum.OnTop;
this.saveSettings(settings);
}
if(!settings.timelineHeader){
settings.timelineHeader = TimeLineHeaderEnum.Title_DomainName;
this.saveSettings(settings);
}
return settings;
}

View File

@ -40,6 +40,20 @@ export enum ContentWarningPolicyEnum {
AddOnAllContent = 3
}
export enum TimeLineModeEnum {
OnTop = 1,
Continuous = 2,
SlowMode = 3
}
export enum TimeLineHeaderEnum {
Title_DomainName = 1,
Title_Username_DomainName = 2,
Title_AccountIcon_DomainName = 3,
Title_AccountIcon = 4,
Title = 5
}
export class ContentWarningPolicy {
policy: ContentWarningPolicyEnum = ContentWarningPolicyEnum.None;
addCwOnContent: string[] = [];
@ -55,6 +69,9 @@ export class GlobalSettings {
notificationSoundFileId: string = '0';
timelineHeader: TimeLineHeaderEnum = TimeLineHeaderEnum.Title_DomainName;
timelineMode: TimeLineModeEnum = TimeLineModeEnum.OnTop;
contentWarningPolicy: ContentWarningPolicy = new ContentWarningPolicy();
columnSwitchingWinAlt = false;
@ -145,6 +162,8 @@ export class SettingsState {
newSettings.notificationSoundFileId = oldSettings.notificationSoundFileId;
newSettings.columnSwitchingWinAlt = oldSettings.columnSwitchingWinAlt;
newSettings.disableRemoteStatusFetching = oldSettings.disableRemoteStatusFetching;
newSettings.timelineHeader = oldSettings.timelineHeader;
newSettings.timelineMode = oldSettings.timelineMode;
return newSettings;
}