[home ]
Can some AIfag create a script to have auto dark mode on this site?
Anonymous
(ID: f5zhNmlf )
27/09/26(Sun)15:01:08
No. 191810
Replies: >>191811
I want it to automatically switch to a light or dark theme of my choice based on my system settings.
For example, if I am using light mode in Windows, it should automatically switch to the light theme of my choice like SimpleChan or Gurochan.
Anonymous
(ID: gN5t+zQ7 )
27/09/26(Sun)15:02:16
No. 191811
Replies: >>191813
>>191810
hi :D
Anonymous
(ID: f5zhNmlf )
27/09/26(Sun)15:03:53
No. 191813
Replies: >>191818
>>191811
Do you have an active AI subscription? If so, please spare a few tokens for this.
Anonymous
(ID: gN5t+zQ7 )
27/09/26(Sun)15:06:39
No. 191818
Replies: >>191820 >>191825
>>191813
:D
>Do you have an active AI subscription?
i don't but you can use opencode's free models
it will be able to give you a js script which you can use with violentmonkey
Anonymous
(ID: gN5t+zQ7 )
27/09/26(Sun)15:07:31
No. 191820
Replies: >>191825
>>191818
pic rel.
Anonymous
(ID: f5zhNmlf )
27/09/26(Sun)15:08:42
No. 191825
Replies: >>191838
>>191818
>>191820
Thanks anon.
Anonymous
(ID: 6FhyVxyi )
27/09/26(Sun)15:11:49
No. 191838
>>191825
my pleasure :D
Anonymous
(ID: f5zhNmlf )
27/09/26(Sun)15:15:53
No. 191848
Replies: >>191849
I made it work:
// ==UserScript==
// @name IndiaChan - Auto Dark/Light Theme
// @namespace https://indiachan.top/ https://indiachan.top/
// @version 1.0.0
// @description Automatically switches IndiaChan between your chosen light/dark themes based on the browser/Windows color-scheme setting.
// @author You
// @match https://indiachan.top/ https://indiachan.top/*
// @match https://www.indiachan.top/ https://www.indiachan.top/*
// @run-at document-start
// @grant none
// ==/UserScript==
(() => {
'use strict';
// =========================
// YOUR PREFERRED THEMES
// =========================
const LIGHT_THEME = 'Simplechan';
const DARK_THEME = 'Simplechan Dark';
const THEME_ALIASES = {
'Simplechan': ['Simplechan'],
'Simplechan Dark': ['Simplechan Dark', 'SimplechanDark'],
'Gurochan': ['Gurochan'],
'Tomorrow': ['Tomorrow'],
'Lainchan': ['Lainchan']
};
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
let lastMode = null;
let applyTimer = null;
const normalize = (value) =>
String(value ?? '')
.trim()
.toLowerCase()
.replace(/\s+/g, ' ');
function aliasesFor(themeName) {
return [themeName, ...(THEME_ALIASES[themeName] || [])]
.filter(Boolean)
.map(normalize);
}
function matchesTheme(value, themeName) {
const actual = normalize(value);
return aliasesFor(themeName).some(alias => {
if (!alias) return false;
return (
actual === alias ||
actual.replace(/[ _-]/g, '') ===
alias.replace(/[ _-]/g, '')
);
});
}
function getWantedTheme() {
return mediaQuery.matches ? DARK_THEME : LIGHT_THEME;
}
function findThemeSelect(themeName) {
const selects = document.querySelectorAll('select');
for (const select of selects) {
const options = [...select.options];
const option = options.find(opt =>
matchesTheme(opt.textContent, themeName) ||
matchesTheme(opt.value, themeName)
);
if (option) {
return { select, option };
}
}
return null;
}
function findThemeRadio(themeName) {
const radios = document.querySelectorAll(
'input[type="radio"]'
);
for (const radio of radios) {
const label = radio.id
? document.querySelector(
`label[for="${CSS.escape(radio.id)}"]`
)
: radio.closest('label');
const text =
label?.textContent ||
radio.value ||
radio.getAttribute('data-theme') ||
'';
if (
matchesTheme(text, themeName) ||
matchesTheme(radio.value, themeName)
) {
return radio;
}
}
return null;
}
function findThemeClickable(themeName) {
const explicit = document.querySelectorAll(
'[data-theme], [data-skin], [data-style], ' +
'[data-theme-name], [data-skin-name]'
);
for (const element of explicit) {
const values = [
element.getAttribute('data-theme'),
element.getAttribute('data-skin'),
element.getAttribute('data-style'),
element.getAttribute('data-theme-name'),
element.getAttribute('data-skin-name'),
element.textContent
];
if (
values.some(value =>
matchesTheme(value, themeName)
)
) {
return element;
}
}
const controls = document.querySelectorAll(
'button, a, [role="button"], label'
);
for (const element of controls) {
const text = normalize(element.textContent);
if (
aliasesFor(themeName).some(
alias => text === alias
)
) {
return element;
}
}
return null;
}
function currentThemeLooksRight(themeName) {
// Select elements
for (const select of document.querySelectorAll('select')) {
const selected =
select.options[select.selectedIndex];
if (!selected) continue;
if (
matchesTheme(selected.textContent, themeName) ||
matchesTheme(selected.value, themeName)
) {
return true;
}
}
// Checked radio buttons
for (
const radio of document.querySelectorAll(
'input[type="radio"]:checked'
)
) {
if (matchesTheme(radio.value, themeName)) {
return true;
}
const label = radio.id
? document.querySelector(
`label[for="${CSS.escape(radio.id)}"]`
)
: radio.closest('label');
if (
label &&
matchesTheme(label.textContent, themeName)
) {
return true;
}
}
// Theme attributes on page
const candidates = [
document.documentElement,
document.body
].filter(Boolean);
for (const element of candidates) {
const attrs = [
element.getAttribute('data-theme'),
element.getAttribute('data-skin'),
element.getAttribute('data-style')
];
if (
attrs.some(value =>
matchesTheme(value, themeName)
)
) {
return true;
}
}
return false;
}
function setSelect(select, option) {
if (select.value === option.value) {
select.dispatchEvent(
new Event('change', { bubbles: true })
);
return true;
}
select.value = option.value;
select.dispatchEvent(
new Event('input', { bubbles: true })
);
select.dispatchEvent(
new Event('change', { bubbles: true })
);
return true;
}
function setRadio(radio) {
if (!radio.checked) {
radio.checked = true;
}
radio.dispatchEvent(
new Event('input', { bubbles: true })
);
radio.dispatchEvent(
new Event('change', { bubbles: true })
);
return true;
}
function applyTheme(force = false) {
const mode = mediaQuery.matches
? 'dark'
: 'light';
const wantedTheme = getWantedTheme();
if (
!force &&
mode === lastMode &&
currentThemeLooksRight(wantedTheme)
) {
return;
}
const selectMatch =
findThemeSelect(wantedTheme);
if (selectMatch) {
setSelect(
selectMatch.select,
selectMatch.option
);
lastMode = mode;
return;
}
const radio =
findThemeRadio(wantedTheme);
if (radio) {
setRadio(radio);
lastMode = mode;
return;
}
const clickable =
findThemeClickable(wantedTheme);
if (clickable) {
clickable.click();
lastMode = mode;
return;
}
}
function scheduleApply(force = false) {
clearTimeout(applyTimer);
applyTimer = setTimeout(
() => applyTheme(force),
100
);
}
// Initial application
if (document.readyState === 'loading') {
document.addEventListener(
'DOMContentLoaded',
() => scheduleApply(true),
{ once: true }
);
} else {
scheduleApply(true);
}
// React to Windows/browser light ↔ dark changes
const onSchemeChange = () => {
lastMode = null;
scheduleApply(true);
};
if (
typeof mediaQuery.addEventListener ===
'function'
) {
mediaQuery.addEventListener(
'change',
onSchemeChange
);
} else if (
typeof mediaQuery.addListener ===
'function'
) {
mediaQuery.addListener(onSchemeChange);
}
// Handle dynamically generated theme controls
const observer =
new MutationObserver(() => {
scheduleApply(false);
});
const startObserver = () => {
if (!document.documentElement) return;
observer.observe(
document.documentElement,
{
childList: true,
subtree: true
}
);
scheduleApply(true);
};
if (document.readyState === 'loading') {
document.addEventListener(
'DOMContentLoaded',
startObserver,
{ once: true }
);
} else {
startObserver();
}
})();
Anonymous
(ID: f5zhNmlf )
27/09/26(Sun)15:16:17
No. 191849
>>191848
Just used ChatGPT Free version kek.
Anonymous
(ID: f5zhNmlf )
27/09/26(Sun)15:17:47
No. 191854
Imagine if we also vibecode threadwatcher and other such features found in scripts like 4chanX.
Post Reply
Theme:
Simplechan
Simplechan Dark
Tomorrow
Gurochan
Lainchan
Avellana