Merge pull request #144 from NicolasConstant/topic_emoji-picker

Topic emoji picker
This commit is contained in:
Nicolas Constant 2019-07-29 22:19:41 -04:00 committed by GitHub
commit 72cf69d9c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 87 additions and 24 deletions

View File

@ -1,8 +1,5 @@
<emoji-mart
[showPreview]="false"
[perLine]="7"
[isNative]="true"
[sheetSize]="16"
[emojiTooltip]="true"
(emojiSelect)="emojiSelected($event)"
class="emojipicker" title="Pick your emoji…" emoji="point_up"></emoji-mart>
*ngIf="loaded"
[showPreview]="false" [perLine]="7" [isNative]="true" [sheetSize]="16" [emojiTooltip]="true"
[custom]="customEmojis" (emojiSelect)="emojiSelected($event)" class="emojipicker" title="Pick your emoji…"
emoji="point_up"></emoji-mart>

View File

@ -13,4 +13,10 @@
left: -1px;
font-size: 19px !important;
cursor: pointer !important;
}
::ng-deep .emoji-mart-emoji-custom span {
position: relative;
top: 0px;
left: 0px;
}

View File

@ -1,5 +1,9 @@
import { Component, OnInit, HostListener, ElementRef, Output, EventEmitter } from '@angular/core';
import { ToolsService } from '../../../services/tools.service';
import { NotificationService } from '../../../services/notification.service';
import { Emoji } from '../../../services/models/mastodon.interfaces';
@Component({
selector: 'app-emoji-picker',
templateUrl: './emoji-picker.component.html',
@ -11,25 +15,62 @@ export class EmojiPickerComponent implements OnInit {
@Output('closed') public closedEvent = new EventEmitter();
@Output('emojiSelected') public emojiSelectedEvent = new EventEmitter<string>();
constructor(private eRef: ElementRef) { }
customEmojis: PickerCustomEmoji[] = [];
loaded: boolean;
constructor(
private notificationService: NotificationService,
private toolsService: ToolsService,
private eRef: ElementRef) { }
@HostListener('document:click', ['$event'])
clickout(event) {
if (!this.init) return;
if (!this.eRef.nativeElement.contains(event.target)) {
if (!this.eRef.nativeElement.contains(event.target)) {
this.closedEvent.emit(null);
}
}
ngOnInit() {
let currentAccount = this.toolsService.getSelectedAccounts()[0];
this.toolsService.getCustomEmojis(currentAccount)
.then(emojis => {
console.warn(emojis);
this.customEmojis = emojis.map(x => this.convertEmoji(x));
})
.catch(err => {
this.notificationService.notifyHttpError(err);
})
.then(() => {
this.loaded = true;
});
setTimeout(() => {
this.init = true;
}, 0);
}
private convertEmoji(emoji: Emoji): PickerCustomEmoji {
return new PickerCustomEmoji(emoji.shortcode, [emoji.shortcode], emoji.shortcode, [emoji.shortcode], emoji.url);
}
emojiSelected(select: any): boolean {
this.emojiSelectedEvent.next(select.emoji.native);
if (select.emoji.custom) {
this.emojiSelectedEvent.next(select.emoji.colons);
} else {
this.emojiSelectedEvent.next(select.emoji.native);
}
return false;
}
}
class PickerCustomEmoji {
constructor(
public name: string,
public shortNames: string[],
public text: string,
public keywords: string[],
public imageUrl: string) {
}
}

View File

@ -2,12 +2,12 @@ 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 } from "./models/mastodon.interfaces";
import { Account, Status, Results, Context, Relationship, Instance, Attachment, Notification, List, Poll, Emoji } from "./models/mastodon.interfaces";
import { AccountInfo } from '../states/accounts.state';
import { StreamTypeEnum, StreamElement } from '../states/streams.state';
@Injectable()
export class MastodonService {
export class MastodonService {
private apiRoutes = new ApiRoutes();
constructor(private readonly httpClient: HttpClient) { }
@ -367,6 +367,11 @@ export class MastodonService {
let route = `https://${account.instance}${this.apiRoutes.deleteStatus}`.replace('{0}', statusId.toString());
const headers = new HttpHeaders({ 'Authorization': `Bearer ${account.token.access_token}` });
return this.httpClient.delete<any>(route, { headers: headers }).toPromise();
}
getCustomEmojis(account: AccountInfo): Promise<Emoji[]> {
let route = `https://${account.instance}${this.apiRoutes.getCustomEmojis}`;
return this.httpClient.get<Emoji[]>(route).toPromise();
}
}

View File

@ -3,6 +3,7 @@ export class ApiRoutes {
createApp = '/api/v1/apps';
getToken = '/oauth/token';
getAccount = '/api/v1/accounts/{0}';
getCustomEmojis = '/api/v1/custom_emojis';
getCurrentAccount = '/api/v1/accounts/verify_credentials';
getAccountFollowers = '/api/v1/accounts/{0}/followers';
getAccountFollowing = '/api/v1/accounts/{0}/following';

View File

@ -3,7 +3,7 @@ import { Store } from '@ngxs/store';
import { AccountInfo } from '../states/accounts.state';
import { MastodonService } from './mastodon.service';
import { Account, Results, Status } from "./models/mastodon.interfaces";
import { Account, Results, Status, Emoji } from "./models/mastodon.interfaces";
import { StatusWrapper } from '../models/common.model';
import { AccountSettings, SaveAccountSettings } from '../states/settings.state';
@ -20,23 +20,23 @@ export class ToolsService {
var regAccounts = <AccountInfo[]>this.store.snapshot().registeredaccounts.accounts;
return regAccounts.filter(x => x.isSelected);
}
getAccountSettings(account: AccountInfo): AccountSettings {
var accountsSettings = <AccountSettings[]>this.store.snapshot().globalsettings.settings.accountSettings;
let accountSettings = accountsSettings.find(x => x.accountId === account.id);
if(!accountSettings){
if (!accountSettings) {
accountSettings = new AccountSettings();
accountSettings.accountId = account.id;
this.saveAccountSettings(accountSettings);
this.saveAccountSettings(accountSettings);
}
if(!accountSettings.customStatusCharLength){
if (!accountSettings.customStatusCharLength) {
accountSettings.customStatusCharLength = 500;
this.saveAccountSettings(accountSettings);
}
return accountSettings;
}
saveAccountSettings(accountSettings: AccountSettings){
saveAccountSettings(accountSettings: AccountSettings) {
this.store.dispatch([
new SaveAccountSettings(accountSettings)
])
@ -45,19 +45,19 @@ export class ToolsService {
findAccount(account: AccountInfo, accountName: string): Promise<Account> {
return this.mastodonService.search(account, accountName, true)
.then((result: Results) => {
if(accountName[0] === '@') accountName = accountName.substr(1);
if (accountName[0] === '@') accountName = accountName.substr(1);
const foundAccount = result.accounts.find(
x => (x.acct.toLowerCase() === accountName.toLowerCase()
||
(x.acct.toLowerCase().split('@')[0] === accountName.toLowerCase().split('@')[0])
&& x.url.replace('https://', '').split('/')[0] === accountName.toLowerCase().split('@')[1])
);
||
(x.acct.toLowerCase().split('@')[0] === accountName.toLowerCase().split('@')[0])
&& x.url.replace('https://', '').split('/')[0] === accountName.toLowerCase().split('@')[1])
);
return foundAccount;
});
}
getStatusUsableByAccount(account: AccountInfo, originalStatus: StatusWrapper): Promise<Status>{
getStatusUsableByAccount(account: AccountInfo, originalStatus: StatusWrapper): Promise<Status> {
const isProvider = originalStatus.provider.id === account.id;
let statusPromise: Promise<Status> = Promise.resolve(originalStatus.status);
@ -82,6 +82,19 @@ export class ToolsService {
}
return `@${fullHandle}`;
}
private emojiCache: { [id: string]: Emoji[] } = {};
getCustomEmojis(account: AccountInfo): Promise<Emoji[]> {
if (this.emojiCache[account.id]) {
return Promise.resolve(this.emojiCache[account.id]);
} else {
return this.mastodonService.getCustomEmojis(account)
.then(emojis => {
this.emojiCache[account.id] = emojis.filter(x => x.visible_in_picker);
return this.emojiCache[account.id];
});
}
}
}
export class OpenThreadEvent {