diff --git a/CHANGELOG-nightly.md b/CHANGELOG-nightly.md
index 65e04d92..6463416d 100644
--- a/CHANGELOG-nightly.md
+++ b/CHANGELOG-nightly.md
@@ -1,6 +1,9 @@
### 3.1.16.2000
- Updated Firefox extension URL in onboarding
+- Added custom moderation action reasons
+- Added an option to select the default timeout duration
+- Added an option to hide the pin confirmation prompt
- Added tier and tenure to Twitch subscriber badge tooltips
### 3.1.16.1000
diff --git a/src/app/chat/UserMessageButtons.vue b/src/app/chat/UserMessageButtons.vue
index dc5c07ad..238e43ff 100644
--- a/src/app/chat/UserMessageButtons.vue
+++ b/src/app/chat/UserMessageButtons.vue
@@ -14,11 +14,11 @@
ref="pinButtonRef"
v-tooltip="'Pin'"
class="seventv-button"
- @click="pinPrompt = true"
+ @click="onPinPrompt"
>
-
@@ -95,7 +95,9 @@ const tray = useTray("Reply", () => ({
: {}),
}));
+const showPinPrompt = useConfig("chat.pin_prompt_toggle");
const showCopyIcon = useConfig("chat.copy_icon_toggle");
+
const copyToastOpen = ref(false);
const copyButtonRef = ref();
const copyToastContainer = useFloatScreen(copyButtonRef, {
@@ -125,6 +127,14 @@ function openReplyTray(): void {
tray.open();
}
+function onPinPrompt(): void {
+ if (showPinPrompt.value) {
+ pinPrompt.value = true;
+ } else {
+ emit("pin");
+ }
+}
+
function onPinAnswer(answer: string): void {
if (answer !== "yes") return;
diff --git a/src/app/settings/SettingsConfigActionReasons.vue b/src/app/settings/SettingsConfigActionReasons.vue
new file mode 100644
index 00000000..4d65666d
--- /dev/null
+++ b/src/app/settings/SettingsConfigActionReasons.vue
@@ -0,0 +1,186 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ reason }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/common/Constant.ts b/src/common/Constant.ts
index be82e12e..c039fd2d 100644
--- a/src/common/Constant.ts
+++ b/src/common/Constant.ts
@@ -21,6 +21,7 @@ export const UNICODE_TAG_0 = "\u{34f}";
export const UNICODE_TAG_0_REGEX = new RegExp(UNICODE_TAG_0, "g");
export const TWITCH_PROFILE_IMAGE_REGEX = /(\d+x\d+)(?=\.\w{3,4}$)/;
+export const TWITCH_TIMEOUT_REGEX = new RegExp("^[0-9]+[dhms]$", "i");
export const HOSTNAME_SUPPORTED_REGEXP = /([a-z0-9]+[.])*(youtube|kick)[.]com/;
export const SEVENTV_EMOTE_LINK = new RegExp(
diff --git a/src/composable/chat/useChatProperties.ts b/src/composable/chat/useChatProperties.ts
index a0f7f0c6..0b0bc217 100644
--- a/src/composable/chat/useChatProperties.ts
+++ b/src/composable/chat/useChatProperties.ts
@@ -14,6 +14,7 @@ interface ChatProperties {
imageFormat: SevenTV.ImageFormat;
twitchBadgeSets: Twitch.BadgeSets | null;
blockedUsers: Set;
+ chatRules: string[];
}
type ChatPauseReason = "MOUSEOVER" | "SCROLL" | "ALTKEY";
@@ -36,6 +37,7 @@ export function useChatProperties(ctx: ChannelContext) {
twitchBadgeSets: {} as Twitch.BadgeSets | null,
blockedUsers: new Set(),
fontAprilFools: "unset",
+ chatRules: [],
});
m.set(ctx, data);
diff --git a/src/composable/useCosmetics.ts b/src/composable/useCosmetics.ts
index 92027df7..e55473ef 100644
--- a/src/composable/useCosmetics.ts
+++ b/src/composable/useCosmetics.ts
@@ -324,12 +324,12 @@ db.ready().then(async () => {
break;
}
- log.debug("", "Assigned", ents.length.toString(), "stored entitlements");
-
if (assigned) {
data.staticallyAssigned[ent.user_id] = {};
}
}
+
+ log.debug("", "Assigned", ents.length.toString(), "stored entitlements");
})
.then(flush);
});
diff --git a/src/site/global/components/FormInput.vue b/src/site/global/components/FormInput.vue
index 4215c3f0..282e7a74 100644
--- a/src/site/global/components/FormInput.vue
+++ b/src/site/global/components/FormInput.vue
@@ -44,6 +44,7 @@ const inputEl = ref(null);
defineExpose({
focus: () => inputEl.value?.focus(),
+ value: () => inputEl.value?.value,
});
onMounted(() => {
diff --git a/src/site/twitch.tv/modules/chat/ChatController.vue b/src/site/twitch.tv/modules/chat/ChatController.vue
index 90b7c204..fd7cf5b3 100644
--- a/src/site/twitch.tv/modules/chat/ChatController.vue
+++ b/src/site/twitch.tv/modules/chat/ChatController.vue
@@ -241,6 +241,7 @@ definePropertyHook(controller.value.component, "props", {
// Keep track of chat props
properties.isDarkTheme = v.theme;
+ properties.chatRules = v.chatRules ?? [];
// Send presence upon message sent
messages.sendMessage = v.chatConnectionAPI.sendMessage;
diff --git a/src/site/twitch.tv/modules/chat/ChatModule.vue b/src/site/twitch.tv/modules/chat/ChatModule.vue
index 87d9606c..113e7c97 100644
--- a/src/site/twitch.tv/modules/chat/ChatModule.vue
+++ b/src/site/twitch.tv/modules/chat/ChatModule.vue
@@ -128,8 +128,10 @@ defineExpose({
+
+
diff --git a/src/site/twitch.tv/modules/chat/components/mod/ModIcons.vue b/src/site/twitch.tv/modules/chat/components/mod/ModIcons.vue
index f716b4f9..7a6b5c8c 100644
--- a/src/site/twitch.tv/modules/chat/components/mod/ModIcons.vue
+++ b/src/site/twitch.tv/modules/chat/components/mod/ModIcons.vue
@@ -1,9 +1,10 @@
-
+
@@ -13,7 +14,8 @@
@@ -39,19 +41,47 @@
+
+
+
+
+
+
+