Skip to content

Commit

Permalink
Highlights comments. FreeTubeApp#783
Browse files Browse the repository at this point in the history
  • Loading branch information
ab-shrek committed Oct 28, 2023
1 parent 8e960fa commit 619c659
Show file tree
Hide file tree
Showing 13 changed files with 228 additions and 12 deletions.
5 changes: 5 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const IpcChannels = {
DB_HISTORY: 'db-history',
DB_PROFILES: 'db-profiles',
DB_PLAYLISTS: 'db-playlists',
DB_HIGHLIGHTED_COMMENTS: 'db-highlighted-comments',

SYNC_SETTINGS: 'sync-settings',
SYNC_HISTORY: 'sync-history',
Expand Down Expand Up @@ -48,6 +49,10 @@ const DBActions = {
DELETE_VIDEO_ID: 'db-action-playlists-delete-video-by-playlist-name',
DELETE_VIDEO_IDS: 'db-action-playlists-delete-video-ids',
DELETE_ALL_VIDEOS: 'db-action-playlists-delete-all-videos'
},

HIGHLIGHTED_COMMENTS: {
UPSERT_COMMENT: 'db-action-highlighted-comments-upsert-highlighted-comment-by-video-id'
}
}

Expand Down
26 changes: 25 additions & 1 deletion src/datastores/handlers/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,35 @@ class Playlists {
}
}

class HighlightedComments {
static create(videoId) {
return db.highlightedComments.insertAsync(videoId)
}

static find() {
return db.highlightedComments.findAsync({})
}

static upsertHighlightedCommentByVideoId(comment, videoId) {
return db.highlightedComments.updateAsync(
{ _id: videoId },
{ $push: { comments: comment } },
{ upsert: true }
)
}

static persist() {
return db.highlightedComments.compactDatafileAsync()
}
}

function compactAllDatastores() {
return Promise.allSettled([
Settings.persist(),
History.persist(),
Profiles.persist(),
Playlists.persist()
Playlists.persist(),
HighlightedComments.persist()
])
}

Expand All @@ -183,6 +206,7 @@ const baseHandlers = {
history: History,
profiles: Profiles,
playlists: Playlists,
highlightedComments: HighlightedComments,

compactAllDatastores
}
Expand Down
36 changes: 35 additions & 1 deletion src/datastores/handlers/electron.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,45 @@ class Playlists {
}
}

class HighlightedComments {
static create(videoId) {
return ipcRenderer.invoke(
IpcChannels.DB_HIGHLIGHTED_COMMENTS,
{ action: DBActions.GENERAL.CREATE, data: videoId }
)
}

static find() {
return ipcRenderer.invoke(
IpcChannels.DB_HIGHLIGHTED_COMMENTS,
{ action: DBActions.GENERAL.FIND }
)
}

static upsertHighlightedCommentByVideoId(comment, videoId) {
return ipcRenderer.invoke(
IpcChannels.DB_HIGHLIGHTED_COMMENTS,
{
action: DBActions.HIGHLIGHTED_COMMENTS.UPSERT_COMMENT,
data: { videoId: videoId, comment: JSON.stringify(comment) }
}
)
}

static persist() {
return ipcRenderer.invoke(
IpcChannels.DB_HIGHLIGHTED_COMMENTS,
{ action: DBActions.GENERAL.PERSIST }
)
}
}

const handlers = {
settings: Settings,
history: History,
profiles: Profiles,
playlists: Playlists
playlists: Playlists,
highlightedComments: HighlightedComments
}

export default handlers
4 changes: 3 additions & 1 deletion src/datastores/handlers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ const DBSettingHandlers = handlers.settings
const DBHistoryHandlers = handlers.history
const DBProfileHandlers = handlers.profiles
const DBPlaylistHandlers = handlers.playlists
const DBHighlightedCommentHandlers = handlers.highlightedComments

