Skip to content

Commit

Permalink
Add ratings system predicates
Browse files Browse the repository at this point in the history
  • Loading branch information
floogulinc committed Aug 18, 2023
1 parent ad50674 commit c238ee6
Show file tree
Hide file tree
Showing 33 changed files with 705 additions and 121 deletions.
12 changes: 11 additions & 1 deletion src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ import { ApiSettingsComponent } from './api-settings/api-settings.component';
import { AppSettingsComponent } from './app-settings/app-settings.component';
import { JsonViewDialogComponent } from './json-view-dialog/json-view-dialog.component';
import { FileMetadataDialogComponent } from './file-metadata-dialog/file-metadata-dialog.component';
import { SystemPredicateRatingsDialogComponent } from './system-predicate-ratings-dialog/system-predicate-ratings-dialog.component';
import { ServiceSelectDialogComponent } from './service-select-dialog/service-select-dialog.component';
import { RatingNumericalComponent } from './rating-numerical/rating-numerical.component';
import { RatingLikeComponent } from './rating-like/rating-like.component';
import { RatingIncDecComponent } from './rating-inc-dec/rating-inc-dec.component';


const MAT_MODULES = [
Expand Down Expand Up @@ -153,7 +158,12 @@ const MAT_MODULES = [
ApiSettingsComponent,
AppSettingsComponent,
JsonViewDialogComponent,
FileMetadataDialogComponent
FileMetadataDialogComponent,
SystemPredicateRatingsDialogComponent,
ServiceSelectDialogComponent,
RatingNumericalComponent,
RatingLikeComponent,
RatingIncDecComponent
],
imports: [
BrowserModule,
Expand Down
24 changes: 3 additions & 21 deletions src/app/file-info-sheet/file-info-sheet.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,7 @@ <h2 mat-dialog-title class="sheet-title">File Info</h2>
<mat-list-item *ngIf="isNumericalRatingService(rating)">
<p matLine>{{rating.name}} ({{rating.value ?? 'not set'}})</p>
<p matLine class="numerical-rating-line">
<bar-rating [rate]="rating.value" [max]="rating.max_stars" (rateChange)="setRating(rating, $event)">
<ng-template ratingActive>
<mat-icon [svgIcon]="ratingIcons[rating.star_shape]"></mat-icon>
</ng-template>
<ng-template ratingInactive>
<mat-icon [svgIcon]="ratingIconsOutline[rating.star_shape]"></mat-icon>
</ng-template>
</bar-rating>
<app-rating-numerical [rating]="rating" (ratingSet)="setRating(rating, $event)"></app-rating-numerical>
</p>
<button mat-icon-button [matMenuTriggerFor]="ratingMenu" [matMenuTriggerData]="{rating}">
<mat-icon>more_vert</mat-icon>
Expand All @@ -123,11 +116,7 @@ <h2 mat-dialog-title class="sheet-title">File Info</h2>
<mat-list-item *ngIf="isLikeRatingService(rating)">
<p matLine>{{rating.name}} ({{rating.value === null ? 'not set' : rating.value ? 'liked' : 'dislike'}})</p>
<p matLine>
<button mat-icon-button [color]="rating.value === false ? 'warn' : ''" (click)="this.setRating(rating, !rating.value)">
<mat-icon *ngIf="rating.value === null" [svgIcon]="ratingIconsOutline[rating.star_shape]"></mat-icon>
<mat-icon *ngIf="rating.value === true" [svgIcon]="ratingIcons[rating.star_shape]"></mat-icon>
<mat-icon *ngIf="rating.value === false" [svgIcon]="ratingIcons[rating.star_shape]"></mat-icon>
</button>
<app-rating-like [rating]="rating" (ratingSet)="setRating(rating, $event)"></app-rating-like>
</p>
<button mat-icon-button [matMenuTriggerFor]="ratingMenu" [matMenuTriggerData]="{rating}">
<mat-icon>more_vert</mat-icon>
Expand All @@ -136,21 +125,14 @@ <h2 mat-dialog-title class="sheet-title">File Info</h2>
<mat-list-item *ngIf="isIncDecRatingService(rating)">
<p matLine>{{rating.name}}</p>
<p matLine class="inc-rating-line">
<button mat-icon-button (click)="setRating(rating, rating.value - 1)" [disabled]="rating.value === 0"><mat-icon>remove</mat-icon></button>
<span>{{rating.value}}</span>
<button mat-icon-button (click)="setRating(rating, rating.value + 1)"><mat-icon>add</mat-icon></button>
<app-rating-inc-dec [rating]="rating" (ratingSet)="setRating(rating, $event)"></app-rating-inc-dec>
</p>
<button mat-icon-button [matMenuTriggerFor]="ratingMenu" [matMenuTriggerData]="{rating}">
<mat-icon>more_vert</mat-icon>
</button>
</mat-list-item>
</ng-template>
</mat-list>
<!-- <div *ngFor="let rating of file.ratings_array">
<ng-template [ngIf]="isNumericalRatingService(rating)">
<div>{{rating.name}}<bar-rating [(rate)]="rating.value" [max]="rating.max_stars" [theme]="'stars'"></bar-rating></div>
</ng-template>
</div> -->
</mat-expansion-panel>
</mat-accordion>

Expand Down
28 changes: 7 additions & 21 deletions src/app/file-info-sheet/file-info-sheet.component.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import { Component, Inject, ChangeDetectionStrategy, Injectable } from '@angular/core';
import { HydrusBasicFile, HydrusFile, FileCategory, HydrusTagService, HydrusTagServiceType, Rating } from '../hydrus-file';
import { HydrusBasicFile, HydrusFile, FileCategory, HydrusTagServiceType } from '../hydrus-file';
import {MatBottomSheetRef, MAT_BOTTOM_SHEET_DATA} from '@angular/material/bottom-sheet';
import { HydrusFilesService } from '../hydrus-files.service';
import { saveAs } from 'file-saver';
import { MatSnackBar } from '@angular/material/snack-bar';
import { tagsObjectFromFile } from '../utils/tag-utils';
import { SettingsService } from '../settings.service';
import { BehaviorSubject, distinctUntilChanged, filter, firstValueFrom, map, shareReplay, switchMap } from 'rxjs';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import { BehaviorSubject, filter, firstValueFrom, map, shareReplay, switchMap } from 'rxjs';
import { MatDialog } from '@angular/material/dialog';
import { SaucenaoDialogComponent } from '../saucenao-dialog/saucenao-dialog.component';
import { SaucenaoService } from '../saucenao.service';
import { HydrusFileDownloadService } from '../hydrus-file-download.service';
import { ActivatedRoute, Router } from '@angular/router';
import { Router } from '@angular/router';
import { HydrusSearchTags } from '../hydrus-tags';
import { HydrusTagsService } from '../hydrus-tags.service';
import { TagInputDialogComponent } from '../tag-input-dialog/tag-input-dialog.component';
import { HydrusRatingStarType, HydrusServiceType, isIncDecRatingService, isLikeRatingService, isNumericalRatingService } from '../hydrus-services';
import { NoteEditDialogComponent } from '../note-edit-dialog/note-edit-dialog.component';
import { HydrusNotesService } from '../hydrus-notes.service';
import { AddUrlOptions, HydrusUrlService } from '../hydrus-url.service';
Expand All @@ -24,6 +22,8 @@ import { HydrusRatingsService } from '../hydrus-ratings.service';
import { JsonViewDialogComponent } from '../json-view-dialog/json-view-dialog.component';
import { ExifReaderService } from '../exif-reader.service';
import { FileMetadataDialogComponent } from '../file-metadata-dialog/file-metadata-dialog.component';
import { isNumericalRatingService, isLikeRatingService, isIncDecRatingService, HydrusRating } from '../hydrus-rating';
import { HydrusServiceType } from '../hydrus-services';

function getFileIcon(fileType: FileCategory) {
switch (fileType) {
Expand Down Expand Up @@ -143,20 +143,6 @@ export class FileInfoSheetComponent {
shareReplay(1),
)

ratingIcons: Record<HydrusRatingStarType, string> = {
'fat star': 'rating:star',
'pentagram star': 'rating:star',
'circle': 'rating:circle',
'square': 'rating:square'
}

ratingIconsOutline: Record<HydrusRatingStarType, string> = {
'fat star': 'rating:star_outline',
'pentagram star': 'rating:star_outline',
'circle': 'rating:circle_outline',
'square': 'rating:square_outline'
}

ipfsUrl$ = this.file$.pipe(
filter(file => file.ipfs_multihashes && Object.values(file.ipfs_multihashes).length > 0),
map(file => `${this.settings.appSettings.ipfsMultihashUrlPrefix}${Object.values(file.ipfs_multihashes)[0]}`)
Expand All @@ -175,7 +161,7 @@ export class FileInfoSheetComponent {
return item.name;
}

trackByRating(index: number, rating: Rating) {
trackByRating(index: number, rating: HydrusRating) {
return rating.service_key;
}

Expand Down
30 changes: 14 additions & 16 deletions src/app/hydrus-file.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { HydrusNotes } from './hydrus-notes';
import { HydrusIncDecRatingService, HydrusLikeRatingService, HydrusNumericalRatingService, HydrusServiceSimple, HydrusServiceType, HydrusServices, isIncDecRatingService, isLikeRatingService, isNumericalRatingService, service_string_lookup } from './hydrus-services';
import { HydrusURLInfo } from './hydrus-url';
import { HydrusFiletype } from './hydrus-file-mimes'
import { HydrusIncDecRatingValue, HydrusLikeRatingValue, HydrusNumericalRatingValue, HydrusRating, isIncDecRatingService, isLikeRatingService, isNumericalRatingService } from './hydrus-rating';
import { HydrusServiceType, HydrusServices } from './hydrus-services';

export interface ServiceNamesToStatusesToTags {
[service: string]: StatusesToTags;
Expand Down Expand Up @@ -50,10 +51,6 @@ export interface HydrusBasicFileFromAPI {
num_words?: number;
}

interface RatingsFromAPI {
[service_key: string]: boolean | number | null;
}

export interface HydrusFileFromAPI extends HydrusBasicFileFromAPI {
known_urls: string[];
file_services: {
Expand Down Expand Up @@ -95,15 +92,9 @@ export interface HydrusFileFromAPI extends HydrusBasicFileFromAPI {
is_deleted?: boolean; // added in v506
}

export type Rating =
{service_key: string} &
((HydrusNumericalRatingService & {value: number | null}) |
(HydrusLikeRatingService & {value: boolean | null}) |
(HydrusIncDecRatingService & {value: number}))

export interface HydrusFile extends HydrusFileFromAPI, HydrusBasicFile {
time_imported?: Date;
ratings_array?: Rating[]
interface RatingsFromAPI {
[service_key: string]: boolean | number | null;
}

export function generateRatingsArray(ratings: RatingsFromAPI, services: HydrusServices) {
Expand All @@ -112,24 +103,31 @@ export function generateRatingsArray(ratings: RatingsFromAPI, services: HydrusSe
if (isNumericalRatingService(service)) {
return {
...service,
value: value as number | null
value: value as HydrusNumericalRatingValue
}
} else if (isLikeRatingService(service)) {
return {
...service,
value: value as boolean | null
value: value as HydrusLikeRatingValue
}
} else if (isIncDecRatingService(service)) {
return {
...service,
value: value as number
value: value as HydrusIncDecRatingValue
}
} else {
return null;
}
})
}


export interface HydrusFile extends HydrusFileFromAPI, HydrusBasicFile {
time_imported?: Date;
ratings_array?: HydrusRating[]
}


export interface HydrusBasicFile extends HydrusBasicFileFromAPI {
file_url: string;
thumbnail_url: string;
Expand Down
71 changes: 71 additions & 0 deletions src/app/hydrus-rating.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { HydrusServiceSimple, HydrusServiceType, HydrusServices } from "./hydrus-services";
import { SystemPredicate } from "./hydrus-system-predicates";

export type HydrusRatingStarType = 'circle' | 'square' | 'fat star' | 'pentagram star';

export const ratingIcons: Record<HydrusRatingStarType, string> = {
'fat star': 'rating:star',
'pentagram star': 'rating:star',
'circle': 'rating:circle',
'square': 'rating:square'
}

export const ratingIconsOutline: Record<HydrusRatingStarType, string> = {
'fat star': 'rating:star_outline',
'pentagram star': 'rating:star_outline',
'circle': 'rating:circle_outline',
'square': 'rating:square_outline'
}

export interface HydrusNumericalRatingService extends HydrusServiceSimple {
min_stars: number;
max_stars: number;
star_shape: HydrusRatingStarType;
type: HydrusServiceType.LOCAL_RATING_NUMERICAL | HydrusServiceType.RATING_NUMERICAL_REPOSITORY;
}

export interface HydrusIncDecRatingService extends HydrusServiceSimple {
type: HydrusServiceType.LOCAL_RATING_INCDEC
}

export function isNumericalRatingService(service: HydrusServiceSimple | HydrusNumericalRatingService): service is HydrusNumericalRatingService {
return service.type === HydrusServiceType.LOCAL_RATING_NUMERICAL || service.type === HydrusServiceType.RATING_NUMERICAL_REPOSITORY;
}

export interface HydrusLikeRatingService extends HydrusServiceSimple {
star_shape: HydrusRatingStarType;
type: HydrusServiceType.LOCAL_RATING_LIKE | HydrusServiceType.RATING_LIKE_REPOSITORY;
}

export function isLikeRatingService(service: HydrusServiceSimple | HydrusLikeRatingService): service is HydrusLikeRatingService {
return service.type === HydrusServiceType.LOCAL_RATING_LIKE || service.type === HydrusServiceType.RATING_LIKE_REPOSITORY;
}

export function isIncDecRatingService(service: HydrusServiceSimple): service is HydrusIncDecRatingService {
return service.type === HydrusServiceType.LOCAL_RATING_INCDEC
}

export type HydrusNumericalRatingValue = number | null;
export type HydrusLikeRatingValue = boolean | null;
export type HydrusIncDecRatingValue = number;
export type HydrusRatingValue = HydrusNumericalRatingValue | HydrusLikeRatingValue | HydrusIncDecRatingValue;

export type HydrusNumericalRating = HydrusNumericalRatingService & {value: HydrusNumericalRatingValue};
export type HydrusLikeRating = HydrusLikeRatingService & {value: HydrusLikeRatingValue};
export type HydrusIncDecRating = HydrusIncDecRatingService & {value: HydrusIncDecRatingValue};

export type HydrusRating = {service_key: string} & (HydrusNumericalRating | HydrusLikeRating | HydrusIncDecRating)

export function ratingsServiceToRatingPredicate(service: HydrusServiceSimple) {
if(isNumericalRatingService(service)) {
return SystemPredicate.RATING_SPECIFIC_NUMERICAL
} else if(isLikeRatingService(service)) {
return SystemPredicate.RATING_SPECIFIC_LIKE_DISLIKE
}else if(isIncDecRatingService(service)) {
return SystemPredicate.RATING_SPECIFIC_INCDEC
}
}

export function isRatingService(service: HydrusServiceSimple) {
return isIncDecRatingService(service) || isLikeRatingService(service) || isNumericalRatingService(service);
}
45 changes: 14 additions & 31 deletions src/app/hydrus-services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,37 +62,6 @@ export interface HydrusService extends HydrusServiceSimple {
service_key: string,
}

export type HydrusRatingStarType = 'circle' | 'square' | 'fat star' | 'pentagram star';

export interface HydrusNumericalRatingService extends HydrusServiceSimple {
min_stars: number;
max_stars: number;
star_shape: HydrusRatingStarType;
type: HydrusServiceType.LOCAL_RATING_NUMERICAL | HydrusServiceType.RATING_NUMERICAL_REPOSITORY;
}

export interface HydrusIncDecRatingService extends HydrusServiceSimple {
type: HydrusServiceType.LOCAL_RATING_INCDEC
}

export function isNumericalRatingService(service: HydrusServiceSimple | HydrusNumericalRatingService): service is HydrusNumericalRatingService {
return service.type === HydrusServiceType.LOCAL_RATING_NUMERICAL || service.type === HydrusServiceType.RATING_NUMERICAL_REPOSITORY;
}

export interface HydrusLikeRatingService extends HydrusServiceSimple {
star_shape: HydrusRatingStarType;
type: HydrusServiceType.LOCAL_RATING_LIKE | HydrusServiceType.RATING_LIKE_REPOSITORY;
}

export function isLikeRatingService(service: HydrusServiceSimple | HydrusLikeRatingService): service is HydrusLikeRatingService {
return service.type === HydrusServiceType.LOCAL_RATING_LIKE || service.type === HydrusServiceType.RATING_LIKE_REPOSITORY;
}

export function isIncDecRatingService(service: HydrusServiceSimple): service is HydrusIncDecRatingService {
return service.type === HydrusServiceType.LOCAL_RATING_INCDEC
}


export interface HydrusServiceInfo {
local_tags: HydrusService[]; // deprecated in v531
tag_repositories: HydrusService[]; // deprecated in v531
Expand Down Expand Up @@ -147,3 +116,17 @@ export function getLocalTagServices(serviceArray: HydrusService[]) {
export function getAllKnownTagsService(services: HydrusServices) {
return services['616c6c206b6e6f776e2074616773'];
}

export function isFileService(service: HydrusServiceSimple) {
return [
HydrusServiceType.FILE_REPOSITORY,
HydrusServiceType.LOCAL_FILE_DOMAIN,
HydrusServiceType.LOCAL_FILE_TRASH_DOMAIN,
HydrusServiceType.LOCAL_FILE_UPDATE_DOMAIN,
HydrusServiceType.COMBINED_LOCAL_FILE,
HydrusServiceType.COMBINED_LOCAL_MEDIA,
HydrusServiceType.COMBINED_FILE,
HydrusServiceType.IPFS,
HydrusServiceType.COMBINED_DELETED_FILE
].includes(service.type);
}
Loading

0 comments on commit c238ee6

Please sign in to comment.