diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 1e1ab5cb..d1b27196 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -4,7 +4,7 @@ import { debounceTime, map } from 'rxjs/operators'; import { Select } from '@ngxs/store'; // import { ElectronService } from 'ngx-electron'; -import { NavigationService, LeftPanelType } from './services/navigation.service'; +import { NavigationService, LeftPanelType, OpenLeftPanelEvent } from './services/navigation.service'; import { StreamElement } from './states/streams.state'; import { OpenMediaEvent } from './models/common.model'; import { ToolsService } from './services/tools.service'; @@ -44,8 +44,8 @@ export class AppComponent implements OnInit, OnDestroy { } }); - this.columnEditorSub = this.navigationService.activatedPanelSubject.subscribe((type: LeftPanelType) => { - if (type === LeftPanelType.Closed) { + this.columnEditorSub = this.navigationService.activatedPanelSubject.subscribe((event: OpenLeftPanelEvent) => { + if (event.type === LeftPanelType.Closed) { this.floatingColumnActive = false; } else { this.floatingColumnActive = true; diff --git a/src/app/components/create-status/create-status.component.ts b/src/app/components/create-status/create-status.component.ts index ee706dc3..e65fb2be 100644 --- a/src/app/components/create-status/create-status.component.ts +++ b/src/app/components/create-status/create-status.component.ts @@ -21,7 +21,7 @@ import { identifierModuleUrl } from '@angular/compiler'; }) export class CreateStatusComponent implements OnInit, OnDestroy { private _title: string; - set title(value: string){ + set title(value: string) { this._title = value; this.countStatusChar(this.status); } @@ -48,6 +48,26 @@ export class CreateStatusComponent implements OnInit, OnDestroy { @Output() onClose = new EventEmitter(); @ViewChild('reply') replyElement: ElementRef; + private _isDirectMention: boolean; + @Input('isDirectMention') + set isDirectMention(value: boolean) { + this._isDirectMention = value; + this.initMention(); + } + get isDirectMention(): boolean { + return this._isDirectMention; + } + + private _replyingUserHandle: string; + @Input('replyingUserHandle') + set replyingUserHandle(value: string) { + this._replyingUserHandle = value; + this.initMention(); + } + get replyingUserHandle(): string { + return this._replyingUserHandle; + } + private statusReplyingTo: Status; selectedPrivacy = 'Public'; @@ -55,6 +75,7 @@ export class CreateStatusComponent implements OnInit, OnDestroy { private accounts$: Observable; private accountSub: Subscription; + private selectedAccount: AccountInfo; constructor( private readonly store: Store, @@ -70,7 +91,8 @@ export class CreateStatusComponent implements OnInit, OnDestroy { this.accountSub = this.accounts$.subscribe((accounts: AccountInfo[]) => { this.accountChanged(accounts); }); - + this.selectedAccount = this.toolsService.getSelectedAccounts()[0]; + if (this.statusReplyingToWrapper) { if (this.statusReplyingToWrapper.status.reblog) { this.statusReplyingTo = this.statusReplyingToWrapper.status.reblog; @@ -99,27 +121,49 @@ export class CreateStatusComponent implements OnInit, OnDestroy { } this.title = this.statusReplyingTo.spoiler_text; + } else if (this.replyingUserHandle) { + this.initMention(); } - setTimeout(() => { - this.replyElement.nativeElement.focus(); - }, 0); + this.focus(); } ngOnDestroy() { this.accountSub.unsubscribe(); } + private focus() { + setTimeout(() => { + this.replyElement.nativeElement.focus(); + }, 0); + } + + private initMention() { + if (!this.selectedAccount) { + this.selectedAccount = this.toolsService.getSelectedAccounts()[0]; + } + + if (this.isDirectMention) { + this.setVisibility(VisibilityEnum.Direct); + } else { + this.getDefaultPrivacy(); + } + this.status = `@${this.replyingUserHandle} `; + this.countStatusChar(this.status); + + this.focus(); + } + private accountChanged(accounts: AccountInfo[]): void { if (accounts && accounts.length > 0) { - const selectedAccount = accounts.filter(x => x.isSelected)[0]; + this.selectedAccount = accounts.filter(x => x.isSelected)[0]; - const settings = this.toolsService.getAccountSettings(selectedAccount); + const settings = this.toolsService.getAccountSettings(this.selectedAccount); if (settings.customStatusCharLengthEnabled) { this.maxCharLength = settings.customStatusCharLength; this.countStatusChar(this.status); } else { - this.instancesInfoService.getMaxStatusChars(selectedAccount.instance) + this.instancesInfoService.getMaxStatusChars(this.selectedAccount.instance) .then((maxChars: number) => { this.maxCharLength = maxChars; this.countStatusChar(this.status); @@ -129,18 +173,22 @@ export class CreateStatusComponent implements OnInit, OnDestroy { }); } - if (!this.statusReplyingToWrapper) { - this.instancesInfoService.getDefaultPrivacy(selectedAccount) - .then((defaultPrivacy: VisibilityEnum) => { - this.setVisibility(defaultPrivacy); - }) - .catch((err: HttpErrorResponse) => { - this.notificationService.notifyHttpError(err); - }); + if (!this.statusReplyingToWrapper && !this.replyingUserHandle) { + this.getDefaultPrivacy(); } } } + private getDefaultPrivacy() { + this.instancesInfoService.getDefaultPrivacy(this.selectedAccount) + .then((defaultPrivacy: VisibilityEnum) => { + this.setVisibility(defaultPrivacy); + }) + .catch((err: HttpErrorResponse) => { + this.notificationService.notifyHttpError(err); + }); + } + private setVisibility(defaultPrivacy: VisibilityEnum) { switch (defaultPrivacy) { case VisibilityEnum.Public: diff --git a/src/app/components/floating-column/add-new-status/add-new-status.component.html b/src/app/components/floating-column/add-new-status/add-new-status.component.html index d7909cf6..48c781bc 100644 --- a/src/app/components/floating-column/add-new-status/add-new-status.component.html +++ b/src/app/components/floating-column/add-new-status/add-new-status.component.html @@ -1,5 +1,7 @@

