diff --git a/wowup-electron/src/app/core/addon-providers/addon-provider.ts b/wowup-electron/src/app/core/addon-providers/addon-provider.ts index d7d3a23c..26d03807 100644 --- a/wowup-electron/src/app/core/addon-providers/addon-provider.ts +++ b/wowup-electron/src/app/core/addon-providers/addon-provider.ts @@ -1,7 +1,7 @@ -import { WowClientType } from "app/models/warcraft/wow-client-type"; +import { WowClientType } from "../../models/warcraft/wow-client-type"; import { Addon } from "../entities/addon"; -import { PotentialAddon } from "app/models/wowup/potential-addon"; -import { AddonSearchResult } from "app/models/wowup/addon-search-result"; +import { PotentialAddon } from "../../models/wowup/potential-addon"; +import { AddonSearchResult } from "../../models/wowup/addon-search-result"; export interface AddonProvider { diff --git a/wowup-electron/src/app/core/addon-providers/curse-addon-provider.ts b/wowup-electron/src/app/core/addon-providers/curse-addon-provider.ts index 213fe634..3b931f32 100644 --- a/wowup-electron/src/app/core/addon-providers/curse-addon-provider.ts +++ b/wowup-electron/src/app/core/addon-providers/curse-addon-provider.ts @@ -11,153 +11,181 @@ import { Observable } from "rxjs"; import { AddonSearchResultFile } from "app/models/wowup/addon-search-result-file"; import { CurseReleaseType } from "app/models/curse/curse-release-type"; import { AddonChannelType } from "app/models/wowup/addon-channel-type"; +import { PotentialAddon } from "../../models/wowup/potential-addon"; const API_URL = "https://addons-ecs.forgesvc.net/api/v2"; export class CurseAddonProvider implements AddonProvider { - private readonly _httpClient: HttpClient; + private readonly _httpClient: HttpClient; - public readonly name = "Curse"; + public readonly name = "Curse"; - constructor(httpClient: HttpClient) { - this._httpClient = httpClient; - } + constructor(httpClient: HttpClient) { + this._httpClient = httpClient; + } - getAll(clientType: WowClientType, addonIds: string[]): Promise { - throw new Error("Method not implemented."); - } + getAll(clientType: WowClientType, addonIds: string[]): Promise { + throw new Error("Method not implemented."); + } - getFeaturedAddons(clientType: WowClientType): Promise { - throw new Error("Method not implemented."); - } + getFeaturedAddons(clientType: WowClientType): Promise { - searchByQuery(query: string, clientType: WowClientType): Promise { - throw new Error("Method not implemented."); - } + } - searchByUrl(addonUri: URL, clientType: WowClientType): Promise { - throw new Error("Method not implemented."); - } + searchByQuery(query: string, clientType: WowClientType): Promise { + throw new Error("Method not implemented."); + } - searchByName(addonName: string, folderName: string, clientType: WowClientType, nameOverride?: string): Promise { - throw new Error("Method not implemented."); - } + searchByUrl(addonUri: URL, clientType: WowClientType): Promise { + throw new Error("Method not implemented."); + } - getById(addonId: string, clientType: WowClientType): Promise { - const url = `${API_URL}/addon/${addonId}`; + searchByName(addonName: string, folderName: string, clientType: WowClientType, nameOverride?: string): Promise { + throw new Error("Method not implemented."); + } - return this._httpClient.get(url) - .pipe( - map(result => { - if (!result) { - return null; - } + getById(addonId: string, clientType: WowClientType): Promise { + const url = `${API_URL}/addon/${addonId}`; - const latestFiles = this.getLatestFiles(result, clientType); - if (!latestFiles?.length) { - return null; - } - - return this.getAddonSearchResult(result, latestFiles); - }) - ) - .toPromise(); - } - - isValidAddonUri(addonUri: URL): boolean { - throw new Error("Method not implemented."); - } - - onPostInstall(addon: Addon): void { - throw new Error("Method not implemented."); - } - - private getAddonSearchResult(result: CurseSearchResult, latestFiles: CurseFile[]): AddonSearchResult { - try { - var thumbnailUrl = this.getThumbnailUrl(result); - var id = result.id; - var name = result.name; - var author = this.getAuthor(result); - - var searchResultFiles: AddonSearchResultFile[] = latestFiles.map(lf => { - return { - channelType: this.getChannelType(lf.releaseType), - version: lf.fileName, - downloadUrl: lf.downloadUrl, - folders: this.getFolderNames(lf), - gameVersion: this.getGameVersion(lf) - }; - }); - - var searchResult: AddonSearchResult = { - author, - externalId: id.toString(), - name, - thumbnailUrl, - externalUrl: result.websiteUrl, - providerName: this.name, - files: searchResultFiles - }; - - return searchResult; - } catch (e) { - console.error(e); + return this._httpClient.get(url) + .pipe( + map(result => { + if (!result) { return null; - } - } + } - private getChannelType(releaseType: CurseReleaseType): AddonChannelType { - switch (releaseType) { - case CurseReleaseType.Alpha: - return AddonChannelType.Alpha; - case CurseReleaseType.Beta: - return AddonChannelType.Beta; - case CurseReleaseType.Release: - default: - return AddonChannelType.Stable; - } - } + const latestFiles = this.getLatestFiles(result, clientType); + if (!latestFiles?.length) { + return null; + } - private getFolderNames(file: CurseFile): string[] { - return file.modules.map(m => m.foldername); - } + return this.getAddonSearchResult(result, latestFiles); + }) + ) + .toPromise(); + } - private getGameVersion(file: CurseFile): string { - return _.first(file.gameVersion); - } + isValidAddonUri(addonUri: URL): boolean { + throw new Error("Method not implemented."); + } - private getAuthor(result: CurseSearchResult): string { - var authorNames = result.authors.map(a => a.name); - return authorNames.join(', '); - } + onPostInstall(addon: Addon): void { + throw new Error("Method not implemented."); + } - private getThumbnailUrl(result: CurseSearchResult): string { - const attachment = _.find(result.attachments, f => f.isDefault && !!f.thumbnailUrl); - return attachment?.thumbnailUrl; - } + private getAddonSearchResult(result: CurseSearchResult, latestFiles: CurseFile[]): AddonSearchResult { + try { + var thumbnailUrl = this.getThumbnailUrl(result); + var id = result.id; + var name = result.name; + var author = this.getAuthor(result); - private getLatestFiles(result: CurseSearchResult, clientType: WowClientType): CurseFile[] { - const clientTypeStr = this.getClientTypeString(clientType); + var searchResultFiles: AddonSearchResultFile[] = latestFiles.map(lf => { + return { + channelType: this.getChannelType(lf.releaseType), + version: lf.fileName, + downloadUrl: lf.downloadUrl, + folders: this.getFolderNames(lf), + gameVersion: this.getGameVersion(lf) + }; + }); - return _.flow( - _.filter((f: CurseFile) => f.isAlternate == false && f.gameVersionFlavor == clientTypeStr), - _.orderBy((f: CurseFile) => f.id), - _.reverse - )(result.latestFiles) as CurseFile[]; - } + var searchResult: AddonSearchResult = { + author, + externalId: id.toString(), + name, + thumbnailUrl, + externalUrl: result.websiteUrl, + providerName: this.name, + files: searchResultFiles + }; - private getClientTypeString(clientType: WowClientType): string { - switch (clientType) { - case WowClientType.Classic: - case WowClientType.ClassicPtr: - return "wow_classic"; - case WowClientType.Retail: - case WowClientType.RetailPtr: - case WowClientType.Beta: - default: - return "wow_retail"; - } + return searchResult; + } catch (e) { + console.error(e); + return null; } + } + + private getFeaturedAddonList(): Promise { + const url = `${API_URL}/addon/featured`; + const body = { + gameId: 1, + featuredCount: 6, + popularCount: 50, + updatedCount: 0 + }; + + return this._httpClient.post(url, body) + .pipe( + map(result => { + if (!result) { + return null; + } + + const latestFiles = this.getLatestFiles(result, clientType); + if (!latestFiles?.length) { + return null; + } + + return this.getAddonSearchResult(result, latestFiles); + }) + ) + .toPromise(); + } + + private getChannelType(releaseType: CurseReleaseType): AddonChannelType { + switch (releaseType) { + case CurseReleaseType.Alpha: + return AddonChannelType.Alpha; + case CurseReleaseType.Beta: + return AddonChannelType.Beta; + case CurseReleaseType.Release: + default: + return AddonChannelType.Stable; + } + } + + private getFolderNames(file: CurseFile): string[] { + return file.modules.map(m => m.foldername); + } + + private getGameVersion(file: CurseFile): string { + return _.first(file.gameVersion); + } + + private getAuthor(result: CurseSearchResult): string { + var authorNames = result.authors.map(a => a.name); + return authorNames.join(', '); + } + + private getThumbnailUrl(result: CurseSearchResult): string { + const attachment = _.find(result.attachments, f => f.isDefault && !!f.thumbnailUrl); + return attachment?.thumbnailUrl; + } + + private getLatestFiles(result: CurseSearchResult, clientType: WowClientType): CurseFile[] { + const clientTypeStr = this.getClientTypeString(clientType); + + return _.flow( + _.filter((f: CurseFile) => f.isAlternate == false && f.gameVersionFlavor == clientTypeStr), + _.orderBy((f: CurseFile) => f.id), + _.reverse + )(result.latestFiles) as CurseFile[]; + } + + private getClientTypeString(clientType: WowClientType): string { + switch (clientType) { + case WowClientType.Classic: + case WowClientType.ClassicPtr: + return "wow_classic"; + case WowClientType.Retail: + case WowClientType.RetailPtr: + case WowClientType.Beta: + default: + return "wow_retail"; + } + } } \ No newline at end of file diff --git a/wowup-electron/src/app/core/services/addons/addon.service.ts b/wowup-electron/src/app/core/services/addons/addon.service.ts index 207b59bc..2f7c5e0b 100644 --- a/wowup-electron/src/app/core/services/addons/addon.service.ts +++ b/wowup-electron/src/app/core/services/addons/addon.service.ts @@ -1,18 +1,19 @@ import { Injectable } from "@angular/core"; -import { WowClientType } from "app/models/warcraft/wow-client-type"; +import { WowClientType } from "../../../models/warcraft/wow-client-type"; import { AddonStorageService } from "../storage/addon.storage.service"; -import { Addon } from "app/core/entities/addon"; +import { Addon } from "../../entities/addon"; import { WarcraftService } from "../warcraft/warcraft.service"; -import { AddonProvider } from "app/core/addon-providers/addon-provider"; -import { CurseAddonProvider } from "app/core/addon-providers/curse-addon-provider"; +import { AddonProvider } from "../../addon-providers/addon-provider"; +import { CurseAddonProvider } from "../../addon-providers/curse-addon-provider"; import { HttpClient } from "@angular/common/http"; -import { AddonSearchResult } from "app/models/wowup/addon-search-result"; -import { AddonSearchResultFile } from "app/models/wowup/addon-search-result-file"; -import { AddonChannelType } from "app/models/wowup/addon-channel-type"; +import { AddonSearchResult } from "../../../models/wowup/addon-search-result"; +import { AddonSearchResultFile } from "../../../models/wowup/addon-search-result-file"; +import { AddonChannelType } from "../../../models/wowup/addon-channel-type"; import * as _ from 'lodash'; import * as uuid from 'uuid'; -import { AddonFolder } from "app/models/wowup/addon-folder"; +import { AddonFolder } from "../../../models/wowup/addon-folder"; import { WowUpApiService } from "../wowup-api/wowup-api.service"; +import { PotentialAddon } from "../../../models/wowup/potential-addon"; @Injectable({ providedIn: 'root' @@ -51,6 +52,11 @@ export class AddonService { return addons; } + public async getFeaturedAddons(clientType: WowClientType) : Promise{ + const results = await Promise.all(this._addonProviders.map(p => p.getFeaturedAddons(clientType))); + return results.flat(1); + } + private getAllStoredAddons(clientType: WowClientType) { const addons: Addon[] = []; diff --git a/wowup-electron/src/app/get-addons/get-addons.component.ts b/wowup-electron/src/app/get-addons/get-addons.component.ts index dcd7391e..6935278f 100644 --- a/wowup-electron/src/app/get-addons/get-addons.component.ts +++ b/wowup-electron/src/app/get-addons/get-addons.component.ts @@ -1,4 +1,6 @@ import { Component, OnInit } from '@angular/core'; +import { WowClientType } from '../models/warcraft/wow-client-type'; +import { AddonService } from '../core/services/addons/addon.service'; @Component({ selector: 'app-get-addons', @@ -22,12 +24,21 @@ export class GetAddonsComponent implements OnInit { { position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' }, ]; - public selectedClient = 'retail'; public query = ''; + public selectedClient = WowClientType.Classic; - constructor() { } + constructor( + private _addonService: AddonService + ) { } ngOnInit(): void { } + private loadPopularAddons(){ + if(this.selectedClient === WowClientType.None){ + return; + } + + + } } diff --git a/wowup-electron/src/app/models/curse/curse-get-featured-response.ts b/wowup-electron/src/app/models/curse/curse-get-featured-response.ts new file mode 100644 index 00000000..0f6735c9 --- /dev/null +++ b/wowup-electron/src/app/models/curse/curse-get-featured-response.ts @@ -0,0 +1,7 @@ +import { CurseSearchResult } from './curse-search-result'; + +export interface CurseGetFeaturedResponse { + featured: CurseSearchResult[]; + popular: CurseSearchResult[]; + recentlyUpdated: CurseSearchResult[]; +} \ No newline at end of file diff --git a/wowup-electron/src/app/models/warcraft/wow-client-type.ts b/wowup-electron/src/app/models/warcraft/wow-client-type.ts index c5ba86f0..c4da53ca 100644 --- a/wowup-electron/src/app/models/warcraft/wow-client-type.ts +++ b/wowup-electron/src/app/models/warcraft/wow-client-type.ts @@ -3,5 +3,6 @@ export enum WowClientType { Classic, RetailPtr, ClassicPtr, - Beta + Beta, + None } \ No newline at end of file diff --git a/wowup-electron/src/app/my-addons/my-addons.component.ts b/wowup-electron/src/app/my-addons/my-addons.component.ts index 1a1d50c0..a3ed1e2f 100644 --- a/wowup-electron/src/app/my-addons/my-addons.component.ts +++ b/wowup-electron/src/app/my-addons/my-addons.component.ts @@ -1,12 +1,12 @@ import { Component, OnInit } from '@angular/core'; -import { WarcraftService } from 'app/core/services/warcraft/warcraft.service'; -import { WowClientType } from 'app/models/warcraft/wow-client-type'; -import { AddonService } from 'app/core/services/addons/addon.service'; +import { WarcraftService } from '../core/services/warcraft/warcraft.service'; +import { WowClientType } from '../models/warcraft/wow-client-type'; +import { AddonService } from '../core/services/addons/addon.service'; import { first, tap } from 'rxjs/operators'; import { from, BehaviorSubject } from 'rxjs'; -import { Addon } from 'app/core/entities/addon'; -import { AddonTableColumnComponent } from 'app/components/addon-table-column/addon-table-column.component'; -import { AddonStatusColumnComponent } from 'app/components/addon-status-column/addon-status-column.component'; +import { Addon } from '../core/entities/addon'; +import { AddonTableColumnComponent } from '../components/addon-table-column/addon-table-column.component'; +import { AddonStatusColumnComponent } from '../components/addon-status-column/addon-status-column.component'; @Component({ selector: 'app-my-addons', @@ -77,7 +77,7 @@ export class MyAddonsComponent implements OnInit { this.warcraftService.clientTypes$ .pipe( first(types => Array.isArray(types) && types.length > 0), - tap(() => this.loadAddons()) + tap(() => this.loadAddons(this.selectedClient)) ) .subscribe(types => this.selectedClient = types[0]); @@ -87,27 +87,24 @@ export class MyAddonsComponent implements OnInit { } onReScan() { - this.loadAddons(true) + this.loadAddons(this.selectedClient, true) } onClientChange() { - this.busy = true; - console.log(this.selectedClient); - this.busy = false; + this.loadAddons(this.selectedClient, false); } onGridReady(params) { this.gridApi = params.api; this.gridApi.sizeColumnsToFit(); - } - private loadAddons(rescan: boolean = false) { + private loadAddons(clientType: WowClientType, rescan: boolean = false) { this.busy = true; - console.log('Load-addons') + console.log('Load-addons', clientType); - from(this.addonService.getAddons(this.selectedClient, rescan)) + from(this.addonService.getAddons(clientType, rescan)) .subscribe((addons) => { this.busy = false; this.formatAddons(addons);