Multicolumn Bluesky client powered by Angular

feat: open author-view when clicking names/avatars

kbenlloch b0fb5cb9 94db0a96

+4 -2
src/app/components/aux-panes/author-view/author-view.component.html
··· 11 11 > 12 12 <avatar 13 13 [src]="author().banner" 14 - class="w-full aspect-[3_/_1]" 14 + (click)="dialogService.openImage([{fullsize: author().banner, thumb: undefined, alt: undefined}], 0)" 15 + class="w-full aspect-[3_/_1] cursor-pointer" 15 16 /> 16 17 17 18 <div ··· 19 20 > 20 21 <avatar 21 22 [src]="author().avatar" 22 - class="h-18 w-18 absolute -top-9 left-2 border-[0.25rem] border-bg !box-content" 23 + (click)="dialogService.openImage([{fullsize: author().avatar, thumb: undefined, alt: undefined}], 0)" 24 + class="h-18 w-18 absolute -top-9 left-2 border-[0.25rem] border-bg !box-content cursor-pointer" 23 25 /> 24 26 </div> 25 27
+2
src/app/components/aux-panes/author-view/author-view.component.ts
··· 20 20 import {AuthorFeedComponent} from '@components/feeds/author-feed/author-feed.component'; 21 21 import {ScrollDirective} from '@shared/directives/scroll.directive'; 22 22 import {IsLoggedUserPipe} from '@shared/pipes/is-logged-user.pipe'; 23 + import {DialogService} from '@services/dialog.service'; 23 24 24 25 @Component({ 25 26 selector: 'author-view', ··· 56 57 57 58 constructor( 58 59 private messageService: MessageService, 60 + protected dialogService: DialogService, 59 61 private cdRef: ChangeDetectorRef 60 62 ) {} 61 63
+5 -3
src/app/components/cards/post-card-detail/post-card-detail.component.html
··· 38 38 39 39 <avatar 40 40 [src]="author.avatar" 41 - (click)="$event.stopPropagation()" 41 + (click)="$event.stopPropagation(); dialogService.openAuthor(author)" 42 42 class="h-12 w-12 shrink-0 cursor-pointer" 43 43 /> 44 44 ··· 46 46 class="flex flex-col flex-1 min-w-0 justify-center" 47 47 > 48 48 <span 49 - class="text-lg font-bold [text-box:trim-both_cap_alphabetic] w-fit min-w-0 overflow-y-visible overflow-x-clip overflow-ellipsis whitespace-nowrap cursor-pointer" 49 + (click)="$event.stopPropagation(); dialogService.openAuthor(author)" 50 + class="text-lg font-bold [text-box:trim-both_cap_alphabetic] w-fit min-w-0 overflow-y-visible overflow-x-clip overflow-ellipsis whitespace-nowrap cursor-pointer hover:underline" 50 51 >{{author | displayName}}</span> 51 52 52 53 @if (author.displayName?.trim().length) { 53 54 <span 54 - class="text-sm text-primary/50 [text-box:trim-both_cap_alphabetic] mt-3 w-fit min-w-0 overflow-y-visible overflow-x-clip whitespace-nowrap text-ellipsis cursor-pointer" 55 + (click)="$event.stopPropagation(); dialogService.openAuthor(author)" 56 + class="text-sm text-primary/50 [text-box:trim-both_cap_alphabetic] mt-3 w-fit min-w-0 overflow-y-visible overflow-x-clip whitespace-nowrap text-ellipsis cursor-pointer hover:underline" 55 57 >{{'@' + author.handle}}</span> 56 58 } 57 59 </div>
+1 -1
src/app/components/cards/post-card-detail/post-card-detail.component.ts
··· 74 74 constructor( 75 75 private postService: PostService, 76 76 private messageService: MessageService, 77 - private dialogService: DialogService, 77 + protected dialogService: DialogService, 78 78 private cdRef: ChangeDetectorRef 79 79 ) { 80 80 effect(() => {
+10 -7
src/app/components/cards/post-card/post-card.component.html
··· 6 6 > 7 7 <avatar 8 8 [src]="post().author.avatar" 9 - (click)="$event.stopPropagation()" 9 + (click)="$event.stopPropagation(); dialogService.openAuthor(post().author)" 10 10 class="h-12 w-12" 11 11 /> 12 12 ··· 65 65 <div 66 66 class="flex mt-[0.15rem] w-full min-w-0" 67 67 > 68 - <span 69 - class="font-bold [text-box:trim-both_cap_alphabetic] mr-1 grow-0 shrink-1 min-w-0 overflow-y-visible overflow-x-clip overflow-ellipsis whitespace-nowrap" 70 - >{{author | displayName}}</span> 68 + <a 69 + (click)="$event.stopPropagation(); dialogService.openAuthor(author)" 70 + class="font-bold [text-box:trim-both_cap_alphabetic] mr-1 grow-0 shrink-1 min-w-0 overflow-y-visible overflow-x-clip overflow-ellipsis whitespace-nowrap hover:underline" 71 + >{{author | displayName}}</a> 71 72 72 73 @if (reason | isFeedDefsReasonRepost) { 73 74 <div ··· 78 79 >repeat</span> 79 80 </div> 80 81 81 - <span 82 - class="font-bold text-primary/50 [text-box:trim-both_cap_alphabetic] grow-1 shrink-0 max-w-1/2 min-w-0 overflow-y-visible overflow-x-clip overflow-ellipsis whitespace-nowrap" 83 - >{{reason.by | displayName}}</span> 82 + <a 83 + (click)="$event.stopPropagation(); dialogService.openAuthor(reason.by)" 84 + class="font-bold text-primary/50 [text-box:trim-both_cap_alphabetic] grow-1 shrink-0 max-w-1/2 min-w-0 overflow-y-visible overflow-x-clip overflow-ellipsis whitespace-nowrap hover:underline" 85 + >{{reason.by | displayName}}</a> 84 86 } 85 87 86 88 <!-- @if (author.displayName?.length) {--> ··· 93 95 <a 94 96 (click)="$event.stopPropagation()" 95 97 [href]="post().uri | linkExtractor: author.handle" 98 + [title]="record.createdAt | date: 'medium'" 96 99 target="_blank" 97 100 class="text-sm text-primary/50 hover:underline [text-box:trim-both_cap_alphabetic] shrink-0 ml-auto pl-3" 98 101 >{{record.createdAt | dateFormatter}}</a>
+8 -4
src/app/components/cards/post-card/post-card.component.ts
··· 15 15 import {DisplayNamePipe} from '@shared/pipes/display-name.pipe'; 16 16 import {IsFeedPostRecordPipe} from '@shared/pipes/type-guards/is-feed-post-record'; 17 17 import {RichTextComponent} from '@components/shared/rich-text/rich-text.component'; 18 - import {NgClass, NgTemplateOutlet} from '@angular/common'; 18 + import {DatePipe, NgClass, NgTemplateOutlet} from '@angular/common'; 19 19 import {IsFeedDefsPostViewPipe} from '@shared/pipes/type-guards/is-feed-defs-postview'; 20 20 import {DateFormatterPipe} from '@shared/pipes/date-formatter.pipe'; 21 21 import {IsEmbedRecordViewPipe} from '@shared/pipes/type-guards/is-embed-record-view.pipe'; ··· 58 58 OverlayModule, 59 59 NgClass, 60 60 ExternalEmbedComponent, 61 - IsEmbedExternalViewPipe 61 + IsEmbedExternalViewPipe, 62 + DatePipe 62 63 ], 63 64 templateUrl: './post-card.component.html', 64 65 styles: ` ··· 75 76 background-size: 1px 100%; 76 77 } 77 78 `, 78 - changeDetection: ChangeDetectionStrategy.OnPush 79 + changeDetection: ChangeDetectionStrategy.OnPush, 80 + providers: [ 81 + DatePipe 82 + ] 79 83 }) 80 84 export class PostCardComponent implements OnInit, OnDestroy { 81 85 post = model<AppBskyFeedDefs.PostView>(); ··· 94 98 constructor( 95 99 private postService: PostService, 96 100 private messageService: MessageService, 97 - private dialogService: DialogService, 101 + protected dialogService: DialogService, 98 102 private cdRef: ChangeDetectorRef 99 103 ) { 100 104 effect(() => {
+1 -1
src/app/components/shared/rich-text/rich-text.component.html
··· 15 15 <a 16 16 href="https://bsky.app/profile/{{segment.mention?.did}}" 17 17 class="hover:underline text-blue-500" 18 - (click)="openAuthor($event, segment.mention?.did)" 18 + (click)="openAuthor($event, segment)" 19 19 >{{segment.text}}</a> 20 20 } @else if (segment.isTag()) { 21 21 <a
+4 -4
src/app/components/shared/rich-text/rich-text.component.ts
··· 8 8 Output, 9 9 } from '@angular/core'; 10 10 import {Facet, RichText, RichTextSegment} from "@atproto/api"; 11 - // import {MskyDialogService} from '@services/msky-dialog.service'; 12 11 import {agent} from '@core/bsky.api'; 12 + import {DialogService} from '@services/dialog.service'; 13 13 14 14 @Component({ 15 15 selector: 'rich-text', ··· 25 25 26 26 constructor( 27 27 private cdRef: ChangeDetectorRef, 28 - // private dialogService: MskyDialogService 28 + private dialogService: DialogService 29 29 ) {} 30 30 31 31 ngOnInit() { ··· 46 46 } 47 47 } 48 48 49 - openAuthor(event: MouseEvent, did: string) { 49 + openAuthor(event: MouseEvent, segment: RichTextSegment) { 50 50 event.preventDefault(); 51 51 event.stopPropagation(); 52 52 53 - //TODO: OpenAuthor 53 + this.dialogService.openAuthor({did: segment.mention?.did, handle: segment.text.replace("@", "")}); 54 54 } 55 55 }