new message

- +
\ No newline at end of file diff --git a/src/app/components/floating-column/add-new-status/add-new-status.component.ts b/src/app/components/floating-column/add-new-status/add-new-status.component.ts index da70569d..3f064f4b 100644 --- a/src/app/components/floating-column/add-new-status/add-new-status.component.ts +++ b/src/app/components/floating-column/add-new-status/add-new-status.component.ts @@ -1,4 +1,4 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, OnInit, Input } from '@angular/core'; import { NavigationService } from '../../../services/navigation.service'; @@ -8,10 +8,14 @@ import { NavigationService } from '../../../services/navigation.service'; styleUrls: ['./add-new-status.component.scss'] }) export class AddNewStatusComponent implements OnInit { - constructor( - private readonly navigationService: NavigationService) { } - ngOnInit() { + @Input() isDirectMention: boolean; + @Input() userHandle: string; + + constructor(private readonly navigationService: NavigationService) { + } + + ngOnInit() { } closeColumn() { diff --git a/src/app/components/floating-column/floating-column.component.html b/src/app/components/floating-column/floating-column.component.html index 418f0c4a..77b128d0 100644 --- a/src/app/components/floating-column/floating-column.component.html +++ b/src/app/components/floating-column/floating-column.component.html @@ -15,7 +15,9 @@ (browseAccountEvent)="browseAccount($event)" (browseHashtagEvent)="browseHashtag($event)" (browseThreadEvent)="browseThread($event)"> - + { + this.activatedPanelSub = this.navigationService.activatedPanelSubject.subscribe((event: OpenLeftPanelEvent) => { + this.isDirectMention = false; + this.userHandle = null; this.overlayActive = false; - switch (type) { + switch (event.type) { case LeftPanelType.Closed: this.openPanel = ''; break; @@ -42,9 +47,11 @@ export class FloatingColumnComponent implements OnInit, OnDestroy { } break; case LeftPanelType.CreateNewStatus: - if (this.openPanel === 'createNewStatus') { + if (this.openPanel === 'createNewStatus' && !event.userHandle) { this.closePanel(); } else { + this.isDirectMention = event.action === LeftPanelAction.DM; + this.userHandle = event.userHandle; this.openPanel = 'createNewStatus'; } break; diff --git a/src/app/components/stream/status/action-bar/action-bar.component.ts b/src/app/components/stream/status/action-bar/action-bar.component.ts index 3cb6f9bf..0bac8ec1 100644 --- a/src/app/components/stream/status/action-bar/action-bar.component.ts +++ b/src/app/components/stream/status/action-bar/action-bar.component.ts @@ -4,6 +4,7 @@ import { Store } from '@ngxs/store'; import { Observable, Subscription } from 'rxjs'; import { faWindowClose, faReply, faRetweet, faStar, faEllipsisH, faLock } from "@fortawesome/free-solid-svg-icons"; import { faWindowClose as faWindowCloseRegular } from "@fortawesome/free-regular-svg-icons"; +import { ContextMenuComponent, ContextMenuService } from 'ngx-contextmenu'; import { MastodonService } from '../../../../services/mastodon.service'; import { AccountInfo } from '../../../../states/accounts.state'; @@ -11,8 +12,7 @@ import { Status, Account } from '../../../../services/models/mastodon.interfaces import { ToolsService } from '../../../../services/tools.service'; import { NotificationService } from '../../../../services/notification.service'; import { StatusWrapper } from '../../../../models/common.model'; - -import { ContextMenuComponent, ContextMenuService } from 'ngx-contextmenu'; +import { NavigationService } from '../../../../services/navigation.service'; @Component({ selector: 'app-action-bar', @@ -59,7 +59,8 @@ export class ActionBarComponent implements OnInit, OnDestroy { private accountSub: Subscription; constructor( - private contextMenuService: ContextMenuService, + private readonly navigationService: NavigationService, + private readonly contextMenuService: ContextMenuService, private readonly store: Store, private readonly toolsService: ToolsService, private readonly mastodonService: MastodonService, @@ -97,7 +98,7 @@ export class ActionBarComponent implements OnInit, OnDestroy { private extractHandle(account: Account) { this.username = account.acct.split('@')[0]; - this.fullHandle = account.acct; + this.fullHandle = account.acct.toLowerCase(); if (!this.fullHandle.includes('@')) { this.fullHandle += `@${account.url.replace('https://', '').split('/')[0]}`; } @@ -273,13 +274,12 @@ export class ActionBarComponent implements OnInit, OnDestroy { } mentionAccount(): boolean { - - + this.navigationService.replyToUser(this.fullHandle, false); return false; } dmAccount(): boolean { - + this.navigationService.replyToUser(this.fullHandle, true); return false; } diff --git a/src/app/services/navigation.service.ts b/src/app/services/navigation.service.ts index 9704ceca..6998f620 100644 --- a/src/app/services/navigation.service.ts +++ b/src/app/services/navigation.service.ts @@ -7,7 +7,7 @@ import { OpenMediaEvent } from '../models/common.model'; @Injectable() export class NavigationService { private accountToManage: AccountWrapper; - activatedPanelSubject = new BehaviorSubject(LeftPanelType.Closed); + activatedPanelSubject = new BehaviorSubject(new OpenLeftPanelEvent(LeftPanelType.Closed)); activatedMediaSubject: Subject = new Subject(); columnSelectedSubject = new BehaviorSubject(-1); @@ -15,18 +15,27 @@ export class NavigationService { openColumnEditor(acc: AccountWrapper) { this.accountToManage = acc; - this.activatedPanelSubject.next(LeftPanelType.ManageAccount); + const newEvent = new OpenLeftPanelEvent(LeftPanelType.ManageAccount); + this.activatedPanelSubject.next(newEvent); } openPanel(type: LeftPanelType){ - this.activatedPanelSubject.next(type); + const newEvent = new OpenLeftPanelEvent(type); + this.activatedPanelSubject.next(newEvent); } closePanel() { - this.activatedPanelSubject.next(LeftPanelType.Closed); + const newEvent = new OpenLeftPanelEvent(LeftPanelType.Closed); + this.activatedPanelSubject.next(newEvent); this.accountToManage = null; } + replyToUser(userHandle: string, isDirectMessage: boolean = false) { + const action = isDirectMessage ? LeftPanelAction.DM : LeftPanelAction.Mention; + const newEvent = new OpenLeftPanelEvent(LeftPanelType.CreateNewStatus, action, userHandle); + this.activatedPanelSubject.next(newEvent); + } + columnSelected(index: number): void { this.columnSelectedSubject.next(index); } @@ -40,6 +49,20 @@ export class NavigationService { } } +export class OpenLeftPanelEvent { + constructor( + public type: LeftPanelType, + public action: LeftPanelAction = LeftPanelAction.None, + public userHandle: string = null ) { + } +} + +export enum LeftPanelAction { + None = 0, + DM = 1, + Mention = 2 +} + export enum LeftPanelType { Closed = 0, ManageAccount = 1,