This commit is contained in:
Benedek László 2024-05-09 23:02:55 +02:00
parent 8693c06757
commit ca2a763636
9 changed files with 133 additions and 41 deletions

View File

@ -4,39 +4,49 @@ import { AuthService } from '../auth/auth.service';
import { AngularFirestore, Reference } from '@angular/fire/compat/firestore'; import { AngularFirestore, Reference } from '@angular/fire/compat/firestore';
import { User } from '../../../model/User'; import { User } from '../../../model/User';
import { UserService } from './user.service'; import { UserService } from './user.service';
import { user } from '@angular/fire/auth'; import { DocumentReference } from '@angular/fire/firestore';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class PostService { export class PostService {
constructor(private auth: AuthService, private afs: AngularFirestore) { } constructor(private auth: AuthService, private afs: AngularFirestore, private usersvc: UserService) { }
getFeed(length: Number, start: Number): Promise<Array<Post>> { getFeed(length: Number, start: Number): Promise<Array<Post>> {
return new Promise<Array<Post>>((resolve, reject) => { return new Promise<Array<Post>>((resolve, reject) => {
let posts = Array<Post>(); let result = Array<Post>();
if (this.auth.checkAllowed()) { if (this.auth.checkAllowed()) {
this.afs.collection<Post>('post').valueChanges({idField: 'id'}).subscribe(data => { this.usersvc.getCurrentUser()
data.forEach(i => { .then(currentUser => {
this.afs.doc((i as any).user).valueChanges().subscribe(user => { // get posts
posts.push({ this.afs.collection<Post>('post').valueChanges({ idField: 'id' }).subscribe(posts => {
user: { posts.forEach(post => {
username: (user as User).username, // get the user who made this post
email: (user as User).email, this.afs.doc((post as any).user).valueChanges().subscribe(user => {
picture: (user as User).picture, // get how many likes it has
followed: (user as User).followed this.afs.collection('like', ref => ref.where('post', '==', this.afs.doc('/post/' + post.id).ref)).valueChanges().subscribe(likes => {
}, // check if we liked this post
content: i.content, let liked: boolean = likes.filter(like => (like as any).user.id == currentUser.username).length != 0;
image: i.image, result.push({
likes: i.likes, user: {
liked: i.liked, username: (user as User).username,
id: i.id email: (user as User).email,
}) picture: (user as User).picture,
followed: (user as User).followed
},
content: post.content,
image: post.image,
likes: likes.length,
liked: liked,
id: post.id
})
})
});
});
resolve(result);
}); });
}); })
resolve(posts);
});
} else { } else {
reject() reject()
} }
@ -48,24 +58,42 @@ export class PostService {
if (this.auth.checkAllowed()) { if (this.auth.checkAllowed()) {
if (username == undefined) { if (username == undefined) {
this.auth.getUser().subscribe(cred => { this.auth.getUser().subscribe(cred => {
// get the user by id
this.afs.collection<User>('user', ref => ref.where('id', '==', cred?.uid)).valueChanges().subscribe(user => { this.afs.collection<User>('user', ref => ref.where('id', '==', cred?.uid)).valueChanges().subscribe(user => {
this.afs.collection<Post>('post', ref => ref.where('user', '==', this.afs.doc('/user/' + user[0].username).ref)).valueChanges({idField:'id'}).subscribe(data => { // get their posts
data.forEach(i => { this.afs.collection<Post>('post', ref => ref.where('user', '==', this.afs.doc('/user/' + user[0].username).ref)).valueChanges({ idField: 'id' }).subscribe(posts => {
i.user = user[0] as User; posts.forEach(post => {
// get how many likes it has
this.afs.collection('like', ref => ref.where('post', '==', this.afs.doc('/post/' + post.id).ref)).valueChanges().subscribe(likes => {
// check if we liked this post
post.liked = likes.filter(like => (like as any).user.id == user[0].username).length != 0;
post.user = user[0] as User;
post.likes = likes.length;
})
resolve(posts)
}) })
resolve(data)
}); });
}) })
}); });
} else { } else {
this.afs.collection<User>('user').doc(username as string).valueChanges().subscribe(user => { this.usersvc.getCurrentUser()
this.afs.collection<Post>('post', ref => ref.where('user', '==', this.afs.doc('/user/' + username).ref)).valueChanges({idField:'id'}).subscribe(data => { .then(currentUser => {
data.forEach(i => { // get the user by username
i.user = user as User; this.afs.collection<User>('user').doc(username as string).valueChanges().subscribe(user => {
}) // get their posts
resolve(data) this.afs.collection<Post>('post', ref => ref.where('user', '==', this.afs.doc('/user/' + username).ref)).valueChanges({ idField: 'id' }).subscribe(posts => {
}); posts.forEach(post => {
}); // get how many likes it has
this.afs.collection('like', ref => ref.where('post', '==', this.afs.doc('/post/' + post.id).ref)).valueChanges().subscribe(likes => {
post.liked = likes.filter(like => (like as any).user.id == currentUser.username).length != 0;
post.user = user as User;
post.likes = likes.length;
})
resolve(posts)
})
});
});
})
} }
} else { } else {
reject() reject()
@ -96,6 +124,37 @@ export class PostService {
} }
removePost(id: String) { removePost(id: String) {
return this.afs.doc('/post/'+id).delete(); return this.afs.doc('/post/' + id).delete();
}
toggleLike(postId: String): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
if (this.auth.checkAllowed()) {
this.usersvc.getCurrentUser()
.then(user => {
let userRef = this.afs.doc('/user/' + user.username).ref;
let postRef = this.afs.doc('/post/' + postId).ref;
this.afs.collection('like', ref => ref.where('user', '==', userRef).where('post', '==', postRef)).get().subscribe(likes => {
if (likes.docs.length == 0) {
// like
this.afs.collection('like').add({
user: userRef,
post: postRef
})
resolve(true);
} else {
// dislike
likes.docs.forEach(likes => {
likes.ref.delete()
})
resolve(false);
}
})
})
.catch(() => reject())
} else {
reject();
}
});
} }
} }

View File

@ -2,7 +2,6 @@ import { Injectable } from '@angular/core';
import { User } from '../../../model/User'; import { User } from '../../../model/User';
import { AuthService } from '../auth/auth.service'; import { AuthService } from '../auth/auth.service';
import { AngularFirestore } from '@angular/fire/compat/firestore'; import { AngularFirestore } from '@angular/fire/compat/firestore';
import { user } from '@angular/fire/auth';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -26,6 +25,19 @@ export class UserService {
}); });
} }
getCurrentUser(): Promise<User> {
return new Promise<User>((resolve,reject)=>{
this.auth.getUser().subscribe(user => {
this.afs.collection<User>('user', ref => ref.where('id', '==', user?.uid)).valueChanges().subscribe(users=>{
if (users.length != 0)
resolve(users[0]);
else
reject();
})
});
});
}
createUser(username: String, email: String, id: String) { createUser(username: String, email: String, id: String) {
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
this.afs.collection('user').doc(username as string).set({ this.afs.collection('user').doc(username as string).set({

View File

@ -5,4 +5,13 @@ mat-sidenav {
button { button {
display: block; display: block;
margin: 10px auto; margin: 10px auto;
}
app-side-menu {
height: 100%;
display: block;
}
mat-sidenav-container {
height: 100%;
} }

View File

@ -1,6 +1,7 @@
<div class="user-container outline"> <div class="user-container outline">
<div [routerLink]="'/user/'+user?.username"> <div [routerLink]="'/user/'+user?.username">
<img [src]="user?.picture" class="outline"> <span>{{user?.username}}</span> <!-- <img [src]="user?.picture" class="outline"> -->
<span>{{user?.username}}</span>
</div> </div>
<span [classList]="user?.followed ? 'follow followed' : 'follow'"></span> <!-- <span [classList]="user?.followed ? 'follow followed' : 'follow'"></span> -->
</div> </div>

View File

@ -16,6 +16,7 @@
} }
span { span {
margin: 20px auto;
display: block; display: block;
width: 100%; width: 100%;
text-align: center; text-align: center;

View File

@ -3,7 +3,7 @@
<div>{{post?.content}}</div> <div>{{post?.content}}</div>
<img *ngIf="post?.image" [src]="post?.image" alt=""> <img *ngIf="post?.image" [src]="post?.image" alt="">
<div class="icons"> <div class="icons">
<span [classList]="post?.liked ? 'likes liked' : 'likes'">{{post?.likes}}</span> <span (click)="like()" [classList]="post?.liked ? 'likes liked' : 'likes'">{{post?.likes}}</span>
<span (click)="remove()" [classList]="isOwned ? 'owned' : ''"></span> <span (click)="remove()" [classList]="isOwned ? 'owned' : ''"></span>
</div> </div>
</div> </div>

View File

@ -14,7 +14,6 @@ import { PostService } from '../../../services/data/post.service';
styleUrl: './post.component.scss' styleUrl: './post.component.scss'
}) })
export class PostComponent implements OnInit { export class PostComponent implements OnInit {
@Input() post: Post | undefined; @Input() post: Post | undefined;
isOwned: boolean = false; isOwned: boolean = false;
@ -38,4 +37,13 @@ export class PostComponent implements OnInit {
alert("failed to delete post"); alert("failed to delete post");
}) })
} }
like() {
this.postSv.toggleLike(this.post?.id as String)
.then((result)=>{
((this.post as Post).likes as number) += result ? 1 : -1;
(this.post as Post).liked = result;
})
.catch(()=>{alert('failed to toggle like on post')})
}
} }

View File

@ -1,3 +1,4 @@
<div [routerLink]="'/user/'+user?.username"> <div [routerLink]="'/user/'+user?.username">
<img [src]="user?.picture" class="outline"> <span>{{user?.username}}</span> <!-- <img [src]="user?.picture" class="outline"> -->
<span>{{user?.username}}</span>
</div> </div>

View File

@ -12,6 +12,7 @@ img {
span { span {
display: inline-block; display: inline-block;
margin: 20px auto;
padding-left: 10px; padding-left: 10px;
transform: translateY(-60%); transform: translateY(-60%);
} }