Skip to content
This repository has been archived by the owner on Jan 31, 2024. It is now read-only.

Commit

Permalink
merge: add like button #32
Browse files Browse the repository at this point in the history
Add Like Button
  • Loading branch information
Marie authored Sep 30, 2023
2 parents b64f963 + 9fd66f9 commit e5d9eb3
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 9 deletions.
7 changes: 3 additions & 4 deletions packages/backend/src/core/entities/NoteEntityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,9 @@ export class NoteEntityService implements OnModuleInit {
uri: note.uri ?? undefined,
url: note.url ?? undefined,
updatedAt: note.updatedAt != null ? note.updatedAt.toISOString() : undefined,
...(meId ? {
myReaction: this.populateMyReaction(note, meId, options?._hint_),
} : {}),

...(opts.detail ? {
clippedCount: note.clippedCount,
Expand All @@ -358,10 +361,6 @@ export class NoteEntityService implements OnModuleInit {
}) : undefined,

poll: note.hasPoll ? this.populatePoll(note, meId) : undefined,

...(meId ? {
myReaction: this.populateMyReaction(note, meId, options?._hint_),
} : {}),
} : {}),
});

Expand Down
20 changes: 20 additions & 0 deletions packages/frontend/src/components/MkNoteDetailed.vue
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-else class="_button" :class="$style.noteFooterButton" disabled>
<i class="ph-prohibit ph-bold ph-lg"></i>
</button>
<button v-if="appearNote.myReaction == null && appearNote.reactionAcceptance !== 'likeOnly'" ref="likeButton" :class="$style.noteFooterButton" class="_button" @mousedown="like()">
<i class="ph-heart ph-bold ph-lg"></i>
</button>
<button v-if="appearNote.myReaction == null" ref="reactButton" :class="$style.noteFooterButton" class="_button" @mousedown="react()">
<i v-if="appearNote.reactionAcceptance === 'likeOnly'" class="ph-heart ph-bold ph-lg"></i>
<i v-else class="ph-smiley ph-bold ph-lg"></i>
Expand Down Expand Up @@ -252,6 +255,7 @@ const renoteButton = shallowRef<HTMLElement>();
const renoteTime = shallowRef<HTMLElement>();
const reactButton = shallowRef<HTMLElement>();
const clipButton = shallowRef<HTMLElement>();
const likeButton = shallowRef<HTMLElement>();
let appearNote = $computed(() => isRenote ? note.renote as Misskey.entities.Note : note);
const isMyRenote = $i && ($i.id === note.userId);
const showContent = ref(false);
Expand Down Expand Up @@ -432,6 +436,22 @@ function react(viaKeyboard = false): void {
}
}

function like(): void {
pleaseLogin();
showMovedDialog();
os.api('notes/reactions/create', {
noteId: props.note.id,
reaction: '❤️',
});
const el = likeButton.value as HTMLElement | null | undefined;
if (el) {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
const y = rect.top + (el.offsetHeight / 2);
os.popup(MkRippleEffect, { x, y }, {}, 'end');
}
}

function undoReact(note): void {
const oldReaction = note.myReaction;
if (!oldReaction) return;
Expand Down
48 changes: 43 additions & 5 deletions packages/frontend/src/components/MkNoteSub.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-->

<template>
<div v-if="!muted" :class="[$style.root, { [$style.children]: depth > 1 }]">
<div ref="el" v-if="!muted" :class="[$style.root, { [$style.children]: depth > 1 }]">
<div :class="$style.main">
<div v-if="note.channel" :class="$style.colorBar" :style="{ background: note.channel.color }"></div>
<MkAvatar :class="$style.avatar" :user="note.user" link preview/>
Expand Down Expand Up @@ -38,6 +38,9 @@ SPDX-License-Identifier: AGPL-3.0-only
<button v-else class="_button" :class="$style.noteFooterButton" disabled>
<i class="ph-prohibit ph-bold ph-lg"></i>
</button>
<button v-if="note.myReaction == null && note.reactionAcceptance !== 'likeOnly'" ref="likeButton" :class="$style.noteFooterButton" class="_button" @mousedown="like()">
<i class="ph-heart ph-bold ph-lg"></i>
</button>
<button v-if="note.myReaction == null" ref="reactButton" :class="$style.noteFooterButton" class="_button" @mousedown="react()">
<i v-if="note.reactionAcceptance === 'likeOnly'" class="ph-heart ph-bold ph-lg"></i>
<i v-else class="ph-smiley ph-bold ph-lg"></i>
Expand Down Expand Up @@ -90,6 +93,8 @@ import { reactionPicker } from '@/scripts/reaction-picker.js';
import { claimAchievement } from '@/scripts/achievements.js';
import type { MenuItem } from '@/types/menu.js';
import { getNoteMenu } from '@/scripts/get-note-menu.js';
import { useNoteCapture } from '@/scripts/use-note-capture.js';

const canRenote = computed(() => ['public', 'home'].includes(props.note.visibility) || props.note.userId === $i.id);

const props = withDefaults(defineProps<{
Expand All @@ -102,17 +107,34 @@ const props = withDefaults(defineProps<{
depth: 1,
});

function focus() {
el.value.focus();
}

const el = shallowRef<HTMLElement>();
const muted = ref(checkWordMute(props.note, $i, defaultStore.state.mutedWords));
const translation = ref(null);
const translating = ref(false);
const isDeleted = ref(false);
const reactButton = shallowRef<HTMLElement>();
const renoteButton = shallowRef<HTMLElement>();
const menuButton = shallowRef<HTMLElement>();
const likeButton = shallowRef<HTMLElement>();

let appearNote = $computed(() => isRenote ? props.note.renote as Misskey.entities.Note : props.note);

const isRenote = (
props.note.renote != null &&
props.note.text == null &&
props.note.fileIds.length === 0 &&
props.note.poll == null
);

useNoteCapture({
rootEl: el,
note: $$(appearNote),
isDeletedRef: isDeleted,
});

function focus() {
el.value.focus();
}

function reply(viaKeyboard = false): void {
pleaseLogin();
Expand Down Expand Up @@ -157,6 +179,22 @@ function react(viaKeyboard = false): void {
}
}

function like(): void {
pleaseLogin();
showMovedDialog();
os.api('notes/reactions/create', {
noteId: props.note.id,
reaction: '❤️',
});
const el = reactButton.value as HTMLElement | null | undefined;
if (el) {
const rect = el.getBoundingClientRect();
const x = rect.left + (el.offsetWidth / 2);
const y = rect.top + (el.offsetHeight / 2);
os.popup(MkRippleEffect, { x, y }, {}, 'end');
}
}

function undoReact(note): void {
const oldReaction = note.myReaction;
if (!oldReaction) return;
Expand Down

0 comments on commit e5d9eb3

Please sign in to comment.