From aa1e51347743513361200ece5b0f225caa348c0c Mon Sep 17 00:00:00 2001 From: liyunze <50455574+liyunze-coding@users.noreply.github.com> Date: Wed, 22 Nov 2023 21:18:44 +0800 Subject: [PATCH] New features - !count - !points - !boardcount - !focus - automaticDoneIndex --- configs.js | 190 ++++++++++-- scripts/index.js | 415 +++++++++++++++++--------- scripts/taskList.js | 710 +++++++++++++++++++++++++++++++++++++++----- styles/taskList.css | 10 + 4 files changed, 1089 insertions(+), 236 deletions(-) diff --git a/configs.js b/configs.js index eb28947..b133e31 100644 --- a/configs.js +++ b/configs.js @@ -2,8 +2,11 @@ const configs = (function () { "use strict"; // settings - const enableLimit = true; // true or false - const limit = 5; // integer + const enableLimit = false; // true or false + const limit = 10; // integer + const automaticDoneIndex = true; // true or false - Automatically assume first unfinished task is complete + const pointsName = "points"; // string + const pointsPerTask = 10; // integer // animation const scrollSpeed = 40; // milliseconds @@ -16,7 +19,7 @@ const configs = (function () { const taskListBorderWidth = "0px"; // px const taskListBorderColor = "#ffffff"; // hex or name - const taskListBorderRadius = "5px"; // px + const taskListBorderRadius = "0px"; // px const taskListHorizontalPadding = "0px"; // px const taskListVerticalPadding = "0px"; // px @@ -25,12 +28,12 @@ const configs = (function () { const headerHorizontalPadding = "10px"; // px const headerVerticalPadding = "10px"; // px - const headerBackgroundColor = "#000000"; // hex only - const headerBackgroundOpacity = 0.8; // 0.0 - 1.0 + const headerBackgroundColor = "#fff"; // hex only + const headerBackgroundOpacity = 1; // 0.0 - 1.0 - const headerBorderWidth = "2px"; // px + const headerBorderWidth = "0px"; // px const headerBorderColor = "#ffffff"; // hex or name - const headerBorderRadius = "5px"; // px + const headerBorderRadius = "3px"; // px const headerFontFamily = "Fredoka"; // font name const headerGoogleFont = true; // true: use google font, false: use system font @@ -38,10 +41,10 @@ const configs = (function () { const headerFontSize = "25px"; // px const headerFontWeight = "bold"; // normal or bold or number - const headerFontColor = "#ffffff"; // hex or name + const headerFontColor = "#000"; // hex or name // body - const bodyBackgroundColor = "#000000"; // hex only + const bodyBackgroundColor = "#fff"; // hex only const bodyBackgroundOpacity = 0; // 0.0 - 1.0 const bodyBorderWidth = "0px"; // px @@ -51,27 +54,37 @@ const configs = (function () { // task const lineHeight = 1.5; // number const usernameFontWeight = "bold"; // normal or bold or number - const usernameColor = "#ffc0cb"; // hex or name or "" for twitch user color + const usernameColor = "pink"; // hex or name or "" for twitch user color const taskWidth = "100%"; - const taskBackgroundColor = "#000000"; // hex only - const taskBackgroundOpacity = 0.7; // 0.0 - 1.0 + const taskBackgroundColor = "#fff"; // hex only + const taskBackgroundOpacity = 0; // 0.0 - 1.0 const taskFontFamily = "Poppins"; // font name const taskGoogleFont = true; // true: use google font, false: use system font const taskFontSize = "20px"; // px - const taskFontColor = "#ffffff"; // hex or name + const taskFontColor = "#fff"; // hex or name - const taskBorderColor = "#000000"; // hex or name + const taskBorderColor = "#fff"; // hex or name const taskBorderWidth = "0px"; // px - const taskBorderRadius = "5px"; // px + const taskBorderRadius = "10px"; // px - const taskMarginBottom = "5px"; // px + const taskMarginBottom = "10px"; // px const taskHorizontalPadding = "20px"; // px const taskVerticalPadding = "10px"; // px + // focus task + const focusTaskBackgroundColor = "#fff"; // hex only + const focusTaskBackgroundOpacity = 1; // 0.0 - 1.0 + const focusTaskBorderRadius = "5px"; // px + + const focusTaskFontColor = "#000"; // hex or name + + const focusTaskHorizontalPadding = "7px"; // px + const focusTaskVerticalPadding = "0px"; // px + // Add task commands - please add commands in the exact format const addTaskCommands = [ "!taska", @@ -81,6 +94,7 @@ const configs = (function () { "!task", "!add", "!todo", + "!a", ]; // Edit task commands - please add commands in the exact format @@ -90,11 +104,11 @@ const configs = (function () { "!etask", "!edittask", "!edit", + "!e", ]; // Delete task commands - please add commands in the exact format const deleteTaskCommands = [ - "!taskd", "!taskdel", "!taskdelete", "!deltask", @@ -105,6 +119,7 @@ const configs = (function () { "!removetask", "!remove", "!delete", + "!r", ]; // Finish task commands - please add commands in the exact format @@ -120,6 +135,7 @@ const configs = (function () { "!finish", "!done", "!finished", + "!f", ]; // Unfinish task commands - please add commands in the exact format @@ -134,8 +150,14 @@ const configs = (function () { "!undone", "!unfinish", "!unfinished", + "!u", ]; + // focus task commands - please add commands in the exact format + const focusTaskCommands = ["!focus", "!taskfocus", "!focustask"]; + + const unfocusTaskCommands = ["!unfocus", "!taskunfocus", "!unfocustask"]; + // Check task commands - please add commands in the exact format const checkCommands = [ "!taskc", @@ -153,6 +175,30 @@ const configs = (function () { // Clear my done commands - please add commands in the exact format const clearMyDoneCommands = ["!clearmydone"]; + // check count commands - please add commands in the exact format + const checkCountCommands = [ + "!taskcount", + "!count", + "!checkcount", + "!mycount", + ]; + + const checkAllCountCommands = [ + "!taskallcount", + "!allcount", + "!checkallcount", + "!boardcount", + "!checkboardcount", + "!taskboardcount", + ]; + + const checkMyPointsCommands = [ + "!taskpoints", + "!points", + "!mypoints", + "!checkpoints", + ]; + // Help commands - please add commands in the exact format const helpCommands = [ "!taskh", @@ -186,6 +232,12 @@ const configs = (function () { "!cleardone", ]; + const adminClearTasksCommands = ["!cleartasks"]; + + const adminResetBoardCount = ["!resetboardcount", "!resetallcount"]; + + const adminResetUsersCount = ["!resetuserscount"]; + const adminClearAllCommands = [ "!clearall", "!allclear", @@ -195,37 +247,82 @@ const configs = (function () { "!aclear", ]; - // Responses + const adminSetBoardCount = ["!setboardcount", "!setallcount"]; + + // Responses related to task addition const taskAdded = 'The task(s) "{task}" has been added, {user}!'; const noTaskAdded = "Looks like you already hit the limit of incomplete tasks, {user}"; const noTaskContent = "Try using !task the-task-you-are-working-on {user}"; - const taskDeleted = - 'Task(s) "{task}" has been deleted successfully, {user}'; - const specifyTaskIndex = "Try specifying the index of the task {user}"; - const duplicateTask = "Looks like you already have the task '{message}' up there {user}!"; + // Responses related to task deletion + const taskDeleted = + 'Task(s) "{task}" has been deleted successfully, {user}'; + const specifyTaskIndex = + "Try specifying the index of the incomplete task(s) {user}"; const clearTasksExceptBroadcaster = "All tasks have been cleared except for the streamer's, {user}!"; - const adminDeleteTasks = "All of {mentioned}'s tasks have been deleted"; - const taskFinished = 'Good job on finishing the task "{task}", {user}!'; - const allTasksFinished = "Good job on finishing all your tasks, {user}!"; + + // Responses related to task completion + const taskFinished = + 'Good job on finishing the task(s) "{task}", {user}! You have earned {pointCount} {pointName} and completed {doneCount} task(s) so far!'; + const allTasksFinished = + "Good job on finishing all your tasks, {user}! You have completed {doneCount} task(s) so far!"; const taskUnfinished = 'Task(s) "{task}" has been unmarked as done, {user}!'; + const taskAlreadyFinished = + "Looks like you already finished that task {user}"; + + // Responses related to task editing const taskEdited = "Task '{originalTask}' has been edited to '{task}' successfully, {user}"; const noTaskEdit = "Try doing !edit [index] [new task] {user}"; + // Responses related to task focus + const taskFocused = "Task(s) {task} has been focused, {user}!"; + const clearFocused = "Task(s) has been unfocused, {user}!"; + const noFocusedTask = "Looks like you don't have a focused task {user}!"; + const alreadyFocusedTask = + "Looks like you already have that task set to focus {user}!"; + const onlyOneFocus = "You can only focus one task at a time {user}!"; + const specifyFocusTask = + "Try specifying an incomplete task to focus {user}!"; + + // Responses related to task existence const noTask = "Looks like you don't have a task up there {user}"; const noTaskA = "Looks like there is no task from that user there {user}"; + + // Responses related to viewing counts + const checkMyPoints = "You have {pointCount} {pointName}, {user}!"; + const checkUserPoints = + "{mentioned} has {pointCount} {pointName}, {user}!"; + const checkYourCount = + "You have completed {doneCount} task(s) so far, {user}!"; + const checkUserCount = + "{mentioned} has completed {doneCount} task(s) so far, {user}!"; + const checkAllCount = + "Everyone has completed {doneCount} task(s) so far, {user}!"; + const noCountAll = "Looks like no one has completed a task yet {user}"; + + // Responses related to permissions const notMod = "Permission denied, {user}; Mods only"; - const clearedAll = "All tasks have been cleared!"; + const notStreamer = "Permission denied, {user}; Streamer only"; + + // Responses related to clearing tasks / counts + const clearedAll = "All tasks and counts have been cleared!"; + const clearedTasks = "All tasks have been cleared!"; const clearedDone = "All completed tasks have been cleared!"; const clearedMyDone = "All your completed tasks have been cleared!"; + const clearedBoardCount = "The board count has been reset!"; + const clearedUsersCount = "The users count has been reset!"; + const setBoardCount = "The board count has been set to {count}!"; const specifyUser = "Try specifying a user to delete their tasks {user}"; + const invalidNumber = "Try specifying a valid number {user}"; + + // Help response const help = `{user} Use the following commands to help you out - !task !edit !remove !done. For mods, you can do !adel @user. More commmands here: https://github.com/liyunze-coding/Chat-Task-Tic-Overlay/blob/main/MultiTask.md/`; // to edit check task command, go to // scripts/taskList.js @@ -242,12 +339,19 @@ const configs = (function () { "!edit", "!remove", "!done", + "!undone", "!botcred", + "!count", + "!points", + "!boardcount", ]; const settings = { enableLimit, limit, + automaticDoneIndex, + pointsName, + pointsPerTask, headerGoogleFont, taskGoogleFont, }; @@ -291,6 +395,12 @@ const configs = (function () { taskMarginBottom, taskHorizontalPadding, taskVerticalPadding, + focusTaskBackgroundColor, + focusTaskBackgroundOpacity, + focusTaskFontColor, + focusTaskHorizontalPadding, + focusTaskVerticalPadding, + focusTaskBorderRadius, }; const animation = { @@ -305,14 +415,23 @@ const configs = (function () { deleteTaskCommands, finishTaskCommands, unfinishTaskCommands, + focusTaskCommands, + unfocusTaskCommands, helpCommands, checkCommands, listCommands, clearMyDoneCommands, + checkCountCommands, + checkAllCountCommands, + checkMyPointsCommands, adminDeleteCommands, adminClearNotStreamerCommands, adminClearDoneCommands, adminClearAllCommands, + adminClearTasksCommands, + adminSetBoardCount, + adminResetBoardCount, + adminResetUsersCount, additionalCommands, }; @@ -326,18 +445,37 @@ const configs = (function () { taskFinished, allTasksFinished, taskUnfinished, + taskAlreadyFinished, taskEdited, noTaskEdit, + clearFocused, + noFocusedTask, + alreadyFocusedTask, + onlyOneFocus, + specifyFocusTask, + taskFocused, noTask, noTaskA, + checkMyPoints, + checkUserPoints, + checkYourCount, + checkUserCount, + checkAllCount, + noCountAll, notMod, + notStreamer, help, clearTasksExceptBroadcaster, adminDeleteTasks, clearedMyDone, + clearedBoardCount, + clearedUsersCount, clearedAll, + clearedTasks, clearedDone, + setBoardCount, specifyUser, + invalidNumber, }; return { diff --git a/scripts/index.js b/scripts/index.js index 3f2a5f4..ca7c4c6 100644 --- a/scripts/index.js +++ b/scripts/index.js @@ -1,5 +1,4 @@ const commands = configs.commands; -const responses = configs.responses; let params = {}; @@ -11,6 +10,10 @@ function respond(template, params) { .replace("{mentioned}", `@${params.mentioned}`) .replace("{task}", params.task) .replace("{originalTask}", params.originalTask) + .replace("{doneCount}", params.doneCount) + .replace("{count}", params.count) + .replace("{pointName}", params.pointName) + .replace("{pointCount}", params.pointCount) ); } @@ -18,6 +21,10 @@ function isMod(flags) { return flags.broadcaster || flags.mod; } +function isStreamer(flags) { + return flags.broadcaster; +} + ComfyJS.onCommand = (user, command, message, flags, extra) => { command = `!${command.toLowerCase()}`; @@ -27,138 +34,163 @@ ComfyJS.onCommand = (user, command, message, flags, extra) => { mentioned: "", task: "", originalTask: "", + doneCount: "", + count: "", + pointName: configs.settings.pointsName, + pointCount: "", }; if (commands.addTaskCommands.includes(command)) { - let addStatus = addTask(user, extra.userColor, message); - - if (addStatus === 0) { - // limit has reached - respond(responses.noTaskAdded, params); - } else if (addStatus === 1) { - // duplicate task - respond(responses.duplicateTask, params); - } else if (addStatus === 2) { - // task has no content - respond(responses.noTaskContent, params); - } else { - let addResponse = responses.taskAdded; - params.task = addStatus.task; - - if (addStatus.tasksFailedToAdd !== "") { - addResponse += ` | Failed to add task(s): "${addStatus.tasksFailedToAdd}"`; - } - - // task added - respond(addResponse, params); - } - } else if (commands.editTaskCommands.includes(command)) { - let editStatus = editTask(user, message); - - if (editStatus === 0) { - // no task - respond(responses.noTask, params); - } else if (editStatus === 1) { - // invalid input - respond(responses.noTaskEdit, params); - } else { - // task edited - params.task = editStatus[1]; - params.originalTask = editStatus[0]; - respond(responses.taskEdited, params); - } - } else if (commands.deleteTaskCommands.includes(command)) { - let removeStatus = removeTask(user, message); - if (removeStatus === 0) { - // no task - respond(responses.noTask, params); - } else if (removeStatus === 1) { - // invalid input - respond(responses.specifyTaskIndex, params); - } else { - // task deleted - let deletedResponse = responses.taskDeleted; - params.task = removeStatus.removedTasks; - - if (removeStatus.failedTasks !== "") { - deletedResponse += ` | Failed to delete task(s): "${removeStatus.failedTasks}"`; - } - - respond(deletedResponse, params); - } - } else if (commands.finishTaskCommands.includes(command)) { - if (message === "all") { - let finishAllStatus = markAllTasksAsDone(user); - - if (finishAllStatus === 0) { - // user has no tasks - respond(responses.noTask, params); - } else { - // all tasks finished - let finishedResponse = responses.allTasksFinished; - - respond(finishedResponse, params); - } + let addRequest = addTask(user, extra.userColor, message); + if (addRequest.status !== 200) { + respond(addRequest.body.error, params); return; } - let finishStatus = markTaskDone(user, message); + let addedResponse = responses.taskAdded; + params.task = addRequest.body.task; - if (finishStatus === 0) { - // user has no tasks - respond(responses.noTask, params); - } else if (finishStatus === 1) { - // invalid input - respond(responses.specifyTaskIndex, params); - } else { - // task finished - let finishedResponse = responses.taskFinished; + if (addRequest.body.tasksFailedToAdd !== "") { + addedResponse += ` | Failed to add task(s): "${addRequest.body.tasksFailedToAdd}"`; + } - params.task = finishStatus.markedTasks; + respond(addedResponse, params); + } else if (commands.editTaskCommands.includes(command)) { + let editRequest = editTask(user, message); - if (finishStatus.failedTasks !== "") { - finishedResponse += ` | Failed to finish task(s): "${finishStatus.failedTasks}"`; + if (editRequest.status !== 200) { + respond(editRequest.body.error, params); + return; + } + + let originalTask = editRequest.body.originalTask; + let newTask = editRequest.body.newTask; + + params.task = newTask; + params.originalTask = originalTask; + + respond(responses.taskEdited, params); + } else if (commands.deleteTaskCommands.includes(command)) { + let removeRequest = removeTask(user, message); + + if (removeRequest.status !== 200) { + respond(removeRequest.body.error, params); + return; + } + let deletedResponse = responses.taskDeleted; + + let removedTasks = removeRequest.body.removedTasks; + let failedTasks = removeRequest.body.failedTasks; + + params.task = removedTasks; + + if (failedTasks !== "") { + deletedResponse += ` | Failed to delete task(s): "${failedTasks}"`; + } + + respond(deletedResponse, params); + } else if (commands.finishTaskCommands.includes(command)) { + if (message === "all") { + let finishAllRequest = markAllTasksAsDone(user); + + if (finishAllRequest.status !== 200) { + respond(finishAllRequest.body.error, params); + return; } - respond(finishedResponse, params); + let finishedAllResponse = responses.allTasksFinished; + params.doneCount = completedTasksCount(user); + + respond(finishedAllResponse, params); + return; } + + let finishRequest = markTaskDone(user, message); + + if (finishRequest.status !== 200) { + respond(finishRequest.body.error, params); + return; + } + + let finishedResponse = responses.taskFinished; + + params.task = finishRequest.body.markedTasks; + params.doneCount = completedTasksCount(user); + params.pointCount = + finishRequest.body.markedTasksCount * + configs.settings.pointsPerTask; + + if (finishRequest.body.failedTasks !== "") { + finishedResponse += ` | Failed to finish task(s): "${finishRequest.body.failedTasks}"`; + } + + respond(finishedResponse, params); } else if (commands.unfinishTaskCommands.includes(command)) { - let unfinishStatus = markTaskUndone(user, message); + let unfinishRequest = markTaskUndone(user, message); - if (unfinishStatus === 0) { - // user has no tasks - respond(responses.noTask, params); - } else if (unfinishStatus === 1) { - // invalid input - respond(responses.specifyTaskIndex, params); - } else { - // task unfinished - let unfinishedResponse = responses.taskUnfinished; - - params.task = unfinishStatus.markedTasks; - - if (unfinishStatus.failedTasks !== "") { - unfinishedResponse += ` | Failed to unfinish task(s): "${unfinishStatus.failedTasks}"`; - } - - respond(unfinishedResponse, params); + if (unfinishRequest.status !== 200) { + respond(unfinishRequest.body.error, params); + return; } + + // task unfinished + let unfinishedResponse = responses.taskUnfinished; + + params.task = unfinishRequest.body.markedTasks; + + if (unfinishRequest.body.failedTasks !== "") { + unfinishedResponse += ` | Failed to unfinish task(s): "${unfinishRequest.body.failedTasks}"`; + } + + respond(unfinishedResponse, params); + } else if (commands.focusTaskCommands.includes(command)) { + let focusRequest = focusTask(user, message); + + if (focusRequest.status !== 200) { + respond(focusRequest.body.error, params); + return; + } + + // task focused + let focusedResponse = responses.taskFocused; + + params.task = focusRequest.body.focusedTask; + + respond(focusedResponse, params); + } else if (commands.unfocusTaskCommands.includes(command)) { + let unfocusRequest = unfocusTask(user); + + if (unfocusRequest.status !== 200) { + respond(unfocusRequest.body.error, params); + return; + } + + // task unfocused + let unfocusedResponse = responses.taskUnfocused; + + respond(unfocusedResponse, params); } else if (commands.checkCommands.includes(command)) { if (message === "") { - let response = checkTasks(user); - if (response === 0) { - return respond(responses.noTask, params); + let checkRequest = checkTasks(user); + if (checkRequest.status !== 200) { + // no tasks + respond(checkRequest.body.error, params); + return; } - return ComfyJS.Say(response); + + return ComfyJS.Say(checkRequest.body.reply); } else { let mentioned = message.replace("@", ""); - let response = checkTasks(mentioned); - if (response === 0) { + let checkRequest = checkTasks(mentioned); + + if (checkRequest.status !== 200) { // no tasks - return respond(responses.noTaskA, params); + respond(checkRequest.body.error, params); + + return; } - return ComfyJS.Say(response); + return ComfyJS.Say(checkRequest.body.reply); } } else if (commands.adminDeleteCommands.includes(command)) { if (!isMod(flags)) { @@ -172,31 +204,40 @@ ComfyJS.onCommand = (user, command, message, flags, extra) => { return; } - clearUserTasks(mentioned); + let clearUserTaskResponse = clearUserTasks(mentioned); params.mentioned = mentioned; - respond(responses.adminDeleteTasks, params); - return mentioned; - } else if (commands.adminClearDoneCommands.includes(command)) { - if (!isMod(flags)) { - respond(responses.notMod, params); - return; - } else { - clearAllDoneTasks(); - respond(responses.clearedDone, params); - } - } else if (commands.adminClearAllCommands.includes(command)) { - if (!isMod(flags)) { - respond(responses.notMod, params); - return; - } else { - clearAllTasks(); - respond(responses.clearedAll, params); - } - } else if (commands.clearMyDoneCommands.includes(command)) { - let response = clearOwnDoneTasks(user); - if (response === 0) { + if (clearUserTaskResponse.status === 0) { + // no tasks + respond(responses.noTaskA, params); + return; + } + + respond(responses.adminDeleteTasks, params); + return; + } else if (commands.adminClearDoneCommands.includes(command)) { + if (!isStreamer(flags)) { + respond(responses.notStreamer, params); + return; + } + + clearAllDoneTasks(); + respond(responses.clearedDone, params); + return; + } else if (commands.adminClearAllCommands.includes(command)) { + if (!isStreamer(flags)) { + respond(responses.notStreamer, params); + return; + } + + clearAll(); + respond(responses.clearedAll, params); + return; + } else if (commands.clearMyDoneCommands.includes(command)) { + let clearOwnDoneResponse = clearOwnDoneTasks(user); + + if (clearOwnDoneResponse.status === 0) { // no tasks respond(responses.noTask, params); return; @@ -204,17 +245,109 @@ ComfyJS.onCommand = (user, command, message, flags, extra) => { respond(responses.clearedMyDone, params); } else if (commands.adminClearNotStreamerCommands.includes(command)) { - clearAllExceptStreamer(auth.channel); - respond(responses.clearTasksExceptBroadcaster, params); - } else if (commands.helpCommands.includes(command)) { - respond(responses.help, params); - } else if (commands.listCommands.includes(command)) { - let response = listTasks(user); - if (response === 0) { - respond(responses.noTask, params); + if (!isStreamer(flags)) { + respond(responses.notStreamer, params); return; } - ComfyJS.Say(response); + + clearAllExceptStreamer(auth.channel); + respond(responses.clearTasksExceptBroadcaster, params); + } else if (commands.adminClearTasksCommands.includes(command)) { + if (!isStreamer(flags)) { + respond(responses.notStreamer, params); + return; + } + + clearAllTasks(); + respond(responses.clearedTasks, params); + } else if (commands.listCommands.includes(command)) { + let listTaskResponse = listTasks(user); + + if (listTaskResponse.status !== 200) { + // no tasks + respond(listTaskResponse.body.error, params); + return; + } + + respond(listTaskResponse.body.reply, params); + } else if (commands.checkCountCommands.includes(command)) { + if (message === "") { + let count = completedTasksCount(user); + + params.doneCount = count; + + return respond(responses.checkYourCount, params); + } else { + let mentioned = message.replace("@", ""); + let count = completedTasksCount(mentioned); + + params.doneCount = count; + params.mentioned = mentioned; + + return respond(responses.checkUserCount, params); + } + } else if (commands.checkAllCountCommands.includes(command)) { + let count = getBoardTotalTaskCount(); + + if (count === 0) { + respond(responses.noCountAll, params); + return; + } + + params.doneCount = count; + + respond(responses.checkAllCount, params); + } else if (commands.checkMyPointsCommands.includes(command)) { + if (message === "") { + let points = calculatePoints(user); + + params.pointCount = points; + + return respond(responses.checkMyPoints, params); + } else { + let mentioned = message.replace("@", ""); + let points = calculatePoints(mentioned); + + params.pointCount = points; + params.mentioned = mentioned; + + return respond(responses.checkUserPoints, params); + } + } else if (commands.adminSetBoardCount.includes(command)) { + if (!isStreamer(flags)) { + respond(responses.notStreamer, params); + return; + } + + // check if message is a number using regex + if (!/^\d+$/.test(message)) { + respond(responses.invalidNumber, params); + return; + } + + params.count = message; + + setTotalCompleteCount(message); + + respond(responses.setBoardCount, params); + } else if (commands.adminResetBoardCount.includes(command)) { + if (!isStreamer(flags)) { + respond(responses.notStreamer, params); + return; + } + + resetBoardCount(); + respond(responses.clearedBoardCount, params); + } else if (commands.adminResetUsersCount.includes(command)) { + if (!isStreamer(flags)) { + respond(responses.notStreamer, params); + return; + } + + resetUsersCount(); + respond(responses.clearedUsersCount, params); + } else if (commands.helpCommands.includes(command)) { + respond(responses.help, params); } else if (commands.additionalCommands[command]) { respond(commands.additionalCommands[command], params); } else { diff --git a/scripts/taskList.js b/scripts/taskList.js index 622c214..d238709 100644 --- a/scripts/taskList.js +++ b/scripts/taskList.js @@ -2,16 +2,21 @@ DB structure: - tasks - - username: + - [username]: - todos (array) - - [{text, done}, {text, done}] - - done + - [{text, done, focus}, {text, done, focus}] - userColor +- counts + - users + - [username]: + - completeCount + - totalCompleteCount */ const settings = configs.settings; const styles = configs.styles; const scrollSpeed = configs.animation.scrollSpeed; +const responses = configs.responses; let scrolling = false; let primaryAnimation, secondaryAnimation; @@ -145,12 +150,102 @@ function setupDB() { if (!localStorage.tasks) { localStorage.setItem(`tasks`, "{}"); } + if (!localStorage.counts) { + localStorage.setItem(`counts`, JSON.stringify({ users: {} })); + } } +function incompleteTasksCount(username) { + const tasks = JSON.parse(localStorage.tasks); + if (!tasks[username]) { + return 0; + } + return tasks[username].todos.filter((t) => !t.done).length; +} + +function completedTasksCount(username) { + const counts = JSON.parse(localStorage.counts); + if (!counts.users[username.toLowerCase()]) { + return 0; + } + return counts.users[username.toLowerCase()].completeCount; +} + +function getUserTotalTaskCount(username) { + return incompleteTasksCount(username) + completedTasksCount(username); +} + +function addDoneCount(username, value) { + const counts = JSON.parse(localStorage.counts); + + if (!counts.users[username.toLowerCase()]) { + counts.users[username.toLowerCase()] = { + completeCount: 0, + }; + } + + if (!counts.totalCompleteCount) { + counts.totalCompleteCount = 0; + } + + counts.users[username.toLowerCase()].completeCount += value; + counts.totalCompleteCount += value; + + localStorage.setItem(`counts`, JSON.stringify(counts)); +} + +function setTotalCompleteCount(value) { + const counts = JSON.parse(localStorage.counts); + + counts.totalCompleteCount = parseInt(value); + + localStorage.setItem(`counts`, JSON.stringify(counts)); +} + +function calculatePoints(username) { + const counts = JSON.parse(localStorage.counts); + + if (!counts.users[username.toLowerCase()]) { + return 0; + } + + return ( + counts.users[username.toLowerCase()].completeCount * + settings.pointsPerTask + ); +} + +function getBoardTotalTaskCount() { + const counts = JSON.parse(localStorage.counts); + + if (!counts.totalCompleteCount) { + return 0; + } + + return counts.totalCompleteCount; +} + +function resetBoardCount() { + const counts = JSON.parse(localStorage.counts); + + counts.totalCompleteCount = 0; + + localStorage.setItem(`counts`, JSON.stringify(counts)); +} + +function resetUsersCount() { + const counts = JSON.parse(localStorage.counts); + + counts.users = {}; + + localStorage.setItem(`counts`, JSON.stringify(counts)); +} + +// status, body // 0: limit has reached // 1: duplicate task // 2: invalid input -// string (single or multiple tasks): success +// 200: success function addTask(username, userColor, task) { const tasks = JSON.parse(localStorage.tasks); if (!tasks[username]) { @@ -165,7 +260,13 @@ function addTask(username, userColor, task) { incompleteTasksCount(username) >= settings.limit && settings.enableLimit ) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has reached the limit of ${settings.limit} tasks`, + error: responses.noTaskAdded, + }, + }; } if ( @@ -173,12 +274,35 @@ function addTask(username, userColor, task) { (t) => t.text.toLowerCase() === task.toLowerCase() ) ) { - return 1; + return { + status: 1, + body: { + "error message": `@${username} already has this task`, + error: responses.duplicateTask, + }, + }; } // if task is whitespace or empty if (!task || !task.trim()) { - return 2; + return { + status: 2, + body: { + "error message": `@${username} empty task`, + error: responses.noTaskContent, + }, + }; + } + + // if task is "all", return error + if (task.toLowerCase() === "all") { + return { + status: 2, + body: { + "error message": `@${username} all is a reserved keyword`, + error: responses.noTaskContent, + }, + }; } let tasksFailedToAdd = []; @@ -204,37 +328,221 @@ function addTask(username, userColor, task) { } for (const t of tasksToAdd) { - tasks[username].todos.push({ text: t, done: false }); + if (t === "") { + continue; + } + if (t === "all") { + tasksFailedToAdd.push(t); + // remove from tasksToAdd + tasksToAdd = tasksToAdd.filter((task) => task !== t); + continue; + } + if (tasks[username].todos.find((task) => task.text === t)) { + tasksToAdd = tasksToAdd.filter((task) => task !== t); + tasksFailedToAdd.push(t); + continue; + } + tasks[username].todos.push({ + text: t, + done: false, + focus: false, + }); } + localStorage.setItem(`tasks`, JSON.stringify(tasks)); + if (!scrolling) { renderTaskListToDOM(); } + return { - task: tasksToAdd.join('", "'), - tasksFailedToAdd: tasksFailedToAdd.join('", "') || "", + status: 200, + body: { + task: tasksToAdd.join('", "'), + tasksFailedToAdd: tasksFailedToAdd.join('", "') || "", + }, }; } - tasks[username].todos.push({ text: task, done: false }); + tasks[username].todos.push({ text: task, done: false, focus: false }); localStorage.setItem(`tasks`, JSON.stringify(tasks)); if (!scrolling) { renderTaskListToDOM(); } return { - task: task, - tasksFailedToAdd: "", + status: 200, + body: { + task: task, + tasksFailedToAdd: "", + }, }; } // 0: user has no tasks // 1: invalid input -// removed task: success +// 200: success +function focusTask(username, task) { + const tasks = JSON.parse(localStorage.tasks); + + if (!tasks[username] || tasks[username].todos.length === 0) { + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; + } + + const incompleteTasks = tasks[username].todos.filter((t) => !t.done); + if (incompleteTasks.length === 0) { + return { + status: 0, + body: { + "error message": `@${username} has no incomplete tasks`, + error: responses.noTask, + }, + }; + } + + if (task.includes(",")) { + return { + status: 1, + body: { + "error message": `@${username} need to specify ONLY ONE task`, + error: responses.onlyOneFocus, + }, + }; + } + + let index = tasks[username].todos.findIndex( + (t) => t.text.toLowerCase() === task.toLowerCase() + ); + + if (index === -1) { + if (isInt(task)) { + index = parseInt(task) - 1; // ACTUAL INDEX + } else if (incompleteTasks.length === 1) { + index = tasks[username].todos.findIndex((t) => !t.done); + } else { + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyFocusTask, + }, + }; + } + + if (index < 0 || index > tasks[username].todos.length - 1) { + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyFocusTask, + }, + }; + } + } else { + if (tasks[username].todos[index].done) { + return { + status: 1, + body: { + "error message": `@${username} task is already completed`, + error: responses.specifyFocusTask, + }, + }; + } + } + + let focusedTask = tasks[username].todos[index].text; + + // if task is already focused, return 1 + if (tasks[username].todos[index].focus) { + return { + status: 1, + body: { + "error message": `@${username} task is already focused`, + error: responses.alreadyFocusedTask, + }, + }; + } + + // set all tasks to unfocused + for (const task of tasks[username].todos) { + task.focus = false; + } + + // set task to focused + tasks[username].todos[index].focus = true; + + localStorage.setItem(`tasks`, JSON.stringify(tasks)); + + if (!scrolling) { + renderTaskListToDOM(); + } + + return { + status: 200, + body: { + focusedTask: focusedTask, + }, + }; +} + +// 0: user has no tasks +// 1: invalid input +// 200: success +function unfocusTask(username) { + const tasks = JSON.parse(localStorage.tasks); + + if (!tasks[username] || tasks[username].todos.length === 0) { + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; + } + + // if no tasks are focused, return 1 + if (!tasks[username].todos.find((t) => t.focus)) { + return { + status: 1, + body: { + "error message": `@${username} no tasks are focused`, + error: responses.noFocusedTask, + }, + }; + } + + // set all tasks to unfocused + for (const task of tasks[username].todos) { + task.focus = false; + } + + localStorage.setItem(`tasks`, JSON.stringify(tasks)); + + return { + status: 200, + }; +} + +// 0: user has no tasks +// 1: invalid input +// 200: success function removeTask(username, task) { const tasks = JSON.parse(localStorage.tasks); if (!tasks[username] || tasks[username].todos.length === 0) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; } const incompleteTasks = tasks[username].todos.filter((t) => !t.done); @@ -286,7 +594,13 @@ function removeTask(username, task) { } if (tasksRemoved.length === 0) { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } // sort removedTaskIndex in descending order @@ -302,8 +616,11 @@ function removeTask(username, task) { renderTaskListToDOM(); } return { - removedTasks: tasksRemoved.join('", "'), - failedTasks: tasksFailedToRemove.join('", "'), + status: 200, + body: { + removedTasks: tasksRemoved.join('", "'), + failedTasks: tasksFailedToRemove.join('", "'), + }, }; } else { let index = tasks[username].todos.findIndex( @@ -316,11 +633,23 @@ function removeTask(username, task) { } else if (incompleteTasks.length === 1) { index = tasks[username].todos.findIndex((t) => !t.done); } else { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } if (index < 0 || index > tasks[username].todos.length - 1) { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } } @@ -330,8 +659,11 @@ function removeTask(username, task) { localStorage.setItem(`tasks`, JSON.stringify(tasks)); renderTaskListToDOM(); return { - removedTasks: task, - failedTasks: "", + status: 200, + body: { + removedTasks: task, + failedTasks: "", + }, }; } } @@ -346,12 +678,18 @@ function isInt(value) { } // 0: user has no tasks -// 1: success +// 200: success function clearOwnDoneTasks(username) { const tasks = JSON.parse(localStorage.tasks); if (!tasks[username] || tasks[username].todos.length === 0) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; } let incompleteUserTasks = tasks[username].todos.filter((t) => !t.done); @@ -364,22 +702,41 @@ function clearOwnDoneTasks(username) { renderTaskListToDOM(); } - return 1; + return { + status: 200, + }; } // 0: user has no tasks // 1: invalid input -// task: succcess +// 2: task is already completed +// 200: succcess function markTaskDone(username, task) { const tasks = JSON.parse(localStorage.tasks); // user does not have any tasks if (!tasks[username] || tasks[username].todos.length === 0) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; } const incompleteTasks = tasks[username].todos.filter((t) => !t.done); + if (incompleteTasks.length === 0) { + return { + status: 0, + body: { + "error message": `@${username} has no incomplete tasks`, + error: responses.noTask, + }, + }; + } + // match regex: integers separated by space e.g. '1 2 3 4' if (task.match(/^(\d+ )*\d+$/)) { // insert commas between integers @@ -399,6 +756,12 @@ function markTaskDone(username, task) { (task) => task.text.toLowerCase() === t.toLowerCase() ); + // check if task is already marked done + if (index !== -1 && tasks[username].todos[index].done) { + tasksFailedToComplete.push(t); + continue; + } + if (index === -1) { if (isInt(t)) { index = parseInt(t) - 1; // ACTUAL INDEX @@ -409,6 +772,8 @@ function markTaskDone(username, task) { tasksMarkedComplete.push( tasks[username].todos[index].text ); + // increment count + addDoneCount(username, 1); } else { tasksFailedToComplete.push(t); continue; @@ -417,19 +782,33 @@ function markTaskDone(username, task) { if (index < 0 || index > tasks[username].todos.length - 1) { tasksFailedToComplete.push(t); continue; + } else if (tasks[username].todos[index].done) { + tasksFailedToComplete.push(t); + continue; } else { tasksMarkedComplete.push( tasks[username].todos[index].text ); + // increment count + addDoneCount(username, 1); } } else { tasksMarkedComplete.push(tasks[username].todos[index].text); + // increment count + addDoneCount(username, 1); } tasks[username].todos[index].done = true; + tasks[username].todos[index].focus = false; } if (tasksMarkedComplete.length === 0) { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } localStorage.setItem(`tasks`, JSON.stringify(tasks)); @@ -437,50 +816,108 @@ function markTaskDone(username, task) { renderTaskListToDOM(); } return { - markedTasks: tasksMarkedComplete.join('", "'), - failedTasks: tasksFailedToComplete.join('", "'), + status: 200, + body: { + markedTasks: tasksMarkedComplete.join('", "'), + failedTasks: tasksFailedToComplete.join('", "'), + markedTasksCount: tasksMarkedComplete.length, + }, }; } else { + // if there's no comma in the task (single task) + let index = tasks[username].todos.findIndex( - (t) => t.text.toLowerCase() === task.toLowerCase() && !t.done + (t) => t.text.toLowerCase() === task.toLowerCase() ); + // is there a task with focus on? + let focusedTask = tasks[username].todos.find((t) => t.focus); + if (index === -1) { if (isInt(task)) { index = parseInt(task) - 1; // ACTUAL INDEX } else if (incompleteTasks.length === 1) { index = tasks[username].todos.findIndex((t) => !t.done); + } else if (focusedTask) { + index = tasks[username].todos.findIndex( + (t) => + t.text.toLowerCase() === + focusedTask.text.toLowerCase() + ); + } else if (settings.automaticDoneIndex) { + // index is the first incomplete task + index = tasks[username].todos.findIndex((t) => !t.done); } else { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } if (index < 0 || index > tasks[username].todos.length - 1) { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } } + // task is already marked done + if (tasks[username].todos[index].done) { + return { + status: 2, + body: { + "error message": `@${username} task is already completed`, + error: responses.alreadyDoneTask, + }, + }; + } + task = tasks[username].todos[index].text; tasks[username].todos[index].done = true; + addDoneCount(username, 1); + localStorage.setItem(`tasks`, JSON.stringify(tasks)); if (!scrolling) { renderTaskListToDOM(); } return { - markedTasks: task, - failedTasks: "", + status: 200, + body: { + markedTasks: task, + failedTasks: "", + markedTasksCount: 1, + }, }; } } +// 0: user has no tasks +// 200: success function markAllTasksAsDone(username) { const tasks = JSON.parse(localStorage.tasks); // user does not have any tasks if (!tasks[username] || tasks[username].todos.length === 0) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; } for (const task of tasks[username].todos) { + if (!task.done) { + addDoneCount(username, 1); + } task.done = true; } @@ -489,15 +926,27 @@ function markAllTasksAsDone(username) { renderTaskListToDOM(); } - return 1; + return { + status: 200, + }; } +// 0: user has no tasks +// 1: invalid input +// 2: task is already incomplete +// 200: succcess function markTaskUndone(username, task) { const tasks = JSON.parse(localStorage.tasks); // user does not have any tasks if (!tasks[username] || tasks[username].todos.length === 0) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; } const completedTasks = tasks[username].todos.filter((t) => t.done); @@ -540,12 +989,19 @@ function markTaskUndone(username, task) { } } else { tasksMarkedUndone.push(tasks[username].todos[index].text); + addDoneCount(username, -1); } tasks[username].todos[index].done = false; } if (tasksMarkedUndone.length === 0) { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } localStorage.setItem(`tasks`, JSON.stringify(tasks)); @@ -554,8 +1010,11 @@ function markTaskUndone(username, task) { } return { - markedTasks: tasksMarkedUndone.join('", "'), - failedTasks: tasksFailedToMarkUndone.join('", "'), + status: 200, + body: { + markedTasks: tasksMarkedUndone.join('", "'), + failedTasks: tasksFailedToMarkUndone.join('", "'), + }, }; } else { let index = tasks[username].todos.findIndex( @@ -568,31 +1027,53 @@ function markTaskUndone(username, task) { } else if (completedTasks.length === 1) { index = tasks[username].todos.findIndex((t) => t.done); } else { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } if (index < 0 || index > tasks[username].todos.length - 1) { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } tasks[username].todos[index].done = false; + localStorage.setItem(`tasks`, JSON.stringify(tasks)); + if (!scrolling) { renderTaskListToDOM(); } return { - markedTasks: tasks[username].todos[index].text, - failedTasks: "", + status: 200, + body: { + markedTasks: tasks[username].todos[index].text, + failedTasks: "", + }, }; } else { tasks[username].todos[index].done = false; + localStorage.setItem(`tasks`, JSON.stringify(tasks)); + if (!scrolling) { renderTaskListToDOM(); } return { - markedTasks: tasks[username].todos[index].text, - failedTasks: "", + status: 200, + body: { + markedTasks: tasks[username].todos[index].text, + failedTasks: "", + }, }; } } @@ -600,13 +1081,19 @@ function markTaskUndone(username, task) { // 0: user has no tasks // 1: invalid input -// [original task, new task]: succcess +// 200: success function editTask(username, message) { const tasks = JSON.parse(localStorage.tasks); let noSpecifiedIndex = false; if (!tasks[username] || tasks[username].todos.length === 0) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; } // example 'message': 1 new task @@ -623,7 +1110,13 @@ function editTask(username, message) { } if (isNaN(index)) { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } let newTask = message.split(" ").slice(1).join(" "); @@ -634,11 +1127,23 @@ function editTask(username, message) { // if newTask is empty or whitespace, return 1 if (!newTask || !newTask.trim()) { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.noTaskContent, + }, + }; } if (index < 0 || index > tasks[username].todos.length - 1) { - return 1; + return { + status: 1, + body: { + "error message": `@${username} invalid input`, + error: responses.specifyTaskIndex, + }, + }; } let originalTask = tasks[username].todos[index].text; @@ -650,7 +1155,13 @@ function editTask(username, message) { renderTaskListToDOM(); } - return [originalTask, newTask]; + return { + status: 200, + body: { + originalTask: originalTask, + newTask: newTask, + }, + }; } // 0: user has no tasks @@ -663,7 +1174,13 @@ function checkTasks(username) { ); if (!tasks[username]) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; } // filter completed tasks @@ -681,7 +1198,10 @@ function checkTasks(username) { t.text.toLowerCase() === incompleteTasks[i].text.toLowerCase() ) + 1; - reply += `${taskIndex}. ${incompleteTasks[i].text} | `; + + reply += `${taskIndex}. ${ + incompleteTasks[i].focus ? "(FOCUSED)" : "" + } ${incompleteTasks[i].text} | `; } reply = reply.slice(0, -3); @@ -699,20 +1219,37 @@ function checkTasks(username) { // } // reply = reply.slice(0, -3); - return reply; + return { + status: 200, + body: { + reply: reply, + }, + }; } // 0: user has no tasks function listTasks(username) { const tasks = JSON.parse(localStorage.tasks); if (!tasks[username]) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; } // filter completed tasks const incompleteTasks = tasks[username].todos.filter((t) => !t.done); if (incompleteTasks.length === 0) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has no incomplete tasks`, + error: responses.noTask, + }, + }; } // format incomplete tasks into string: 1. task 1 | 2. task 2 | 3. task 3... @@ -729,15 +1266,12 @@ function listTasks(username) { reply += `${incompleteTasks[i].text}, `; } reply = reply.slice(0, -2); - return reply; -} - -function incompleteTasksCount(username) { - const tasks = JSON.parse(localStorage.tasks); - if (!tasks[username]) { - return 0; - } - return tasks[username].todos.filter((t) => !t.done).length; + return { + status: 200, + body: { + reply: reply, + }, + }; } // 0: user has no tasks @@ -749,12 +1283,22 @@ function clearUserTasks(username) { ); if (!username) { - return 0; + return { + status: 0, + body: { + "error message": `@${username} has no tasks`, + error: responses.noTask, + }, + }; } tasks[username].todos = []; localStorage.setItem(`tasks`, JSON.stringify(tasks)); + + return { + status: 200, + }; } function clearAllDoneTasks() { @@ -766,15 +1310,35 @@ function clearAllDoneTasks() { checkToAnimate(); localStorage.setItem(`tasks`, JSON.stringify(tasks)); renderTaskListToDOM(); + + return { + status: 200, + }; } function clearAllTasks() { + localStorage.setItem(`tasks`, "{}"); + cancelAnimation(); + checkToAnimate(); + renderTaskListToDOM(); + + return { + status: 200, + }; +} + +function clearAll() { resetDB(); cancelAnimation(); checkToAnimate(); renderTaskListToDOM(); + + return { + status: 200, + }; } +// 200: success function clearAllExceptStreamer(streamer) { // clear all tasks except for broadcasters const tasks = JSON.parse(localStorage.tasks); @@ -792,6 +1356,10 @@ function clearAllExceptStreamer(streamer) { checkToAnimate(); renderTaskListToDOM(); + + return { + status: 200, + }; } function renderTaskListToDOM() { @@ -806,6 +1374,8 @@ function renderTaskListToDOM() { for (const user in tasks) { const userTasks = tasks[user]; if (userTasks.todos.length === 0) { + // remove user from tasks + delete tasks[user]; continue; } @@ -840,6 +1410,8 @@ function renderTaskListToDOM() { if (task.done) { taskElement.classList.add("done"); completedTasksCount++; + } else if (task.focus) { + taskElement.classList.add("focus"); } taskElement.innerText = task.text; @@ -851,6 +1423,7 @@ function renderTaskListToDOM() { ".task-count" ).innerText = `${completedTasksCount}/${totalTaskCount}`; }); + localStorage.setItem(`tasks`, JSON.stringify(tasks)); checkToAnimate(); } @@ -974,7 +1547,6 @@ function cancelAnimation() { secondaryAnimation.cancel(); } scrolling = false; - // console.log("animation cancelled"); } (function () { diff --git a/styles/taskList.css b/styles/taskList.css index 50f4a88..2dfe322 100644 --- a/styles/taskList.css +++ b/styles/taskList.css @@ -112,6 +112,8 @@ body { } #main-container .task-wrapper .task-container .task .user-tasks { list-style-position: inside; + width: -moz-fit-content; + width: fit-content; } #main-container .task-wrapper .task-container .task .user-tasks .todo { overflow: hidden; @@ -120,4 +122,12 @@ body { } #main-container .task-wrapper .task-container .task .user-tasks .done { text-decoration: line-through; +} +#main-container .task-wrapper .task-container .task .user-tasks .focus { + background: var(--focus-task-background-color); + color: var(--focus-task-font-color); + padding: var(--focus-task-vertical-padding) var(--focus-task-horizontal-padding); + border-radius: var(--focus-task-border-radius); + width: -moz-fit-content; + width: fit-content; }/*# sourceMappingURL=taskList.css.map */ \ No newline at end of file