mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-09-14 13:04:59 +00:00
Sticker pack selection (without widget)
This is the UI where the user can pick which stickers they want. This does not add the widget yet though. Helps towards #156
This commit is contained in:
parent
e8274c9d87
commit
7a0af05ac4
@ -1,40 +1,9 @@
|
|||||||
import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest";
|
import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest";
|
||||||
import { AdminService } from "./AdminService";
|
import { AdminService } from "./AdminService";
|
||||||
import { Cache, CACHE_STICKERS } from "../../MemoryCache";
|
|
||||||
import StickerPack from "../../db/models/StickerPack";
|
import StickerPack from "../../db/models/StickerPack";
|
||||||
import Sticker from "../../db/models/Sticker";
|
|
||||||
import { ApiError } from "../ApiError";
|
import { ApiError } from "../ApiError";
|
||||||
|
import { DimensionStickerService, MemoryStickerPack } from "../dimension/DimensionStickerService";
|
||||||
export interface MemoryStickerPack {
|
import { Cache, CACHE_STICKERS } from "../../MemoryCache";
|
||||||
id: number;
|
|
||||||
displayName: string;
|
|
||||||
avatarUrl: string;
|
|
||||||
description: string;
|
|
||||||
isEnabled: boolean;
|
|
||||||
author: {
|
|
||||||
type: string;
|
|
||||||
name: string;
|
|
||||||
reference: string;
|
|
||||||
};
|
|
||||||
license: {
|
|
||||||
name: string;
|
|
||||||
urlPath: string;
|
|
||||||
};
|
|
||||||
stickers: {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
image: {
|
|
||||||
mxc: string;
|
|
||||||
mimetype: string;
|
|
||||||
};
|
|
||||||
thumbnail: {
|
|
||||||
mxc: string;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
};
|
|
||||||
}[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SetEnabledRequest {
|
interface SetEnabledRequest {
|
||||||
isEnabled: boolean;
|
isEnabled: boolean;
|
||||||
@ -46,61 +15,11 @@ interface SetEnabledRequest {
|
|||||||
@Path("/api/v1/dimension/admin/stickers")
|
@Path("/api/v1/dimension/admin/stickers")
|
||||||
export class AdminStickerService {
|
export class AdminStickerService {
|
||||||
|
|
||||||
public static async getStickerPacks(enabledOnly: boolean = false): Promise<MemoryStickerPack[]> {
|
|
||||||
const cachedPacks = Cache.for(CACHE_STICKERS).get("packs");
|
|
||||||
if (cachedPacks) {
|
|
||||||
if (enabledOnly) return cachedPacks.filter(p => p.isEnabled);
|
|
||||||
return cachedPacks;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dbPacks = await StickerPack.findAll();
|
|
||||||
const packs: MemoryStickerPack[] = [];
|
|
||||||
for (const pack of dbPacks) {
|
|
||||||
const stickers = await Sticker.findAll({where: {packId: pack.id}});
|
|
||||||
packs.push(<MemoryStickerPack>{
|
|
||||||
id: pack.id,
|
|
||||||
displayName: pack.name,
|
|
||||||
avatarUrl: pack.avatarUrl,
|
|
||||||
description: pack.description,
|
|
||||||
isEnabled: pack.isEnabled,
|
|
||||||
author: {
|
|
||||||
type: pack.authorType,
|
|
||||||
name: pack.authorName,
|
|
||||||
reference: pack.authorReference,
|
|
||||||
},
|
|
||||||
license: {
|
|
||||||
name: pack.license,
|
|
||||||
urlPath: pack.licensePath,
|
|
||||||
},
|
|
||||||
stickers: stickers.map(s => {
|
|
||||||
return {
|
|
||||||
id: s.id,
|
|
||||||
name: s.name,
|
|
||||||
description: s.description,
|
|
||||||
image: {
|
|
||||||
mxc: s.imageMxc,
|
|
||||||
mimetype: s.mimetype,
|
|
||||||
},
|
|
||||||
thumbnail: {
|
|
||||||
mxc: s.thumbnailMxc,
|
|
||||||
width: s.thumbnailWidth,
|
|
||||||
height: s.thumbnailHeight,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Cache.for(CACHE_STICKERS).put("packs", packs);
|
|
||||||
if (enabledOnly) return packs.filter(p => p.isEnabled);
|
|
||||||
return packs;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("packs")
|
@Path("packs")
|
||||||
public async getStickerPacks(@QueryParam("scalar_token") scalarToken: string): Promise<MemoryStickerPack[]> {
|
public async getStickerPacks(@QueryParam("scalar_token") scalarToken: string): Promise<MemoryStickerPack[]> {
|
||||||
await AdminService.validateAndGetAdminTokenOwner(scalarToken);
|
await AdminService.validateAndGetAdminTokenOwner(scalarToken);
|
||||||
return await AdminStickerService.getStickerPacks();
|
return await DimensionStickerService.getStickerPacks(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@ -112,6 +31,7 @@ export class AdminStickerService {
|
|||||||
|
|
||||||
pack.isEnabled = request.isEnabled;
|
pack.isEnabled = request.isEnabled;
|
||||||
await pack.save();
|
await pack.save();
|
||||||
|
Cache.for(CACHE_STICKERS).clear();
|
||||||
|
|
||||||
return {}; // 200 OK
|
return {}; // 200 OK
|
||||||
}
|
}
|
||||||
|
156
src/api/dimension/DimensionStickerService.ts
Normal file
156
src/api/dimension/DimensionStickerService.ts
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
import { GET, Path, PathParam, POST, QueryParam } from "typescript-rest";
|
||||||
|
import { Cache, CACHE_STICKERS } from "../../MemoryCache";
|
||||||
|
import StickerPack from "../../db/models/StickerPack";
|
||||||
|
import Sticker from "../../db/models/Sticker";
|
||||||
|
import { ScalarService } from "../scalar/ScalarService";
|
||||||
|
import UserStickerPack from "../../db/models/UserStickerPack";
|
||||||
|
import { ApiError } from "../ApiError";
|
||||||
|
|
||||||
|
export interface MemoryStickerPack {
|
||||||
|
id: number;
|
||||||
|
displayName: string;
|
||||||
|
avatarUrl: string;
|
||||||
|
description: string;
|
||||||
|
isEnabled: boolean;
|
||||||
|
author: {
|
||||||
|
type: string;
|
||||||
|
name: string;
|
||||||
|
reference: string;
|
||||||
|
};
|
||||||
|
license: {
|
||||||
|
name: string;
|
||||||
|
urlPath: string;
|
||||||
|
};
|
||||||
|
stickers: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
image: {
|
||||||
|
mxc: string;
|
||||||
|
mimetype: string;
|
||||||
|
};
|
||||||
|
thumbnail: {
|
||||||
|
mxc: string;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
};
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MemoryUserStickerPack extends MemoryStickerPack {
|
||||||
|
isSelected: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SetSelectedRequest {
|
||||||
|
isSelected: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API for stickers
|
||||||
|
*/
|
||||||
|
@Path("/api/v1/dimension/stickers")
|
||||||
|
export class DimensionStickerService {
|
||||||
|
|
||||||
|
public static async getStickerPacks(enabledOnly: boolean = false): Promise<MemoryStickerPack[]> {
|
||||||
|
const cachedPacks = Cache.for(CACHE_STICKERS).get("packs");
|
||||||
|
if (cachedPacks) {
|
||||||
|
if (enabledOnly) return cachedPacks.filter(p => p.isEnabled);
|
||||||
|
return cachedPacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dbPacks = await StickerPack.findAll();
|
||||||
|
const packs: MemoryStickerPack[] = [];
|
||||||
|
for (const pack of dbPacks) {
|
||||||
|
packs.push(await DimensionStickerService.packToMemory(pack));
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache.for(CACHE_STICKERS).put("packs", packs);
|
||||||
|
if (enabledOnly) return packs.filter(p => p.isEnabled);
|
||||||
|
return packs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("packs")
|
||||||
|
public async getStickerPacks(@QueryParam("scalar_token") scalarToken: string): Promise<MemoryStickerPack[]> {
|
||||||
|
const userId = await ScalarService.getTokenOwner(scalarToken);
|
||||||
|
|
||||||
|
const cachedPacks = Cache.for(CACHE_STICKERS).get("packs_" + userId);
|
||||||
|
if (cachedPacks) return cachedPacks;
|
||||||
|
|
||||||
|
const allPacks = await DimensionStickerService.getStickerPacks(true);
|
||||||
|
if (allPacks.length === 0) return []; // We can just skip the database call
|
||||||
|
|
||||||
|
const userPacks = await UserStickerPack.findAll({where: {userId: userId, isSelected: true}});
|
||||||
|
|
||||||
|
const packs: MemoryUserStickerPack[] = [];
|
||||||
|
for (const pack of allPacks) {
|
||||||
|
const userPack = userPacks.find(p => p.packId === pack.id);
|
||||||
|
|
||||||
|
const selectedPack = JSON.parse(JSON.stringify(pack));
|
||||||
|
selectedPack.isSelected = userPack ? userPack.isSelected : false;
|
||||||
|
packs.push(selectedPack);
|
||||||
|
}
|
||||||
|
|
||||||
|
Cache.for(CACHE_STICKERS).put("packs_" + userId, packs);
|
||||||
|
return packs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("packs/:packId/selected")
|
||||||
|
public async setPackSelected(@QueryParam("scalar_token") scalarToken: string, @PathParam("packId") packId: number, request: SetSelectedRequest): Promise<any> {
|
||||||
|
const userId = await ScalarService.getTokenOwner(scalarToken);
|
||||||
|
|
||||||
|
const pack = await StickerPack.findByPrimary(packId);
|
||||||
|
if (!pack) throw new ApiError(404, "Sticker pack not found");
|
||||||
|
|
||||||
|
let userPack = await UserStickerPack.findOne({where: {userId: userId, packId: packId}});
|
||||||
|
if (!userPack) {
|
||||||
|
userPack = await UserStickerPack.create({
|
||||||
|
packId: packId,
|
||||||
|
userId: userId,
|
||||||
|
isSelected: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
userPack.isSelected = request.isSelected;
|
||||||
|
await userPack.save();
|
||||||
|
return {}; // 200 OK
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async packToMemory(pack: StickerPack): Promise<MemoryStickerPack> {
|
||||||
|
const stickers = await Sticker.findAll({where: {packId: pack.id}});
|
||||||
|
return {
|
||||||
|
id: pack.id,
|
||||||
|
displayName: pack.name,
|
||||||
|
avatarUrl: pack.avatarUrl,
|
||||||
|
description: pack.description,
|
||||||
|
isEnabled: pack.isEnabled,
|
||||||
|
author: {
|
||||||
|
type: pack.authorType,
|
||||||
|
name: pack.authorName,
|
||||||
|
reference: pack.authorReference,
|
||||||
|
},
|
||||||
|
license: {
|
||||||
|
name: pack.license,
|
||||||
|
urlPath: pack.licensePath,
|
||||||
|
},
|
||||||
|
stickers: stickers.map(s => {
|
||||||
|
return {
|
||||||
|
id: s.id,
|
||||||
|
name: s.name,
|
||||||
|
description: s.description,
|
||||||
|
image: {
|
||||||
|
mxc: s.imageMxc,
|
||||||
|
mimetype: s.mimetype,
|
||||||
|
},
|
||||||
|
thumbnail: {
|
||||||
|
mxc: s.thumbnailMxc,
|
||||||
|
width: s.thumbnailWidth,
|
||||||
|
height: s.thumbnailHeight,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -20,6 +20,7 @@ import IrcBridgeRecord from "./models/IrcBridgeRecord";
|
|||||||
import IrcBridgeNetwork from "./models/IrcBridgeNetwork";
|
import IrcBridgeNetwork from "./models/IrcBridgeNetwork";
|
||||||
import StickerPack from "./models/StickerPack";
|
import StickerPack from "./models/StickerPack";
|
||||||
import Sticker from "./models/Sticker";
|
import Sticker from "./models/Sticker";
|
||||||
|
import UserStickerPack from "./models/UserStickerPack";
|
||||||
|
|
||||||
class _DimensionStore {
|
class _DimensionStore {
|
||||||
private sequelize: Sequelize;
|
private sequelize: Sequelize;
|
||||||
@ -51,6 +52,7 @@ class _DimensionStore {
|
|||||||
IrcBridgeNetwork,
|
IrcBridgeNetwork,
|
||||||
StickerPack,
|
StickerPack,
|
||||||
Sticker,
|
Sticker,
|
||||||
|
UserStickerPack,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
24
src/db/migrations/20180512232045-AddUserStickerPacks.ts
Normal file
24
src/db/migrations/20180512232045-AddUserStickerPacks.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { QueryInterface } from "sequelize";
|
||||||
|
import { DataType } from "sequelize-typescript";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
up: (queryInterface: QueryInterface) => {
|
||||||
|
return queryInterface.createTable("dimension_user_sticker_packs", {
|
||||||
|
"id": {type: DataType.INTEGER, primaryKey: true, autoIncrement: true, allowNull: false},
|
||||||
|
"packId": {
|
||||||
|
type: DataType.INTEGER, allowNull: false,
|
||||||
|
references: {model: "dimension_sticker_packs", key: "id"},
|
||||||
|
onUpdate: "cascade", onDelete: "cascade",
|
||||||
|
},
|
||||||
|
"userId": {
|
||||||
|
type: DataType.STRING, allowNull: false,
|
||||||
|
references: {model: "dimension_users", key: "userId"},
|
||||||
|
onUpdate: "cascade", onDelete: "cascade",
|
||||||
|
},
|
||||||
|
"isSelected": {type: DataType.BOOLEAN, allowNull: false},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
down: (queryInterface: QueryInterface) => {
|
||||||
|
return queryInterface.dropTable("dimension_user_sticker_packs");
|
||||||
|
}
|
||||||
|
}
|
26
src/db/models/UserStickerPack.ts
Normal file
26
src/db/models/UserStickerPack.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { AutoIncrement, Column, ForeignKey, Model, PrimaryKey, Table } from "sequelize-typescript";
|
||||||
|
import StickerPack from "./StickerPack";
|
||||||
|
import User from "./User";
|
||||||
|
|
||||||
|
@Table({
|
||||||
|
tableName: "dimension_user_sticker_packs",
|
||||||
|
underscoredAll: false,
|
||||||
|
timestamps: false,
|
||||||
|
})
|
||||||
|
export default class UserStickerPack extends Model<UserStickerPack> {
|
||||||
|
@PrimaryKey
|
||||||
|
@AutoIncrement
|
||||||
|
@Column
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ForeignKey(() => StickerPack)
|
||||||
|
packId: number;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
@ForeignKey(() => User)
|
||||||
|
userId: string;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
isSelected: boolean;
|
||||||
|
}
|
@ -75,6 +75,8 @@ import { AdminStickersApiService } from "./shared/services/admin/admin-stickers-
|
|||||||
import { AdminStickerPacksComponent } from "./admin/sticker-packs/sticker-packs.component";
|
import { AdminStickerPacksComponent } from "./admin/sticker-packs/sticker-packs.component";
|
||||||
import { AdminStickerPackPreviewComponent } from "./admin/sticker-packs/preview/preview.component";
|
import { AdminStickerPackPreviewComponent } from "./admin/sticker-packs/preview/preview.component";
|
||||||
import { MediaService } from "./shared/services/media.service";
|
import { MediaService } from "./shared/services/media.service";
|
||||||
|
import { StickerApiService } from "./shared/services/integrations/sticker-api.service";
|
||||||
|
import { StickerpickerComponent } from "./configs/stickerpicker/stickerpicker.component";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -140,6 +142,7 @@ import { MediaService } from "./shared/services/media.service";
|
|||||||
ScreenshotCapableDirective,
|
ScreenshotCapableDirective,
|
||||||
AdminStickerPacksComponent,
|
AdminStickerPacksComponent,
|
||||||
AdminStickerPackPreviewComponent,
|
AdminStickerPackPreviewComponent,
|
||||||
|
StickerpickerComponent,
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
],
|
],
|
||||||
@ -158,6 +161,7 @@ import { MediaService } from "./shared/services/media.service";
|
|||||||
IrcApiService,
|
IrcApiService,
|
||||||
AdminStickersApiService,
|
AdminStickersApiService,
|
||||||
MediaService,
|
MediaService,
|
||||||
|
StickerApiService,
|
||||||
{provide: Window, useValue: window},
|
{provide: Window, useValue: window},
|
||||||
|
|
||||||
// Vendor
|
// Vendor
|
||||||
|
@ -25,6 +25,7 @@ import { AdminBridgesComponent } from "./admin/bridges/bridges.component";
|
|||||||
import { AdminIrcBridgeComponent } from "./admin/bridges/irc/irc.component";
|
import { AdminIrcBridgeComponent } from "./admin/bridges/irc/irc.component";
|
||||||
import { IrcBridgeConfigComponent } from "./configs/bridge/irc/irc.bridge.component";
|
import { IrcBridgeConfigComponent } from "./configs/bridge/irc/irc.bridge.component";
|
||||||
import { AdminStickerPacksComponent } from "./admin/sticker-packs/sticker-packs.component";
|
import { AdminStickerPacksComponent } from "./admin/sticker-packs/sticker-packs.component";
|
||||||
|
import { StickerpickerComponent } from "./configs/stickerpicker/stickerpicker.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{path: "", component: HomeComponent},
|
{path: "", component: HomeComponent},
|
||||||
@ -164,6 +165,11 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "stickerpicker",
|
||||||
|
component: StickerpickerComponent,
|
||||||
|
data: {breadcrumb: "Your Sticker Packs", name: "Your Sticker Packs"},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
25
web/app/configs/stickerpicker/stickerpicker.component.html
Normal file
25
web/app/configs/stickerpicker/stickerpicker.component.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<div *ngIf="isLoading">
|
||||||
|
<my-spinner></my-spinner>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="!isLoading">
|
||||||
|
<my-ibox title="Sticker Packs">
|
||||||
|
<div class="my-ibox-content" *ngIf="packs.length <= 0">
|
||||||
|
<h5 style="text-align: center;">Sticker packs are not enabled on this Dimension instance.</h5>
|
||||||
|
</div>
|
||||||
|
<div class="my-ibox-content" *ngIf="packs.length > 0">
|
||||||
|
<div class="pack" *ngFor="let pack of packs trackById">
|
||||||
|
<img [src]="getThumbnailUrl(pack.avatarUrl, 120, 120)" width="120" height="120"/>
|
||||||
|
<div class="caption">
|
||||||
|
<ui-switch [checked]="pack.isSelected" size="medium" [disabled]="isUpdating"
|
||||||
|
(change)="toggleSelected(pack)" class="toggle-switch"></ui-switch>
|
||||||
|
|
||||||
|
<span class="name">{{ pack.displayName }}</span>
|
||||||
|
<span class="description">{{ pack.description }}</span>
|
||||||
|
|
||||||
|
<span class="author" *ngIf="pack.author.type !== 'none'">Created by <a [href]="pack.author.reference">{{ pack.author.name }}</a> under </span>
|
||||||
|
<span class="license"><a [href]="pack.license.urlPath">{{ pack.license.name }}</a></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</my-ibox>
|
||||||
|
</div>
|
38
web/app/configs/stickerpicker/stickerpicker.component.scss
Normal file
38
web/app/configs/stickerpicker/stickerpicker.component.scss
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
.pack {
|
||||||
|
display: flex;
|
||||||
|
margin: 20px;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: #f6fbff;
|
||||||
|
|
||||||
|
.caption {
|
||||||
|
flex: 1;
|
||||||
|
margin-left: 20px;
|
||||||
|
padding-top: 20px;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
color: #7d7d7d;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-switch {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.author, .license {
|
||||||
|
font-size: 0.8em;
|
||||||
|
color: #7d7d7d;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #7d7d7d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
web/app/configs/stickerpicker/stickerpicker.component.ts
Normal file
52
web/app/configs/stickerpicker/stickerpicker.component.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { FE_UserStickerPack } from "../../shared/models/integration";
|
||||||
|
import { StickerApiService } from "../../shared/services/integrations/sticker-api.service";
|
||||||
|
import { ToasterService } from "angular2-toaster";
|
||||||
|
import { MediaService } from "../../shared/services/media.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "stickerpicker.component.html",
|
||||||
|
styleUrls: ["stickerpicker.component.scss"],
|
||||||
|
})
|
||||||
|
export class StickerpickerComponent implements OnInit {
|
||||||
|
|
||||||
|
public isLoading = true;
|
||||||
|
public isUpdating = false;
|
||||||
|
public packs: FE_UserStickerPack[];
|
||||||
|
|
||||||
|
constructor(private stickerApi: StickerApiService,
|
||||||
|
private media: MediaService,
|
||||||
|
private toaster: ToasterService) {
|
||||||
|
this.isLoading = true;
|
||||||
|
this.isUpdating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ngOnInit() {
|
||||||
|
try {
|
||||||
|
this.packs = await this.stickerApi.getPacks();
|
||||||
|
this.isLoading = false;
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
this.toaster.pop("error", "Failed to load sticker packs");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public getThumbnailUrl(mxc: string, width: number, height: number, method: "crop" | "scale" = "scale"): string {
|
||||||
|
return this.media.getThumbnailUrl(mxc, width, height, method, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public toggleSelected(pack: FE_UserStickerPack) {
|
||||||
|
pack.isSelected = !pack.isSelected;
|
||||||
|
this.isUpdating = true;
|
||||||
|
this.stickerApi.togglePackSelection(pack.id, pack.isSelected).then(() => {
|
||||||
|
this.isUpdating = false;
|
||||||
|
this.toaster.pop("success", "Stickers updated");
|
||||||
|
// TODO: Add the user widget when we have >1 sticker pack selected
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
pack.isSelected = !pack.isSelected; // revert change
|
||||||
|
this.isUpdating = false;
|
||||||
|
this.toaster.pop("error", "Error updating stickers");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -195,6 +195,12 @@ export class RiotHomeComponent {
|
|||||||
let type = null;
|
let type = null;
|
||||||
if (!this.requestedScreen) return;
|
if (!this.requestedScreen) return;
|
||||||
|
|
||||||
|
if (this.requestedScreen === "type_m.stickerpicker") {
|
||||||
|
console.log("Intercepting config screen handling to open sticker picker config");
|
||||||
|
this.router.navigate(['riot-app', 'stickerpicker']);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const targetIntegration = IntegrationsRegistry.getIntegrationForScreen(this.requestedScreen);
|
const targetIntegration = IntegrationsRegistry.getIntegrationForScreen(this.requestedScreen);
|
||||||
if (targetIntegration) {
|
if (targetIntegration) {
|
||||||
category = targetIntegration.category;
|
category = targetIntegration.category;
|
||||||
|
@ -44,6 +44,10 @@ export interface FE_StickerPack extends FE_Integration {
|
|||||||
stickers: FE_Sticker[];
|
stickers: FE_Sticker[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface FE_UserStickerPack extends FE_StickerPack {
|
||||||
|
isSelected: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface FE_Sticker {
|
export interface FE_Sticker {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
|
19
web/app/shared/services/integrations/sticker-api.service.ts
Normal file
19
web/app/shared/services/integrations/sticker-api.service.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
import { Http } from "@angular/http";
|
||||||
|
import { AuthedApi } from "../authed-api";
|
||||||
|
import { FE_UserStickerPack } from "../../models/integration";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class StickerApiService extends AuthedApi {
|
||||||
|
constructor(http: Http) {
|
||||||
|
super(http);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getPacks(): Promise<FE_UserStickerPack[]> {
|
||||||
|
return this.authedGet("/api/v1/dimension/stickers/packs").map(r => r.json()).toPromise();
|
||||||
|
}
|
||||||
|
|
||||||
|
public togglePackSelection(packId: number, isSelected: boolean): Promise<any> {
|
||||||
|
return this.authedPost("/api/v1/dimension/stickers/packs/" + packId + "/selected", {isSelected: isSelected}).map(r => r.json()).toPromise();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user