export {
DBSettingHandlers,
DBHistoryHandlers,
DBProfileHandlers,
DBPlaylistHandlers
DBPlaylistHandlers,
DBHighlightedCommentHandlers
}
4 changes: 4 additions & 0 deletions src/datastores/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,9 @@ db.settings = new Datastore({ filename: dbPath('settings'), autoload: true })
db.profiles = new Datastore({ filename: dbPath('profiles'), autoload: true })
db.playlists = new Datastore({ filename: dbPath('playlists'), autoload: true })
db.history = new Datastore({ filename: dbPath('history'), autoload: true })
db.highlightedComments = new Datastore({
filename: dbPath('highlightedComments'),
autoload: true
})

export default db
26 changes: 26 additions & 0 deletions src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,32 @@ function runApp() {
}
})

// *********** //
// Highlighted Comments
ipcMain.handle(IpcChannels.DB_HIGHLIGHTED_COMMENTS, async (event, { action, data }) => {
try {
switch (action) {
case DBActions.GENERAL.CREATE:
await baseHandlers.highlightedComments.create(data)
return null

case DBActions.GENERAL.FIND:
return await baseHandlers.highlightedComments.find()

case DBActions.HIGHLIGHTED_COMMENTS.UPSERT_COMMENT:
await baseHandlers.highlightedComments.upsertHighlightedCommentByVideoId(data.comment, data.videoId)
return null

default:
// eslint-disable-next-line no-throw-literal
throw 'invalid highlighted comments db action'
}
} catch (err) {
if (typeof err === 'string') throw err
else throw err.toString()
}
})

// *********** //

