Compare commits
7 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d8df9b2ca1 | ||
|
|
72da262759 | ||
|
|
de75b3cd4c | ||
|
|
7c9869e967 | ||
|
|
7fc656680e | ||
|
|
52bbde40bd | ||
|
|
efcc8000f8 |
7 changed files with 459 additions and 1331 deletions
424
configs.js
424
configs.js
|
|
@ -1,350 +1,110 @@
|
||||||
const configs = (function () {
|
const configs = (function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
// settings
|
|
||||||
const enableLimit = true; // true or false
|
|
||||||
const limit = 5; // integer
|
|
||||||
|
|
||||||
// animation
|
|
||||||
const scrollSpeed = 40; // milliseconds
|
|
||||||
const gapBetweenScrolls = 0; // px
|
|
||||||
|
|
||||||
// STYLES
|
|
||||||
// task list
|
|
||||||
const taskListBackgroundColor = "#000000"; // hex only
|
|
||||||
const taskListBackgroundOpacity = 0; // 0.0 - 1.0
|
|
||||||
|
|
||||||
const taskListBorderWidth = "0px"; // px
|
|
||||||
const taskListBorderColor = "#ffffff"; // hex or name
|
|
||||||
const taskListBorderRadius = "5px"; // px
|
|
||||||
|
|
||||||
const taskListHorizontalPadding = "0px"; // px
|
|
||||||
const taskListVerticalPadding = "0px"; // px
|
|
||||||
|
|
||||||
// header
|
|
||||||
const headerHorizontalPadding = "10px"; // px
|
|
||||||
const headerVerticalPadding = "10px"; // px
|
|
||||||
|
|
||||||
const headerBackgroundColor = "#000000"; // hex only
|
|
||||||
const headerBackgroundOpacity = 0.8; // 0.0 - 1.0
|
|
||||||
|
|
||||||
const headerBorderWidth = "2px"; // px
|
|
||||||
const headerBorderColor = "#ffffff"; // hex or name
|
|
||||||
const headerBorderRadius = "5px"; // px
|
|
||||||
|
|
||||||
const headerFontFamily = "Fredoka"; // font name
|
|
||||||
const headerGoogleFont = true; // true: use google font, false: use system font
|
|
||||||
|
|
||||||
const headerFontSize = "25px"; // px
|
|
||||||
const headerFontWeight = "bold"; // normal or bold or number
|
|
||||||
|
|
||||||
const headerFontColor = "#ffffff"; // hex or name
|
|
||||||
|
|
||||||
// body
|
|
||||||
const bodyBackgroundColor = "#000000"; // hex only
|
|
||||||
const bodyBackgroundOpacity = 0; // 0.0 - 1.0
|
|
||||||
|
|
||||||
const bodyBorderWidth = "0px"; // px
|
|
||||||
const bodyBorderColor = "#fff"; // hex or name
|
|
||||||
const bodyBorderRadius = "5px"; // px
|
|
||||||
|
|
||||||
// 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 taskWidth = "100%";
|
|
||||||
|
|
||||||
const taskBackgroundColor = "#000000"; // hex only
|
|
||||||
const taskBackgroundOpacity = 0.7; // 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 taskBorderColor = "#000000"; // hex or name
|
|
||||||
const taskBorderWidth = "0px"; // px
|
|
||||||
const taskBorderRadius = "5px"; // px
|
|
||||||
|
|
||||||
const taskMarginBottom = "5px"; // px
|
|
||||||
const taskHorizontalPadding = "20px"; // px
|
|
||||||
const taskVerticalPadding = "10px"; // px
|
|
||||||
|
|
||||||
// Add task commands - please add commands in the exact format
|
|
||||||
const addTaskCommands = [
|
|
||||||
"!taska",
|
|
||||||
"!taskadd",
|
|
||||||
"!atask",
|
|
||||||
"!addtask",
|
|
||||||
"!task",
|
|
||||||
"!add",
|
|
||||||
"!todo",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Edit task commands - please add commands in the exact format
|
|
||||||
const editTaskCommands = [
|
|
||||||
"!taske",
|
|
||||||
"!taskedit",
|
|
||||||
"!etask",
|
|
||||||
"!edittask",
|
|
||||||
"!edit",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Delete task commands - please add commands in the exact format
|
|
||||||
const deleteTaskCommands = [
|
|
||||||
"!taskd",
|
|
||||||
"!taskdel",
|
|
||||||
"!taskdelete",
|
|
||||||
"!deltask",
|
|
||||||
"!deletetask",
|
|
||||||
"!taskr",
|
|
||||||
"!taskremove",
|
|
||||||
"!rtask",
|
|
||||||
"!removetask",
|
|
||||||
"!remove",
|
|
||||||
"!delete",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Finish task commands - please add commands in the exact format
|
|
||||||
const finishTaskCommands = [
|
|
||||||
"!taskf",
|
|
||||||
"!taskfinish",
|
|
||||||
"!ftask",
|
|
||||||
"!finishtask",
|
|
||||||
"!taskd",
|
|
||||||
"!taskdone",
|
|
||||||
"!donetask",
|
|
||||||
"!dtask",
|
|
||||||
"!finish",
|
|
||||||
"!done",
|
|
||||||
"!finished",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Unfinish task commands - please add commands in the exact format
|
|
||||||
const unfinishTaskCommands = [
|
|
||||||
"!tasku",
|
|
||||||
"!taskunfinish",
|
|
||||||
"!utask",
|
|
||||||
"!unfinishtask",
|
|
||||||
"!taskud",
|
|
||||||
"!taskundone",
|
|
||||||
"!undonetask",
|
|
||||||
"!undone",
|
|
||||||
"!unfinish",
|
|
||||||
"!unfinished",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Check task commands - please add commands in the exact format
|
|
||||||
const checkCommands = [
|
|
||||||
"!taskc",
|
|
||||||
"!taskcheck",
|
|
||||||
"!ctask",
|
|
||||||
"!checktask",
|
|
||||||
"!mytask",
|
|
||||||
"!check",
|
|
||||||
"!mytasks",
|
|
||||||
];
|
|
||||||
|
|
||||||
// List tasks commands - please add commands in the exact format
|
|
||||||
const listCommands = ["!taskl", "!tasklist", "!listtasks", "!list"];
|
|
||||||
|
|
||||||
// Clear my done commands - please add commands in the exact format
|
|
||||||
const clearMyDoneCommands = ["!clearmydone"];
|
|
||||||
|
|
||||||
// Help commands - please add commands in the exact format
|
|
||||||
const helpCommands = [
|
|
||||||
"!taskh",
|
|
||||||
"!taskhelp",
|
|
||||||
"!htask",
|
|
||||||
"!helptask",
|
|
||||||
"!tasks",
|
|
||||||
"!help",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Admin clear all except streamer - please add commands following the exact format
|
|
||||||
const adminClearNotStreamerCommands = [
|
|
||||||
"!clearnotstreamer",
|
|
||||||
"!aclearnotstreamer",
|
|
||||||
"!adminclearnotstreamer",
|
|
||||||
"!clearns",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Admin delete - please add commands following the exact format
|
|
||||||
const adminDeleteCommands = [
|
|
||||||
"!taskadel",
|
|
||||||
"!adel",
|
|
||||||
"!adelete",
|
|
||||||
"!admindelete",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Admin clear done - please add commands following the exact format
|
|
||||||
const adminClearDoneCommands = [
|
|
||||||
"!acleardone",
|
|
||||||
"!admincleardone",
|
|
||||||
"!cleardone",
|
|
||||||
];
|
|
||||||
|
|
||||||
const adminClearAllCommands = [
|
|
||||||
"!clearall",
|
|
||||||
"!allclear",
|
|
||||||
"!adminclearall",
|
|
||||||
"!adminallclear",
|
|
||||||
"!aclearall",
|
|
||||||
"!aclear",
|
|
||||||
];
|
|
||||||
|
|
||||||
// Responses
|
|
||||||
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}!";
|
|
||||||
|
|
||||||
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}!";
|
|
||||||
const taskUnfinished =
|
|
||||||
'Task(s) "{task}" has been unmarked as done, {user}!';
|
|
||||||
const taskEdited =
|
|
||||||
"Task '{originalTask}' has been edited to '{task}' successfully, {user}";
|
|
||||||
const noTaskEdit = "Try doing !edit [index] [new task] {user}";
|
|
||||||
|
|
||||||
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}";
|
|
||||||
const notMod = "Permission denied, {user}; Mods only";
|
|
||||||
const clearedAll = "All tasks have been cleared!";
|
|
||||||
const clearedDone = "All completed tasks have been cleared!";
|
|
||||||
const clearedMyDone = "All your completed tasks have been cleared!";
|
|
||||||
const specifyUser = "Try specifying a user to delete their tasks {user}";
|
|
||||||
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
|
|
||||||
// function checkTasks(username)
|
|
||||||
|
|
||||||
const additionalCommands = {
|
|
||||||
"!botcred":
|
|
||||||
"{user} Ryan is the creator of this bot! You can find him on https://github.com/liyunze-coding or https://www.twitch.tv/RythonDev",
|
|
||||||
};
|
|
||||||
|
|
||||||
const titles = [
|
|
||||||
"!taskhelp",
|
|
||||||
"!task",
|
|
||||||
"!edit",
|
|
||||||
"!remove",
|
|
||||||
"!done",
|
|
||||||
"!botcred",
|
|
||||||
];
|
|
||||||
|
|
||||||
const settings = {
|
const settings = {
|
||||||
enableLimit,
|
streamer: "RythonDev",
|
||||||
limit,
|
testTasks: false, // true or false
|
||||||
headerGoogleFont,
|
headerGoogleFont: true, // true: use google font, false: use system font
|
||||||
taskGoogleFont,
|
taskGoogleFont: true, // true: use google font, false: use system font
|
||||||
};
|
showStreamersTasksOnly: false, // true or false
|
||||||
|
|
||||||
const styles = {
|
|
||||||
taskListBackgroundColor,
|
|
||||||
taskListBackgroundOpacity,
|
|
||||||
taskListBorderWidth,
|
|
||||||
taskListBorderColor,
|
|
||||||
taskListBorderRadius,
|
|
||||||
taskListHorizontalPadding,
|
|
||||||
taskListVerticalPadding,
|
|
||||||
headerHorizontalPadding,
|
|
||||||
headerVerticalPadding,
|
|
||||||
headerBackgroundColor,
|
|
||||||
headerBackgroundOpacity,
|
|
||||||
headerBorderWidth,
|
|
||||||
headerBorderColor,
|
|
||||||
headerBorderRadius,
|
|
||||||
headerFontSize,
|
|
||||||
headerFontWeight,
|
|
||||||
headerFontFamily,
|
|
||||||
headerFontColor,
|
|
||||||
bodyBackgroundColor,
|
|
||||||
bodyBackgroundOpacity,
|
|
||||||
bodyBorderWidth,
|
|
||||||
bodyBorderColor,
|
|
||||||
bodyBorderRadius,
|
|
||||||
taskWidth,
|
|
||||||
lineHeight,
|
|
||||||
usernameFontWeight,
|
|
||||||
usernameColor,
|
|
||||||
taskBackgroundColor,
|
|
||||||
taskBackgroundOpacity,
|
|
||||||
taskFontFamily,
|
|
||||||
taskFontSize,
|
|
||||||
taskFontColor,
|
|
||||||
taskBorderColor,
|
|
||||||
taskBorderWidth,
|
|
||||||
taskBorderRadius,
|
|
||||||
taskMarginBottom,
|
|
||||||
taskHorizontalPadding,
|
|
||||||
taskVerticalPadding,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const animation = {
|
const animation = {
|
||||||
scrollSpeed,
|
scrollSpeed: 40, // milliseconds
|
||||||
gapBetweenScrolls,
|
gapBetweenScrolls: 0, // px
|
||||||
titles,
|
titles: [
|
||||||
|
"!taskhelp",
|
||||||
|
"!task",
|
||||||
|
"!edit",
|
||||||
|
"!remove",
|
||||||
|
"!done",
|
||||||
|
"!undone",
|
||||||
|
"!botcred",
|
||||||
|
"!count",
|
||||||
|
"!points",
|
||||||
|
"!boardcount",
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const commands = {
|
const styles = {
|
||||||
addTaskCommands,
|
// task list
|
||||||
editTaskCommands,
|
taskListBackgroundColor: "#000000", // hex only
|
||||||
deleteTaskCommands,
|
taskListBackgroundOpacity: 0, // 0.0 - 1.0
|
||||||
finishTaskCommands,
|
|
||||||
unfinishTaskCommands,
|
|
||||||
helpCommands,
|
|
||||||
checkCommands,
|
|
||||||
listCommands,
|
|
||||||
clearMyDoneCommands,
|
|
||||||
adminDeleteCommands,
|
|
||||||
adminClearNotStreamerCommands,
|
|
||||||
adminClearDoneCommands,
|
|
||||||
adminClearAllCommands,
|
|
||||||
additionalCommands,
|
|
||||||
};
|
|
||||||
|
|
||||||
const responses = {
|
taskListBorderWidth: "0px", // px
|
||||||
taskAdded,
|
taskListBorderColor: "#ffffff", // hex or name
|
||||||
noTaskAdded,
|
taskListBorderRadius: "0px", // px
|
||||||
noTaskContent,
|
|
||||||
taskDeleted,
|
taskListHorizontalPadding: "0px", // px
|
||||||
specifyTaskIndex,
|
taskListVerticalPadding: "0px", // px
|
||||||
duplicateTask,
|
|
||||||
taskFinished,
|
// header
|
||||||
allTasksFinished,
|
headerHorizontalPadding: "10px", // px
|
||||||
taskUnfinished,
|
headerVerticalPadding: "10px", // px
|
||||||
taskEdited,
|
|
||||||
noTaskEdit,
|
headerBackgroundColor: "#fff", // hex only
|
||||||
noTask,
|
headerBackgroundOpacity: 1, // 0.0 - 1.0
|
||||||
noTaskA,
|
|
||||||
notMod,
|
headerBorderWidth: "0px", // px
|
||||||
help,
|
headerBorderColor: "#ffffff", // hex or name
|
||||||
clearTasksExceptBroadcaster,
|
headerBorderRadius: "3px", // px
|
||||||
adminDeleteTasks,
|
|
||||||
clearedMyDone,
|
headerFontFamily: "Fredoka", // font name
|
||||||
clearedAll,
|
|
||||||
clearedDone,
|
headerFontSize: "25px", // px
|
||||||
specifyUser,
|
headerFontWeight: "bold", // normal or bold or number
|
||||||
|
|
||||||
|
headerFontColor: "#000", // hex or name
|
||||||
|
|
||||||
|
// body
|
||||||
|
bodyBackgroundColor: "#fff", // hex only
|
||||||
|
bodyBackgroundOpacity: 0, // 0.0 - 1.0
|
||||||
|
|
||||||
|
bodyBorderWidth: "0px", // px
|
||||||
|
bodyBorderColor: "#fff", // hex or name
|
||||||
|
bodyBorderRadius: "5px", // px
|
||||||
|
|
||||||
|
// task
|
||||||
|
lineHeight: 1.5, // number
|
||||||
|
usernameFontWeight: "bold", // normal or bold or number
|
||||||
|
usernameColor: "pink", // hex or name or "" for twitch user color
|
||||||
|
usernameFontSize: "20px", // px
|
||||||
|
|
||||||
|
taskWidth: "100%",
|
||||||
|
|
||||||
|
taskBackgroundColor: "#000", // hex only
|
||||||
|
taskBackgroundOpacity: 0, // 0.0 - 1.0
|
||||||
|
|
||||||
|
taskFontFamily: "Poppins", // font name
|
||||||
|
|
||||||
|
taskFontSize: "20px", // px
|
||||||
|
taskFontColor: "#fff", // hex or name
|
||||||
|
|
||||||
|
taskBorderColor: "#fff", // hex or name
|
||||||
|
taskBorderWidth: "0px", // px
|
||||||
|
taskBorderRadius: "10px", // px
|
||||||
|
|
||||||
|
taskMarginBottom: "10px", // px
|
||||||
|
taskHorizontalPadding: "20px", // px
|
||||||
|
taskVerticalPadding: "10px", // px
|
||||||
|
|
||||||
|
// done task
|
||||||
|
doneTaskFontColor: "#bbb", // hex or name
|
||||||
|
|
||||||
|
// focus task
|
||||||
|
focusTaskBackgroundColor: "#fff", // hex only
|
||||||
|
focusTaskBackgroundOpacity: 1, // 0.0 - 1.0
|
||||||
|
focusTaskBorderRadius: "5px", // px
|
||||||
|
|
||||||
|
focusTaskFontColor: "#000", // hex or name
|
||||||
|
|
||||||
|
focusTaskHorizontalPadding: "7px", // px
|
||||||
|
focusTaskVerticalPadding: "0px", // px
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
settings,
|
settings,
|
||||||
styles,
|
styles,
|
||||||
animation,
|
animation,
|
||||||
commands,
|
|
||||||
responses,
|
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
https://id.twitch.tv/oauth2/authorize
|
|
||||||
?client_id=CLIENT_ID_HERE
|
|
||||||
&redirect_uri=http://localhost
|
|
||||||
&response_type=token
|
|
||||||
&scope=channel:moderate+chat:edit+chat:read+channel:manage:broadcast+user:edit:broadcast+channel:read:redemptions+user:read:email
|
|
||||||
25
index.html
25
index.html
|
|
@ -1,44 +1,31 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<head>
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<script src="http://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
|
<script src="http://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/comfy.js@latest/dist/comfy.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/comfy.js@latest/dist/comfy.min.js"></script>
|
||||||
|
|
||||||
<script src="./auth.js"></script>
|
|
||||||
<script src="./configs.js"></script>
|
<script src="./configs.js"></script>
|
||||||
<script defer src="scripts/index.js"></script>
|
<script defer src="scripts/defaultConfigs.js"></script>
|
||||||
<script defer src="scripts/taskList.js"></script>
|
<script defer src="scripts/taskList.js"></script>
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="styles/taskList.css" />
|
<link rel="stylesheet" type="text/css" href="styles/taskList.css" />
|
||||||
|
|
||||||
<title>Task List</title>
|
<title>Task List</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="main-container">
|
<div id="main-container">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<div class="title">!taskhelp</div>
|
<div class="title">!taskhelp</div>
|
||||||
<div class="task-count">0/0</div>
|
<div class="task-count">0/0</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="task-wrapper">
|
<div class="task-wrapper">
|
||||||
<div class="task-container primary">
|
<div class="task-container primary"></div>
|
||||||
<!--
|
|
||||||
<div class="task">
|
|
||||||
<div class="username">RyanPython</div>
|
|
||||||
<ol class="user-tasks">
|
|
||||||
<li class="todo">complete website</li>
|
|
||||||
<li class="todo">work on overlay</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
</div>
|
|
||||||
<div class="task-container secondary"></div>
|
<div class="task-container secondary"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
110
scripts/defaultConfigs.js
Normal file
110
scripts/defaultConfigs.js
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
const defaultConfigs = (function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
const settings = {
|
||||||
|
streamer: "RythonDev",
|
||||||
|
testTasks: false, // true or false
|
||||||
|
headerGoogleFont: true, // true: use google font, false: use system font
|
||||||
|
taskGoogleFont: true, // true: use google font, false: use system font
|
||||||
|
showStreamersTasksOnly: true, // true or false
|
||||||
|
};
|
||||||
|
|
||||||
|
const animation = {
|
||||||
|
scrollSpeed: 40, // milliseconds
|
||||||
|
gapBetweenScrolls: 0, // px
|
||||||
|
titles: [
|
||||||
|
"!taskhelp",
|
||||||
|
"!task",
|
||||||
|
"!edit",
|
||||||
|
"!remove",
|
||||||
|
"!done",
|
||||||
|
"!undone",
|
||||||
|
"!botcred",
|
||||||
|
"!count",
|
||||||
|
"!points",
|
||||||
|
"!boardcount",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
// task list
|
||||||
|
taskListBackgroundColor: "#000000", // hex only
|
||||||
|
taskListBackgroundOpacity: 0, // 0.0 - 1.0
|
||||||
|
|
||||||
|
taskListBorderWidth: "0px", // px
|
||||||
|
taskListBorderColor: "#ffffff", // hex or name
|
||||||
|
taskListBorderRadius: "0px", // px
|
||||||
|
|
||||||
|
taskListHorizontalPadding: "0px", // px
|
||||||
|
taskListVerticalPadding: "0px", // px
|
||||||
|
|
||||||
|
// header
|
||||||
|
headerHorizontalPadding: "10px", // px
|
||||||
|
headerVerticalPadding: "10px", // px
|
||||||
|
|
||||||
|
headerBackgroundColor: "#fff", // hex only
|
||||||
|
headerBackgroundOpacity: 1, // 0.0 - 1.0
|
||||||
|
|
||||||
|
headerBorderWidth: "0px", // px
|
||||||
|
headerBorderColor: "#ffffff", // hex or name
|
||||||
|
headerBorderRadius: "3px", // px
|
||||||
|
|
||||||
|
headerFontFamily: "Fredoka", // font name
|
||||||
|
|
||||||
|
headerFontSize: "25px", // px
|
||||||
|
headerFontWeight: "bold", // normal or bold or number
|
||||||
|
|
||||||
|
headerFontColor: "#000", // hex or name
|
||||||
|
|
||||||
|
// body
|
||||||
|
bodyBackgroundColor: "#fff", // hex only
|
||||||
|
bodyBackgroundOpacity: 0, // 0.0 - 1.0
|
||||||
|
|
||||||
|
bodyBorderWidth: "0px", // px
|
||||||
|
bodyBorderColor: "#fff", // hex or name
|
||||||
|
bodyBorderRadius: "5px", // px
|
||||||
|
|
||||||
|
// task
|
||||||
|
lineHeight: 1.5, // number
|
||||||
|
usernameFontWeight: "bold", // normal or bold or number
|
||||||
|
usernameColor: "pink", // hex or name or "" for twitch user color
|
||||||
|
usernameFontSize: "20px", // px
|
||||||
|
|
||||||
|
taskWidth: "100%",
|
||||||
|
|
||||||
|
taskBackgroundColor: "#000", // hex only
|
||||||
|
taskBackgroundOpacity: 0, // 0.0 - 1.0
|
||||||
|
|
||||||
|
taskFontFamily: "Poppins", // font name
|
||||||
|
|
||||||
|
taskFontSize: "20px", // px
|
||||||
|
taskFontColor: "#fff", // hex or name
|
||||||
|
|
||||||
|
taskBorderColor: "#fff", // hex or name
|
||||||
|
taskBorderWidth: "0px", // px
|
||||||
|
taskBorderRadius: "10px", // px
|
||||||
|
|
||||||
|
taskMarginBottom: "10px", // px
|
||||||
|
taskHorizontalPadding: "20px", // px
|
||||||
|
taskVerticalPadding: "10px", // px
|
||||||
|
|
||||||
|
// done task
|
||||||
|
doneTaskFontColor: "#bbb", // hex or name
|
||||||
|
|
||||||
|
// focus task
|
||||||
|
focusTaskBackgroundColor: "#fff", // hex only
|
||||||
|
focusTaskBackgroundOpacity: 1, // 0.0 - 1.0
|
||||||
|
focusTaskBorderRadius: "5px", // px
|
||||||
|
|
||||||
|
focusTaskFontColor: "#000", // hex or name
|
||||||
|
|
||||||
|
focusTaskHorizontalPadding: "7px", // px
|
||||||
|
focusTaskVerticalPadding: "0px", // px
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
settings,
|
||||||
|
styles,
|
||||||
|
animation,
|
||||||
|
};
|
||||||
|
})();
|
||||||
225
scripts/index.js
225
scripts/index.js
|
|
@ -1,225 +0,0 @@
|
||||||
const commands = configs.commands;
|
|
||||||
const responses = configs.responses;
|
|
||||||
|
|
||||||
let params = {};
|
|
||||||
|
|
||||||
function respond(template, params) {
|
|
||||||
ComfyJS.Say(
|
|
||||||
template
|
|
||||||
.replace("{user}", `@${params.user}`)
|
|
||||||
.replace("{message}", params.message)
|
|
||||||
.replace("{mentioned}", `@${params.mentioned}`)
|
|
||||||
.replace("{task}", params.task)
|
|
||||||
.replace("{originalTask}", params.originalTask)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isMod(flags) {
|
|
||||||
return flags.broadcaster || flags.mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
ComfyJS.onCommand = (user, command, message, flags, extra) => {
|
|
||||||
command = `!${command.toLowerCase()}`;
|
|
||||||
|
|
||||||
params = {
|
|
||||||
user: user,
|
|
||||||
message: message,
|
|
||||||
mentioned: "",
|
|
||||||
task: "",
|
|
||||||
originalTask: "",
|
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let finishStatus = markTaskDone(user, message);
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
params.task = finishStatus.markedTasks;
|
|
||||||
|
|
||||||
if (finishStatus.failedTasks !== "") {
|
|
||||||
finishedResponse += ` | Failed to finish task(s): "${finishStatus.failedTasks}"`;
|
|
||||||
}
|
|
||||||
|
|
||||||
respond(finishedResponse, params);
|
|
||||||
}
|
|
||||||
} else if (commands.unfinishTaskCommands.includes(command)) {
|
|
||||||
let unfinishStatus = 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);
|
|
||||||
}
|
|
||||||
} else if (commands.checkCommands.includes(command)) {
|
|
||||||
if (message === "") {
|
|
||||||
let response = checkTasks(user);
|
|
||||||
if (response === 0) {
|
|
||||||
return respond(responses.noTask, params);
|
|
||||||
}
|
|
||||||
return ComfyJS.Say(response);
|
|
||||||
} else {
|
|
||||||
let mentioned = message.replace("@", "");
|
|
||||||
let response = checkTasks(mentioned);
|
|
||||||
if (response === 0) {
|
|
||||||
// no tasks
|
|
||||||
return respond(responses.noTaskA, params);
|
|
||||||
}
|
|
||||||
return ComfyJS.Say(response);
|
|
||||||
}
|
|
||||||
} else if (commands.adminDeleteCommands.includes(command)) {
|
|
||||||
if (!isMod(flags)) {
|
|
||||||
respond(responses.notMod, params);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mentioned = message.replace("@", "");
|
|
||||||
|
|
||||||
if (mentioned === "") {
|
|
||||||
respond(responses.specifyUser, params);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
// no tasks
|
|
||||||
respond(responses.noTask, params);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ComfyJS.Say(response);
|
|
||||||
} else if (commands.additionalCommands[command]) {
|
|
||||||
respond(commands.additionalCommands[command], params);
|
|
||||||
} else {
|
|
||||||
// command not found
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ComfyJS.Init(auth.username, `oauth:${auth.oauth}`, [auth.channel]);
|
|
||||||
|
|
@ -2,13 +2,119 @@
|
||||||
DB structure:
|
DB structure:
|
||||||
|
|
||||||
- tasks
|
- tasks
|
||||||
- username:
|
- [username]:
|
||||||
- todos (array)
|
- todos (array)
|
||||||
- [{text, done}, {text, done}]
|
- [{text, done, focus}, {text, done, focus}]
|
||||||
- done
|
|
||||||
- userColor
|
- userColor
|
||||||
|
- counts
|
||||||
|
- users
|
||||||
|
- [username]:
|
||||||
|
- completeCount
|
||||||
|
- points
|
||||||
|
- totalCompleteCount
|
||||||
|
|
||||||
|
- taskmaster
|
||||||
|
- users
|
||||||
|
- [username]:
|
||||||
|
- taskMasterCompleteCount
|
||||||
|
- startDate
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
var taskListMemory = {
|
||||||
|
doneTaskCount: 0,
|
||||||
|
totalTaskCount: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
function getSetting(setting) {
|
||||||
|
return configs.settings[setting] ?? defaultConfigs.settings[setting];
|
||||||
|
}
|
||||||
|
|
||||||
|
const DBHandler = {
|
||||||
|
db: null,
|
||||||
|
open: function () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let request = indexedDB.open("tasksDB", 1);
|
||||||
|
|
||||||
|
request.onupgradeneeded = function (e) {
|
||||||
|
let db = e.target.result;
|
||||||
|
if (!db.objectStoreNames.contains("tasks")) {
|
||||||
|
db.createObjectStore("tasks", { autoIncrement: true });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onsuccess = function (e) {
|
||||||
|
DBHandler.db = e.target.result;
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onerror = function (e) {
|
||||||
|
console.log("Error opening db", e);
|
||||||
|
reject(e);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
get: function (key) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let transaction = DBHandler.db.transaction(["tasks"], "readonly");
|
||||||
|
let store = transaction.objectStore("tasks");
|
||||||
|
let request = store.get(key);
|
||||||
|
|
||||||
|
request.onsuccess = function (e) {
|
||||||
|
resolve(e.target.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onerror = function (e) {
|
||||||
|
reject("Error getting item", e);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
set: function (key, value) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let transaction = DBHandler.db.transaction(["tasks"], "readwrite");
|
||||||
|
let store = transaction.objectStore("tasks");
|
||||||
|
let request = store.put(value, key);
|
||||||
|
|
||||||
|
request.onsuccess = function (e) {
|
||||||
|
resolve(e.target.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onerror = function (e) {
|
||||||
|
reject("Error setting item", e);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
remove: function (key) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let transaction = DBHandler.db.transaction(["tasks"], "readwrite");
|
||||||
|
let store = transaction.objectStore("tasks");
|
||||||
|
let request = store.delete(key);
|
||||||
|
|
||||||
|
request.onsuccess = function (e) {
|
||||||
|
resolve(e.target.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onerror = function (e) {
|
||||||
|
reject("Error removing item", e);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
clear: function () {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
let transaction = DBHandler.db.transaction(["tasks"], "readwrite");
|
||||||
|
let store = transaction.objectStore("tasks");
|
||||||
|
let request = store.clear();
|
||||||
|
|
||||||
|
request.onsuccess = function (e) {
|
||||||
|
resolve(e.target.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
request.onerror = function (e) {
|
||||||
|
reject("Error clearing store", e);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const settings = configs.settings;
|
const settings = configs.settings;
|
||||||
const styles = configs.styles;
|
const styles = configs.styles;
|
||||||
const scrollSpeed = configs.animation.scrollSpeed;
|
const scrollSpeed = configs.animation.scrollSpeed;
|
||||||
|
|
@ -136,739 +242,122 @@ function importStyles() {
|
||||||
}, 8000);
|
}, 8000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetDB() {
|
async function renderTaskListToDOM() {
|
||||||
localStorage.clear();
|
const tasks = await DBHandler.get("tasks");
|
||||||
setupDB();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setupDB() {
|
|
||||||
if (!localStorage.tasks) {
|
|
||||||
localStorage.setItem(`tasks`, "{}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0: limit has reached
|
|
||||||
// 1: duplicate task
|
|
||||||
// 2: invalid input
|
|
||||||
// string (single or multiple tasks): success
|
|
||||||
function addTask(username, userColor, task) {
|
|
||||||
const tasks = JSON.parse(localStorage.tasks);
|
|
||||||
if (!tasks[username]) {
|
|
||||||
tasks[username] = {
|
|
||||||
todos: [],
|
|
||||||
done: [],
|
|
||||||
userColor: userColor,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
incompleteTasksCount(username) >= settings.limit &&
|
|
||||||
settings.enableLimit
|
|
||||||
) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
tasks[username].todos.find(
|
|
||||||
(t) => t.text.toLowerCase() === task.toLowerCase()
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if task is whitespace or empty
|
|
||||||
if (!task || !task.trim()) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
let tasksFailedToAdd = [];
|
|
||||||
|
|
||||||
// if task has commas
|
|
||||||
if (task.includes(",")) {
|
|
||||||
let tasksToAdd = task.split(",").map((t) => t.trim());
|
|
||||||
|
|
||||||
if (
|
|
||||||
incompleteTasksCount(username) + tasksToAdd.length >
|
|
||||||
settings.limit &&
|
|
||||||
settings.enableLimit
|
|
||||||
) {
|
|
||||||
tasksFailedToAdd = tasksToAdd.slice(
|
|
||||||
settings.limit - incompleteTasksCount(username),
|
|
||||||
tasksToAdd.length
|
|
||||||
);
|
|
||||||
|
|
||||||
tasksToAdd = tasksToAdd.slice(
|
|
||||||
0,
|
|
||||||
settings.limit - incompleteTasksCount(username)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const t of tasksToAdd) {
|
|
||||||
tasks[username].todos.push({ text: t, done: false });
|
|
||||||
}
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
if (!scrolling) {
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
task: tasksToAdd.join('", "'),
|
|
||||||
tasksFailedToAdd: tasksFailedToAdd.join('", "') || "",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks[username].todos.push({ text: task, done: false });
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
if (!scrolling) {
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
task: task,
|
|
||||||
tasksFailedToAdd: "",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0: user has no tasks
|
|
||||||
// 1: invalid input
|
|
||||||
// removed task: success
|
|
||||||
function removeTask(username, task) {
|
|
||||||
const tasks = JSON.parse(localStorage.tasks);
|
|
||||||
if (!tasks[username] || tasks[username].todos.length === 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const incompleteTasks = tasks[username].todos.filter((t) => !t.done);
|
|
||||||
|
|
||||||
// match regex: integers separated by space e.g. '1 2 3 4'
|
|
||||||
if (task.match(/^(\d+ )*\d+$/)) {
|
|
||||||
// insert commas between integers
|
|
||||||
task = task.replace(/(\d+)/g, "$1,");
|
|
||||||
// remove trailing comma
|
|
||||||
task = task.slice(0, -1);
|
|
||||||
}
|
|
||||||
let removedTaskIndex = [];
|
|
||||||
let tasksRemoved = [];
|
|
||||||
let tasksFailedToRemove = [];
|
|
||||||
|
|
||||||
// check if there's a comma in the task (multiple tasks)
|
|
||||||
if (task.includes(",")) {
|
|
||||||
let tasksToRemove = task.split(",").map((t) => t.trim());
|
|
||||||
for (const t of tasksToRemove) {
|
|
||||||
let index = tasks[username].todos.findIndex(
|
|
||||||
(task) => task.text.toLowerCase() === t.toLowerCase()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (index === -1) {
|
|
||||||
if (isInt(t)) {
|
|
||||||
index = parseInt(t) - 1; // ACTUAL INDEX
|
|
||||||
} else if (incompleteTasks.length === 1) {
|
|
||||||
index = tasks[username].todos.findIndex((t) => !t.done);
|
|
||||||
tasksRemoved.push(tasks[username].todos[index].text);
|
|
||||||
removedTaskIndex.push(index);
|
|
||||||
} else {
|
|
||||||
tasksFailedToRemove.push(t);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < 0 || index > tasks[username].todos.length - 1) {
|
|
||||||
tasksFailedToRemove.push(t);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
tasksRemoved.push(tasks[username].todos[index].text);
|
|
||||||
removedTaskIndex.push(index);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tasksRemoved.push(tasks[username].todos[index].text);
|
|
||||||
removedTaskIndex.push(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tasksRemoved.length === 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort removedTaskIndex in descending order
|
|
||||||
removedTaskIndex.sort((a, b) => b - a);
|
|
||||||
|
|
||||||
// remove tasks from tasks array
|
|
||||||
for (const index of removedTaskIndex) {
|
|
||||||
tasks[username].todos.splice(index, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
if (!scrolling) {
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
removedTasks: tasksRemoved.join('", "'),
|
|
||||||
failedTasks: tasksFailedToRemove.join('", "'),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
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 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < 0 || index > tasks[username].todos.length - 1) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task = tasks[username].todos[index].text;
|
|
||||||
|
|
||||||
tasks[username].todos.splice(index, 1);
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
renderTaskListToDOM();
|
|
||||||
return {
|
|
||||||
removedTasks: task,
|
|
||||||
failedTasks: "",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// function to determine if string is integer
|
|
||||||
function isInt(value) {
|
|
||||||
return (
|
|
||||||
!isNaN(value) &&
|
|
||||||
parseInt(Number(value)) == value &&
|
|
||||||
!isNaN(parseInt(value, 10))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0: user has no tasks
|
|
||||||
// 1: success
|
|
||||||
function clearOwnDoneTasks(username) {
|
|
||||||
const tasks = JSON.parse(localStorage.tasks);
|
|
||||||
|
|
||||||
if (!tasks[username] || tasks[username].todos.length === 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let incompleteUserTasks = tasks[username].todos.filter((t) => !t.done);
|
|
||||||
|
|
||||||
// replace user's task with incomplete tasks
|
|
||||||
tasks[username].todos = incompleteUserTasks;
|
|
||||||
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
if (!scrolling) {
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0: user has no tasks
|
|
||||||
// 1: invalid input
|
|
||||||
// task: 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
const incompleteTasks = tasks[username].todos.filter((t) => !t.done);
|
|
||||||
|
|
||||||
// match regex: integers separated by space e.g. '1 2 3 4'
|
|
||||||
if (task.match(/^(\d+ )*\d+$/)) {
|
|
||||||
// insert commas between integers
|
|
||||||
task = task.replace(/(\d+)/g, "$1,");
|
|
||||||
// remove trailing comma
|
|
||||||
task = task.slice(0, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let tasksMarkedComplete = [];
|
|
||||||
let tasksFailedToComplete = [];
|
|
||||||
|
|
||||||
// check if there's a comma in the task (multiple tasks)
|
|
||||||
if (task.includes(",")) {
|
|
||||||
let tasksToMarkDone = task.split(",").map((t) => t.trim());
|
|
||||||
for (const t of tasksToMarkDone) {
|
|
||||||
let index = tasks[username].todos.findIndex(
|
|
||||||
(task) => task.text.toLowerCase() === t.toLowerCase()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (index === -1) {
|
|
||||||
if (isInt(t)) {
|
|
||||||
index = parseInt(t) - 1; // ACTUAL INDEX
|
|
||||||
} else if (incompleteTasks.length === 1) {
|
|
||||||
index = tasks[username].todos.findIndex((t) => !t.done);
|
|
||||||
tasksMarkedComplete.push(tasks[username].todos[index].text);
|
|
||||||
} else {
|
|
||||||
tasksFailedToComplete.push(t);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < 0 || index > tasks[username].todos.length - 1) {
|
|
||||||
tasksFailedToComplete.push(t);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
tasksMarkedComplete.push(tasks[username].todos[index].text);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tasksMarkedComplete.push(tasks[username].todos[index].text);
|
|
||||||
}
|
|
||||||
tasks[username].todos[index].done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tasksMarkedComplete.length === 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
if (!scrolling) {
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
markedTasks: tasksMarkedComplete.join('", "'),
|
|
||||||
failedTasks: tasksFailedToComplete.join('", "'),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
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 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < 0 || index > tasks[username].todos.length - 1) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task = tasks[username].todos[index].text;
|
|
||||||
tasks[username].todos[index].done = true;
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
if (!scrolling) {
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
markedTasks: task,
|
|
||||||
failedTasks: "",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const task of tasks[username].todos) {
|
|
||||||
task.done = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
if (!scrolling) {
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
const completedTasks = tasks[username].todos.filter((t) => t.done);
|
|
||||||
|
|
||||||
// match regex: integers separated by space e.g. '1 2 3 4'
|
|
||||||
if (task.match(/^(\d+ )*\d+$/)) {
|
|
||||||
// insert commas between integers
|
|
||||||
task = task.replace(/(\d+)/g, "$1,");
|
|
||||||
// remove trailing comma
|
|
||||||
task = task.slice(0, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
let tasksMarkedUndone = [];
|
|
||||||
let tasksFailedToMarkUndone = [];
|
|
||||||
|
|
||||||
// check if there's a comma in the task (multiple tasks)
|
|
||||||
if (task.includes(",")) {
|
|
||||||
let tasksToMarkUndone = task.split(",").map((t) => t.trim());
|
|
||||||
for (const t of tasksToMarkUndone) {
|
|
||||||
let index = tasks[username].todos.findIndex(
|
|
||||||
(task) => task.text.toLowerCase() === t.toLowerCase()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (index === -1) {
|
|
||||||
// user input isn't the task name
|
|
||||||
if (isInt(t)) {
|
|
||||||
index = parseInt(t) - 1; // ACTUAL INDEX
|
|
||||||
} else {
|
|
||||||
tasksFailedToMarkUndone.push(t);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < 0 || index > tasks[username].todos.length - 1) {
|
|
||||||
tasksFailedToMarkUndone.push(t);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
tasksMarkedUndone.push(tasks[username].todos[index].text);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tasksMarkedUndone.push(tasks[username].todos[index].text);
|
|
||||||
}
|
|
||||||
tasks[username].todos[index].done = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tasksMarkedUndone.length === 0) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
if (!scrolling) {
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
markedTasks: tasksMarkedUndone.join('", "'),
|
|
||||||
failedTasks: tasksFailedToMarkUndone.join('", "'),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
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 (completedTasks.length === 1) {
|
|
||||||
index = tasks[username].todos.findIndex((t) => t.done);
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < 0 || index > tasks[username].todos.length - 1) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks[username].todos[index].done = false;
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
if (!scrolling) {
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
markedTasks: tasks[username].todos[index].text,
|
|
||||||
failedTasks: "",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0: user has no tasks
|
|
||||||
// 1: invalid input
|
|
||||||
// [original task, new task]: succcess
|
|
||||||
function editTask(username, message) {
|
|
||||||
const tasks = JSON.parse(localStorage.tasks);
|
|
||||||
let noSpecifiedIndex = false;
|
|
||||||
|
|
||||||
if (!tasks[username] || tasks[username].todos.length === 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// example 'message': 1 new task
|
|
||||||
let index = parseInt(message.split(" ")[0]) - 1; // ACTUAL INDEX
|
|
||||||
|
|
||||||
let incompleteTaskCount = tasks[username].todos.filter(
|
|
||||||
(t) => !t.done
|
|
||||||
).length;
|
|
||||||
|
|
||||||
if (incompleteTaskCount === 1 && index !== 0) {
|
|
||||||
// find index of incomplete task
|
|
||||||
index = tasks[username].todos.findIndex((t) => !t.done);
|
|
||||||
noSpecifiedIndex = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNaN(index)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let newTask = message.split(" ").slice(1).join(" ");
|
|
||||||
|
|
||||||
if (noSpecifiedIndex) {
|
|
||||||
newTask = message;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if newTask is empty or whitespace, return 1
|
|
||||||
if (!newTask || !newTask.trim()) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index < 0 || index > tasks[username].todos.length - 1) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let originalTask = tasks[username].todos[index].text;
|
|
||||||
|
|
||||||
tasks[username].todos[index].text = newTask;
|
|
||||||
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
if (!scrolling) {
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
|
|
||||||
return [originalTask, newTask];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0: user has no tasks
|
|
||||||
function checkTasks(username) {
|
|
||||||
const tasks = JSON.parse(localStorage.tasks);
|
|
||||||
|
|
||||||
// Go through keys of tasks, find match of lowercased username
|
|
||||||
username = Object.keys(tasks).find(
|
|
||||||
(user) => user.toLowerCase() === username.toLowerCase()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tasks[username]) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// filter completed tasks
|
|
||||||
const incompleteTasks = tasks[username].todos.filter((t) => !t.done);
|
|
||||||
const completedTasks = tasks[username].todos.filter((t) => t.done);
|
|
||||||
|
|
||||||
// format incomplete tasks into string: 1. task 1 | 2. task 2 | 3. task 3...
|
|
||||||
let reply = `@${username} incomplete tasks (${incompleteTasks.length}) : `;
|
|
||||||
let taskIndex;
|
|
||||||
for (let i = 0; i < incompleteTasks.length; i++) {
|
|
||||||
// get index of task by task name
|
|
||||||
taskIndex =
|
|
||||||
tasks[username].todos.findIndex(
|
|
||||||
(t) =>
|
|
||||||
t.text.toLowerCase() ===
|
|
||||||
incompleteTasks[i].text.toLowerCase()
|
|
||||||
) + 1;
|
|
||||||
reply += `${taskIndex}. ${incompleteTasks[i].text} | `;
|
|
||||||
}
|
|
||||||
reply = reply.slice(0, -3);
|
|
||||||
|
|
||||||
// format completed tasks into string: 1. task 1 | 2. task 2 | 3. task 3...
|
|
||||||
// reply += `\n|| completed tasks (${completedTasks.length}) : `;
|
|
||||||
|
|
||||||
// for (let j = 0; j < completedTasks.length; j++) {
|
|
||||||
// taskIndex =
|
|
||||||
// tasks[username].todos.findIndex(
|
|
||||||
// (t) =>
|
|
||||||
// t.text.toLowerCase() ===
|
|
||||||
// completedTasks[j].text.toLowerCase()
|
|
||||||
// ) + 1;
|
|
||||||
// reply += `${taskIndex}. ${completedTasks[j].text} | `;
|
|
||||||
// }
|
|
||||||
// reply = reply.slice(0, -3);
|
|
||||||
|
|
||||||
return reply;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0: user has no tasks
|
|
||||||
function listTasks(username) {
|
|
||||||
const tasks = JSON.parse(localStorage.tasks);
|
|
||||||
if (!tasks[username]) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// filter completed tasks
|
|
||||||
const incompleteTasks = tasks[username].todos.filter((t) => !t.done);
|
|
||||||
|
|
||||||
if (incompleteTasks.length === 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// format incomplete tasks into string: 1. task 1 | 2. task 2 | 3. task 3...
|
|
||||||
let reply = `@${username} `;
|
|
||||||
let taskIndex;
|
|
||||||
for (let i = 0; i < incompleteTasks.length; i++) {
|
|
||||||
// get index of task by task name
|
|
||||||
taskIndex =
|
|
||||||
tasks[username].todos.findIndex(
|
|
||||||
(t) =>
|
|
||||||
t.text.toLowerCase() ===
|
|
||||||
incompleteTasks[i].text.toLowerCase()
|
|
||||||
) + 1;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0: user has no tasks
|
|
||||||
function clearUserTasks(username) {
|
|
||||||
const tasks = JSON.parse(localStorage.tasks);
|
|
||||||
// find username where lowercase matches username
|
|
||||||
username = Object.keys(tasks).find(
|
|
||||||
(user) => user.toLowerCase() === username.toLowerCase()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!username) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks[username].todos = [];
|
|
||||||
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearAllDoneTasks() {
|
|
||||||
const tasks = JSON.parse(localStorage.tasks);
|
|
||||||
for (const user in tasks) {
|
|
||||||
tasks[user].todos = tasks[user].todos.filter((t) => !t.done);
|
|
||||||
}
|
|
||||||
cancelAnimation();
|
|
||||||
checkToAnimate();
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearAllTasks() {
|
|
||||||
resetDB();
|
|
||||||
cancelAnimation();
|
|
||||||
checkToAnimate();
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearAllExceptStreamer(streamer) {
|
|
||||||
// clear all tasks except for broadcasters
|
|
||||||
const tasks = JSON.parse(localStorage.tasks);
|
|
||||||
for (const user in tasks) {
|
|
||||||
if (user.toLowerCase() !== streamer.toLowerCase()) {
|
|
||||||
tasks[user].todos = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem(`tasks`, JSON.stringify(tasks));
|
|
||||||
|
|
||||||
clearAllDoneTasks();
|
|
||||||
|
|
||||||
cancelAnimation();
|
|
||||||
checkToAnimate();
|
|
||||||
|
|
||||||
renderTaskListToDOM();
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderTaskListToDOM() {
|
|
||||||
const tasks = JSON.parse(localStorage.tasks);
|
|
||||||
|
|
||||||
const taskContainers = document.querySelectorAll(".task-container");
|
const taskContainers = document.querySelectorAll(".task-container");
|
||||||
|
|
||||||
taskContainers.forEach((taskList) => {
|
taskContainers.forEach((taskList) => {
|
||||||
taskList.innerHTML = "";
|
taskList.innerHTML = "";
|
||||||
|
|
||||||
let totalTaskCount = 0;
|
let totalTaskCount = 0;
|
||||||
let completedTasksCount = 0;
|
let completedTasksCount = 0;
|
||||||
|
|
||||||
|
if (getSetting("showStreamersTasksOnly")) {
|
||||||
|
const streamer = getSetting("streamer");
|
||||||
|
if (tasks[streamer]) {
|
||||||
|
({ totalTaskCount, completedTasksCount } = handleTasks(
|
||||||
|
tasks,
|
||||||
|
streamer,
|
||||||
|
taskList,
|
||||||
|
totalTaskCount,
|
||||||
|
completedTasksCount
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
for (const user in tasks) {
|
for (const user in tasks) {
|
||||||
const userTasks = tasks[user];
|
if (user.toLowerCase() === "id" || !tasks[user].todos) continue;
|
||||||
if (userTasks.todos.length === 0) {
|
({ totalTaskCount, completedTasksCount } = handleTasks(
|
||||||
continue;
|
tasks,
|
||||||
|
user,
|
||||||
|
taskList,
|
||||||
|
totalTaskCount,
|
||||||
|
completedTasksCount
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const userColor = userTasks.userColor;
|
updateTaskCount(totalTaskCount, completedTasksCount);
|
||||||
|
});
|
||||||
|
|
||||||
|
await DBHandler.set("tasks", tasks);
|
||||||
|
await checkToAnimate();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTasks(
|
||||||
|
tasks,
|
||||||
|
user,
|
||||||
|
taskList,
|
||||||
|
totalTaskCount,
|
||||||
|
completedTasksCount
|
||||||
|
) {
|
||||||
|
const userTasks = tasks[user];
|
||||||
|
if (userTasks.todos.length === 0) {
|
||||||
|
delete tasks[user];
|
||||||
|
} else {
|
||||||
|
const taskDiv = createTaskDiv(userTasks, user);
|
||||||
|
taskList.appendChild(taskDiv);
|
||||||
|
|
||||||
|
for (const task of userTasks.todos) {
|
||||||
|
const taskElement = createTaskElement(task);
|
||||||
|
taskDiv.querySelector(".user-tasks").appendChild(taskElement);
|
||||||
|
|
||||||
|
totalTaskCount++;
|
||||||
|
if (task.done) completedTasksCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { totalTaskCount, completedTasksCount };
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTaskDiv(userTasks, username) {
|
||||||
const taskDiv = document.createElement("div");
|
const taskDiv = document.createElement("div");
|
||||||
taskDiv.classList.add("task");
|
taskDiv.classList.add("task");
|
||||||
taskList.appendChild(taskDiv);
|
|
||||||
|
|
||||||
const usernameDiv = document.createElement("div");
|
const usernameDiv = document.createElement("div");
|
||||||
usernameDiv.classList.add("username");
|
usernameDiv.classList.add("username");
|
||||||
usernameDiv.innerText = user;
|
usernameDiv.innerText = username;
|
||||||
|
usernameDiv.style.color = styles.usernameColor || userTasks.userColor;
|
||||||
if (styles.usernameColor === "") {
|
|
||||||
usernameDiv.style.color = userColor;
|
|
||||||
} else {
|
|
||||||
usernameDiv.style.color = styles.usernameColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
taskDiv.appendChild(usernameDiv);
|
taskDiv.appendChild(usernameDiv);
|
||||||
|
|
||||||
const olListDiv = document.createElement("ol");
|
const olListDiv = document.createElement("ol");
|
||||||
olListDiv.classList.add("user-tasks");
|
olListDiv.classList.add("user-tasks");
|
||||||
taskDiv.appendChild(olListDiv);
|
taskDiv.appendChild(olListDiv);
|
||||||
|
|
||||||
for (const task of userTasks.todos) {
|
return taskDiv;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createTaskElement(task) {
|
||||||
const taskElement = document.createElement("li");
|
const taskElement = document.createElement("li");
|
||||||
taskElement.classList.add("todo");
|
taskElement.classList.add("todo");
|
||||||
|
|
||||||
totalTaskCount++;
|
|
||||||
|
|
||||||
if (task.done) {
|
|
||||||
taskElement.classList.add("done");
|
|
||||||
completedTasksCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
taskElement.innerText = task.text;
|
taskElement.innerText = task.text;
|
||||||
olListDiv.appendChild(taskElement);
|
|
||||||
|
if (task.done) taskElement.classList.add("done");
|
||||||
|
else if (task.focus) taskElement.classList.add("focus");
|
||||||
|
|
||||||
|
return taskElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTaskCount(totalTaskCount, completedTasksCount) {
|
||||||
|
if (taskListMemory.doneTaskCount > completedTasksCount) {
|
||||||
|
completedTasksCount = taskListMemory.doneTaskCount;
|
||||||
|
totalTaskCount = taskListMemory.totalTaskCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (totalTaskCount < completedTasksCount) {
|
||||||
|
totalTaskCount = completedTasksCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.querySelector(
|
document.querySelector(
|
||||||
".task-count"
|
".task-count"
|
||||||
).innerText = `${completedTasksCount}/${totalTaskCount}`;
|
).innerText = `${completedTasksCount}/${totalTaskCount}`;
|
||||||
});
|
|
||||||
checkToAnimate();
|
taskListMemory.doneTaskCount = completedTasksCount;
|
||||||
|
taskListMemory.totalTaskCount = totalTaskCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
function sleep(ms) {
|
function sleep(ms) {
|
||||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
// unit tests
|
|
||||||
async function tests1() {
|
|
||||||
let listOfStreamers = [
|
|
||||||
`cloudydayzzz`,
|
|
||||||
`berryspace`,
|
|
||||||
`MohFocus`,
|
|
||||||
`xeno_hiraeth`,
|
|
||||||
`euphie___`,
|
|
||||||
`unknownnie`,
|
|
||||||
`theyolotato`,
|
|
||||||
// `charliosaurus`,
|
|
||||||
// `jutstreams`,
|
|
||||||
// `mikewhatwhere`,
|
|
||||||
// `studypaws`,
|
|
||||||
// `pcc_lanezzz`,
|
|
||||||
// `workwithjandj`,
|
|
||||||
// `studylena`,
|
|
||||||
];
|
|
||||||
|
|
||||||
for (let i = 0; i < listOfStreamers.length; i++) {
|
|
||||||
addTask(
|
|
||||||
listOfStreamers[i],
|
|
||||||
"#ffc0cb",
|
|
||||||
`task 1, task 2, task 3, task 4, task 5`
|
|
||||||
);
|
|
||||||
await sleep(1000);
|
|
||||||
markTaskDone(listOfStreamers[i], `1, 2, 3, 4, 5`);
|
|
||||||
await sleep(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function checkToAnimate() {
|
async function checkToAnimate() {
|
||||||
// compare task container height and task wrapper height
|
// compare task container height and task wrapper height
|
||||||
|
|
||||||
|
|
@ -940,10 +429,10 @@ function addAnimationListeners() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function animationFinished() {
|
async function animationFinished() {
|
||||||
scrolling = false;
|
scrolling = false;
|
||||||
renderTaskListToDOM();
|
await renderTaskListToDOM();
|
||||||
checkToAnimate();
|
await checkToAnimate();
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancelAnimation() {
|
function cancelAnimation() {
|
||||||
|
|
@ -954,11 +443,17 @@ function cancelAnimation() {
|
||||||
secondaryAnimation.cancel();
|
secondaryAnimation.cancel();
|
||||||
}
|
}
|
||||||
scrolling = false;
|
scrolling = false;
|
||||||
console.log("animation cancelled");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(function () {
|
DBHandler.open()
|
||||||
setupDB();
|
.then(async () => {
|
||||||
importStyles();
|
importStyles();
|
||||||
renderTaskListToDOM();
|
await renderTaskListToDOM();
|
||||||
})();
|
|
||||||
|
setInterval(async () => {
|
||||||
|
await renderTaskListToDOM();
|
||||||
|
}, 5000);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error("Error opening database:", error);
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,6 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
|
||||||
background-color: gray;
|
|
||||||
}
|
|
||||||
|
|
||||||
#main-container {
|
#main-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
|
@ -109,6 +105,7 @@ body {
|
||||||
}
|
}
|
||||||
#main-container .task-wrapper .task-container .task .username {
|
#main-container .task-wrapper .task-container .task .username {
|
||||||
font-weight: var(--username-font-weight);
|
font-weight: var(--username-font-weight);
|
||||||
|
font-size: var(--username-font-size);
|
||||||
}
|
}
|
||||||
#main-container .task-wrapper .task-container .task .user-tasks {
|
#main-container .task-wrapper .task-container .task .user-tasks {
|
||||||
list-style-position: inside;
|
list-style-position: inside;
|
||||||
|
|
@ -120,4 +117,13 @@ body {
|
||||||
}
|
}
|
||||||
#main-container .task-wrapper .task-container .task .user-tasks .done {
|
#main-container .task-wrapper .task-container .task .user-tasks .done {
|
||||||
text-decoration: line-through;
|
text-decoration: line-through;
|
||||||
|
color: var(--done-task-font-color);
|
||||||
|
}
|
||||||
|
#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 */
|
}/*# sourceMappingURL=taskList.css.map */
|
||||||
Loading…
Reference in a new issue