function syncOtherWindows(channel, event, payload) {
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ export default defineComponent({
this.grabAllProfiles(this.$t('Profile.All Channels')).then(async () => {
this.grabHistory()
this.grabAllPlaylists()
this.grabAllHighlightedComments()

if (process.env.IS_ELECTRON) {
ipcRenderer = require('electron').ipcRenderer
Expand Down Expand Up @@ -532,6 +533,7 @@ export default defineComponent({

...mapActions([
'grabUserSettings',
'grabAllHighlightedComments',
'grabAllProfiles',
'grabHistory',
'grabAllPlaylists',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,19 @@
margin-block-end: 5px;
}

.commentHighlighted {
font-weight: normal;
font-size: 12px;
margin-block-start: 0;
margin-inline-start: 68px;
margin-block-end: 5px;
}

.commentDate {
font-weight: normal;
margin-inline-start: 5px;
font-size: 12px;
cursor: pointer;
}

.commentMemberIcon {
Expand Down Expand Up @@ -190,4 +199,4 @@
text-decoration: underline;
cursor: pointer;
color: var(--title-color);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import FtTimestampCatcher from '../../components/ft-timestamp-catcher/ft-timesta
import { copyToClipboard, showToast } from '../../helpers/utils'
import { invidiousGetCommentReplies, invidiousGetComments } from '../../helpers/api/invidious'
import { getLocalComments, parseLocalComment } from '../../helpers/api/local'
import { mapActions } from 'vuex'

export default defineComponent({
name: 'WatchVideoComments',
Expand Down Expand Up @@ -120,6 +121,10 @@ export default defineComponent({

subscriptions: function() {
return this.$store.getters.getActiveProfile.subscriptions
},

highlightedComments: function () {
return this.$store.getters.getHighlightedComments(this.id)
}
},
mounted: function () {
Expand Down Expand Up @@ -151,6 +156,7 @@ export default defineComponent({

getCommentData: function () {
this.isLoading = true
this.commentData = this.commentData.concat(this.highlightedComments)
if (!process.env.IS_ELECTRON || this.backendPreference === 'invidious') {
this.getCommentDataInvidious()
} else {
Expand Down Expand Up @@ -206,11 +212,10 @@ export default defineComponent({
const parsedComments = comments.contents
.map(commentThread => parseLocalComment(commentThread.comment, commentThread))

if (more) {
this.commentData = this.commentData.concat(parsedComments)
} else {
this.commentData = parsedComments
}
// Append and remove duplicate comments based on commentId.
this.commentData = Array.from([...this.commentData, ...parsedComments]
.reduce((m, o) => m.set(o.commentId, o), new Map())
.values())

this.nextPageToken = comments.has_continuation ? comments : null
this.isLoading = false
Expand Down Expand Up @@ -269,7 +274,9 @@ export default defineComponent({
nextPageToken: this.nextPageToken,
sortNewest: this.sortNewest
}).then(({ response, commentData }) => {
this.commentData = this.commentData.concat(commentData)
this.commentData = Array.from([...this.commentData, ...commentData]
.reduce((m, o) => m.set(o.commentId, o), new Map())
.values())
this.nextPageToken = response.continuation
this.isLoading = false
this.showComments = true
Expand Down Expand Up @@ -319,5 +326,15 @@ export default defineComponent({
this.isLoading = false
})
},

addHighlightedCommentAndReloadPage: function (comment) {
showToast(this.$t('Highlighting comment'))
this.$store.dispatch('addHighlightedComment', { videoId: this.id, comment: comment })
window.location.reload()
},

...mapActions([
'addHighlightedComment'
])
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@
>
</template>
</router-link>
<p
v-if="highlightedComments.find((highlightedComment) => highlightedComment.commentId === comment.commentId)"
class="commentHighlighted"
>
{{ $t("Highlighted comment") }}
</p>
<p
v-if="comment.isPinned"
class="commentPinned"
Expand Down Expand Up @@ -114,7 +120,12 @@
class="commentSubscribedIcon"
alt=""
>
<span class="commentDate">
<span
class="commentDate"
@click="addHighlightedCommentAndReloadPage(comment)"
@keydown.space.prevent="addHighlightedCommentAndReloadPage(comment)"
@keydown.enter.prevent="addHighlightedCommentAndReloadPage(comment)"
>
{{ comment.time }}
</span>
</p>
Expand Down
3 changes: 2 additions & 1 deletion src/renderer/helpers/api/local.js
Original file line number Diff line number Diff line change
Expand Up @@ -885,7 +885,8 @@ export function parseLocalComment(comment, commentThread = undefined) {
hasOwnerReplied,
replyToken,
showReplies: false,
replies: []
replies: [],
commentId: comment.comment_id
}
}

Expand Down
79 changes: 79 additions & 0 deletions src/renderer/store/modules/highlighted-comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { DBHighlightedCommentHandlers } from '../../../datastores/handlers/index'

const state = {
videoHighlightedComments: {}
}

const getters = {
getHighlightedComments: (state) => (videoId) => (
videoId in state.videoHighlightedComments
? state.videoHighlightedComments[videoId]
: [])
}

const actions = {
async addVideoId({ commit }, payload) {
try {
await DBHighlightedCommentHandlers.create(payload)
commit('addVideoId', payload)
} catch (errMessage) {
console.error(errMessage)
}
},
async addHighlightedComment({ commit }, payload) {
try {
await DBHighlightedCommentHandlers.upsertHighlightedCommentByVideoId(payload.comment, payload.videoId)
commit('upsertHighlightedCommentToVideo', payload.comment, payload.videoId)
} catch (errMessage) {
console.error(errMessage)
}
},

async grabAllHighlightedComments({ commit, dispatch, state }) {
try {
const payload = await DBHighlightedCommentHandlers.find()
commit('setAllHighlightedComments', payload)
} catch (errMessage) {
console.error(errMessage)
}
}
}

const mutations = {
addVideoId(state, videoId) {
if (!(videoId in state.videoHighlightedComments)) {
state.videoHighlightedComments[videoId] = []
}
},
upsertHighlightedCommentToVideo(state, comment, videoId) {
if (videoId in state.videoHighlightedComments) {
const comments = state.videoHighlightedComments[videoId]
const existingCommentIndex = comments.findIndex(c => c.text === comment.text)
if (existingCommentIndex === -1) {
state.videoHighlightedComments[videoId].push(comment)
}
} else {
state.videoHighlightedComments[videoId] = [comment]
}
},

setAllHighlightedComments(state, payload) {
if (Array.isArray(payload) && payload.length > 0) {
payload.forEach(entry => {
if (!(entry._id in state.videoHighlightedComments)) {
state.videoHighlightedComments[entry._id] = []
}
state.videoHighlightedComments[entry._id] = (
state.videoHighlightedComments[entry._id].concat(
entry.comments.map(x => JSON.parse(x))))
})
}
}
}

export default {
state,
getters,
actions,
mutations
}
Loading

0 comments on commit 619c659

Please sign in to comment.