parent
bc3551d7d1
commit
db9cc4a4e6
|
@ -1,34 +1,34 @@
|
|||
function ColorDetector (image) {
|
||||
this.color = { r: 0, g: 0, b: 0 };
|
||||
this.image = image;
|
||||
this.color = { r:0, g:0, b:0 };
|
||||
this.image = image;
|
||||
}
|
||||
[
|
||||
function componentToHex (c) {
|
||||
var hex = Math.max(Math.min(c, 255), 0).toString(16);
|
||||
return hex.length === 1 ? "0" + hex : hex;
|
||||
var hex = Math.max(Math.min(c, 255),0).toString(16);
|
||||
return hex.length == 1 ? '0' + hex : hex;
|
||||
},
|
||||
|
||||
function getHexColor (offset) {
|
||||
if (!offset) {
|
||||
offset = { r: 0, g: 0, b: 0 };
|
||||
if(!offset) {
|
||||
offset = {r:0,g:0,b:0};
|
||||
}
|
||||
return "#" +
|
||||
this.componentToHex(this.color.r + offset.r) +
|
||||
this.componentToHex(this.color.g + offset.g) +
|
||||
this.componentToHex(this.color.b + offset.b);
|
||||
return "#"
|
||||
+ this.componentToHex(this.color.r + offset.r)
|
||||
+ this.componentToHex(this.color.g + offset.g)
|
||||
+ this.componentToHex(this.color.b + offset.b);
|
||||
},
|
||||
|
||||
function detect () {
|
||||
return new Promise((resolve) => {
|
||||
let blockSize = 5;
|
||||
const canvas = document.createElement("canvas");
|
||||
const context = canvas.getContext && canvas.getContext("2d");
|
||||
let data; let width; let height;
|
||||
let i = -4;
|
||||
let rgb = { r: 0, g: 0, b: 0 };
|
||||
let length;
|
||||
let count = 0;
|
||||
if (!context) {
|
||||
const canvas = document.createElement('canvas');
|
||||
const context = canvas.getContext && canvas.getContext('2d');
|
||||
let data, width, height,
|
||||
i = -4,
|
||||
rgb = {r:0,g:0,b:0},
|
||||
length,
|
||||
count = 0;
|
||||
if(!context) {
|
||||
console.warn("can't get context of avatar");
|
||||
resolve(this.color);
|
||||
return;
|
||||
|
@ -41,7 +41,7 @@ function ColorDetector (image) {
|
|||
|
||||
try {
|
||||
data = context.getImageData(0, 0, width, height);
|
||||
} catch (e) {
|
||||
} catch(e) {
|
||||
console.error("can't get image data");
|
||||
console.error(e);
|
||||
resolve(this.color);
|
||||
|
@ -50,36 +50,36 @@ function ColorDetector (image) {
|
|||
|
||||
length = data.data.length;
|
||||
|
||||
while ((i += blockSize * 4) < length) {
|
||||
while ( ( i += blockSize * 4) < length ) {
|
||||
++count;
|
||||
rgb.r += data.data[i];
|
||||
rgb.g += data.data[i + 1];
|
||||
rgb.b += data.data[i + 2];
|
||||
rgb.g += data.data[i+1];
|
||||
rgb.b += data.data[i+2];
|
||||
}
|
||||
|
||||
this.color.r = ~~(rgb.r / count);
|
||||
this.color.g = ~~(rgb.g / count);
|
||||
this.color.b = ~~(rgb.b / count);
|
||||
this.color.r = ~~(rgb.r/count);
|
||||
this.color.g = ~~(rgb.g/count);
|
||||
this.color.b = ~~(rgb.b/count);
|
||||
|
||||
resolve(this.color);
|
||||
});
|
||||
}
|
||||
].forEach((fn) => { ColorDetector.prototype[fn.name] = fn; });
|
||||
|
||||
function PleromaCat (handle) {
|
||||
function PleromaCat(handle) {
|
||||
this.handle = handle;
|
||||
this.colors = {
|
||||
backgroundColor: "#000000",
|
||||
borderColor: "#000000"
|
||||
backgroundColor: '#000000',
|
||||
borderColor: '#000000'
|
||||
};
|
||||
this.config = {
|
||||
"nya": {
|
||||
'nya': {
|
||||
enabled: true,
|
||||
matcher: "(^|\s|>)な+(\s|<|$)", // eslint-disable-line no-useless-escape
|
||||
matcher: "(^|\s|>)な+(\s|<|$)",
|
||||
replacer: {
|
||||
source: "な",
|
||||
dest: "にゃ"
|
||||
}
|
||||
dest: 'にゃ'
|
||||
},
|
||||
}
|
||||
};
|
||||
this.loadConfig();
|
||||
|
@ -92,7 +92,7 @@ function PleromaCat (handle) {
|
|||
if (!json.nya) {
|
||||
return;
|
||||
}
|
||||
this.config.nya.enabled = json.nya.enabled;
|
||||
this.config.nya.enabled = json.nya.enabled;
|
||||
if (this.config.nya.enabled) {
|
||||
this.config.nya.matcher = json.nya.matcher || this.config.nya.matcher;
|
||||
this.config.nya.replacer.source = json.nya.replacer.source || this.config.nya.replacer.source;
|
||||
|
@ -110,50 +110,50 @@ function PleromaCat (handle) {
|
|||
},
|
||||
|
||||
function getClassName () {
|
||||
return "USER____" + this.handle.replace(/@/g, "_AT_").replace(/\./g, "_");
|
||||
return 'USER____' + this.handle.replace(/@/g,'_AT_').replace(/\./g,'_');
|
||||
},
|
||||
|
||||
function makeCat () {
|
||||
var posts = document.querySelectorAll("." + this.getClassName());
|
||||
this.makeCatByClassName("user-info");
|
||||
this.makeCatByClassName("basic-user-card", "basic-user-card-screen-name");
|
||||
for (const currentPost of posts) {
|
||||
this.makeCatByClassName('user-info');
|
||||
this.makeCatByClassName('basic-user-card', 'basic-user-card-screen-name');
|
||||
for(const currentPost of posts) {
|
||||
this.makeCatByElement(currentPost);
|
||||
this.nyaByPost(currentPost);
|
||||
}
|
||||
},
|
||||
|
||||
function makeCatByClassName (className, usernameClass) {
|
||||
if (!className) {
|
||||
className = "user-info";
|
||||
if(!className) {
|
||||
className = 'user-info';
|
||||
}
|
||||
if (!usernameClass) {
|
||||
usernameClass = "user-screen-name";
|
||||
usernameClass = 'user-screen-name';
|
||||
}
|
||||
const userinfos = document.querySelectorAll("." + className);
|
||||
for (const infoIndex in userinfos) {
|
||||
if (userinfos[infoIndex].querySelector && !/cat$/.test(userinfos[infoIndex].innerText)) {
|
||||
for(const infoIndex in userinfos) {
|
||||
if(userinfos[infoIndex].querySelector && !/cat$/.test(userinfos[infoIndex].innerText)) {
|
||||
const handle = userinfos[infoIndex].querySelector("." + usernameClass);
|
||||
const regexHandle = new RegExp(this.handle, "i");
|
||||
if (handle) {
|
||||
if (regexHandle.test(handle.innerText)) {
|
||||
const regexHandle = new RegExp(this.handle, 'i');
|
||||
if(handle) {
|
||||
if(regexHandle.test(handle.innerText)) {
|
||||
this.makeCatByElement(userinfos[infoIndex]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
function makeCatByElement (element) {
|
||||
if (element.querySelectorAll) {
|
||||
if (!/cat$/.test(element.className)) {
|
||||
element.className += " cat";
|
||||
if(element.querySelectorAll) {
|
||||
if(!/cat$/.test(element.className)) {
|
||||
element.className += ' cat';
|
||||
}
|
||||
const avatars = element.querySelectorAll(".avatar");
|
||||
for (const avatarIndex in avatars) {
|
||||
const avatars = element.querySelectorAll('.avatar');
|
||||
for(const avatarIndex in avatars) {
|
||||
const currentAvatar = avatars[avatarIndex];
|
||||
if (currentAvatar.style) {
|
||||
if (this.colors.borderColor === "#000000") {
|
||||
if(currentAvatar.style) {
|
||||
if(this.colors.borderColor == '#000000') {
|
||||
this.detectColors(currentAvatar);
|
||||
}
|
||||
currentAvatar.style.backgroundColor = this.colors.backgroundColor;
|
||||
|
@ -164,16 +164,16 @@ function PleromaCat (handle) {
|
|||
},
|
||||
|
||||
function nyaByPost (element) {
|
||||
if (element.querySelectorAll && this.config.nya.enabled) {
|
||||
const contents = element.querySelectorAll(".status-content");
|
||||
for (const content of contents) {
|
||||
if (content.innerHTML) {
|
||||
if(element.querySelectorAll && this.config.nya.enabled) {
|
||||
const contents = element.querySelectorAll('.status-content');
|
||||
for(const content of contents) {
|
||||
if(content.innerHTML) {
|
||||
const regex = new RegExp(this.config.nya.matcher, "g");
|
||||
let match;
|
||||
while ((match = regex.exec(content.innerHTML)) !== null) {
|
||||
while((match = regex.exec(content.innerHTML))!==null) {
|
||||
const source = match[0];
|
||||
const dest = source.replace(
|
||||
new RegExp(this.config.nya.replacer.source, "g"),
|
||||
new RegExp(this.config.nya.replacer.source, "g"),
|
||||
this.config.nya.replacer.dest
|
||||
);
|
||||
content.innerHTML = content.innerHTML.replace(source, dest);
|
||||
|
@ -184,14 +184,14 @@ function PleromaCat (handle) {
|
|||
},
|
||||
|
||||
function detectColors (avatarElement) {
|
||||
const images = avatarElement.querySelectorAll("img");
|
||||
for (const imageIndex in images) {
|
||||
const images = avatarElement.querySelectorAll('img');
|
||||
for(const imageIndex in images) {
|
||||
images[imageIndex].crossOrigin = "anonymous";
|
||||
const colorAvatar = () => {
|
||||
const detector = new ColorDetector(images[imageIndex]);
|
||||
detector.detect().then((color) => {
|
||||
this.colors.backgroundColor = detector.getHexColor();
|
||||
this.colors.borderColor = detector.getHexColor({ r: -40, g: -40, b: -40 });
|
||||
this.colors.borderColor = detector.getHexColor({r:-40,g:-40,b:-40});
|
||||
avatarElement.style.backgroundColor = this.colors.backgroundColor;
|
||||
avatarElement.style.borderColor = this.colors.borderColor;
|
||||
});
|
||||
|
@ -206,7 +206,7 @@ function PleromaCat (handle) {
|
|||
}
|
||||
].forEach((fn) => { PleromaCat.prototype[fn.name] = fn; });
|
||||
|
||||
function PleromaModCatify () {
|
||||
function PleromaModCatify() {
|
||||
this.cats = {};
|
||||
this.config = {
|
||||
stylesheet: "style.css",
|
||||
|
@ -234,13 +234,12 @@ function PleromaModCatify () {
|
|||
]
|
||||
},
|
||||
filter: [
|
||||
"user-info",
|
||||
"timeline",
|
||||
"panel-body",
|
||||
"main",
|
||||
"active",
|
||||
"status-body"
|
||||
]
|
||||
],
|
||||
};
|
||||
|
||||
this.loadConfig();
|
||||
|
@ -264,9 +263,6 @@ function PleromaModCatify () {
|
|||
},
|
||||
|
||||
function onMutation (mutation, observer) {
|
||||
if (mutation.target.classList.contains("user-info")) {
|
||||
mutation.target.classList.remove("cat");
|
||||
}
|
||||
this.detectCats();
|
||||
this.catify();
|
||||
},
|
||||
|
@ -283,21 +279,21 @@ function PleromaModCatify () {
|
|||
|
||||
function addCat (handle) {
|
||||
handle = handle.trim();
|
||||
if (!this.cats.handle) {
|
||||
if(!this.cats.hasOwnProperty(handle)) {
|
||||
this.cats[handle] = new PleromaCat(handle);
|
||||
}
|
||||
},
|
||||
|
||||
function areYouACat () {
|
||||
const profile = document.querySelector(".user-card");
|
||||
const pattern = this.config.triggers.displayName.join("|");
|
||||
const regex = new RegExp(pattern, "i");
|
||||
if (profile) {
|
||||
const username = profile.querySelector(".user-name");
|
||||
if (username) {
|
||||
if (regex.test(username.innerText)) {
|
||||
const accountName = profile.querySelector(".user-screen-name");
|
||||
if (accountName) {
|
||||
const profile = document.querySelector('.user-card');
|
||||
const pattern = this.config.triggers.displayName.join('|');
|
||||
const regex = new RegExp(pattern, 'i');
|
||||
if(profile) {
|
||||
const username = profile.querySelector('.user-name');
|
||||
if(username) {
|
||||
if(regex.test(username.innerText)) {
|
||||
const accountName = profile.querySelector('.user-screen-name');
|
||||
if(accountName) {
|
||||
this.addCat(accountName.innerText.substring(1), true);
|
||||
}
|
||||
}
|
||||
|
@ -306,24 +302,24 @@ function PleromaModCatify () {
|
|||
},
|
||||
|
||||
function detectCatsByClassName (classname, usernameClass, accountnameClass) {
|
||||
classname = classname || "name-and-account-name";
|
||||
usernameClass = usernameClass || "user-name";
|
||||
accountnameClass = accountnameClass || "account-name";
|
||||
classname = classname || 'name-and-account-name';
|
||||
usernameClass = usernameClass || 'user-name';
|
||||
accountnameClass = accountnameClass || 'account-name';
|
||||
const nameAndAccountNames = document.querySelectorAll("." + classname);
|
||||
const regexName = new RegExp(this.config.triggers.displayName.join("|"), "i");
|
||||
const regexInstance = new RegExp(this.config.triggers.instances.join("|"), "i");
|
||||
for (const currentAccount of nameAndAccountNames) {
|
||||
if (currentAccount.querySelector) {
|
||||
const regexName = new RegExp(this.config.triggers.displayName.join('|'),'i');
|
||||
const regexInstance = new RegExp(this.config.triggers.instances.join('|'),'i');
|
||||
for(const currentAccount of nameAndAccountNames) {
|
||||
if(currentAccount.querySelector) {
|
||||
let isCat = false;
|
||||
const username = currentAccount.querySelector("." + usernameClass);
|
||||
if (username) {
|
||||
if(username) {
|
||||
isCat = regexName.test(username.innerText);
|
||||
}
|
||||
const account = currentAccount.querySelector("." + accountnameClass);
|
||||
if (account) {
|
||||
if(account) {
|
||||
const handle = account.innerText;
|
||||
isCat = isCat || regexInstance.test(handle);
|
||||
if (isCat) {
|
||||
if(isCat) {
|
||||
this.addCat(handle);
|
||||
}
|
||||
}
|
||||
|
@ -332,12 +328,12 @@ function PleromaModCatify () {
|
|||
},
|
||||
|
||||
function detectCats () {
|
||||
this.detectCatsByClassName("name-and-account-name");
|
||||
this.detectCatsByClassName("basic-user-card", "basic-user-card-user-name-value", "basic-user-card-screen-name");
|
||||
this.detectCatsByClassName('name-and-account-name');
|
||||
this.detectCatsByClassName('basic-user-card', 'basic-user-card-user-name-value', 'basic-user-card-screen-name');
|
||||
},
|
||||
|
||||
function catify () {
|
||||
for (const catKey in this.cats) {
|
||||
for(const catKey in this.cats) {
|
||||
this.cats[catKey].makeCat();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
.post-status-form button.btn.btn-default::after {
|
||||
content: "Submit";
|
||||
line-height: 0;
|
||||
text-indent: initial;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.post-status-form button.btn.btn-default {
|
||||
text-indent: -9999px;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.cat>:not(.status-body) .avatar::before, .cat>:not(.status-body) .avatar::after {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
|
@ -21,7 +33,7 @@
|
|||
z-index: 1;
|
||||
}
|
||||
|
||||
.cat>:not(.status-body) .avatar img, .cat>:not(.status-body) .avatar canvas {
|
||||
.cat>:not(.status-body) .avatar img {
|
||||
border-radius: 100%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
|
|
|
@ -1,60 +1,51 @@
|
|||
|
||||
function AudioPlayer( callback, effect ) {
|
||||
var AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
var audioContext = new AudioContext();
|
||||
var scriptProcessor = audioContext.createScriptProcessor( 0, 0, 2 );
|
||||
var audioSource = new SineSource( audioContext.sampleRate );
|
||||
var gainNode = audioContext.createGain();
|
||||
gainNode.gain.value = localStorage.getItem('volume') === null ? 0.25 : localStorage.getItem('volume');
|
||||
gainNode.connect( audioContext.destination );
|
||||
|
||||
var onaudioprocess = function( event ) {
|
||||
var count = event.outputBuffer.length;
|
||||
if( callback ) {
|
||||
callback( count );
|
||||
}
|
||||
var leftBuf = event.outputBuffer.getChannelData( 0 );
|
||||
var rightBuf = event.outputBuffer.getChannelData( 1 );
|
||||
audioSource.getAudio( leftBuf, rightBuf, count );
|
||||
if( effect ) {
|
||||
effect( leftBuf, rightBuf, count );
|
||||
}
|
||||
}
|
||||
this.getSamplingRate = function() {
|
||||
return audioContext.sampleRate;
|
||||
}
|
||||
this.setAudioSource = function( audioSrc ) {
|
||||
audioSource = audioSrc;
|
||||
}
|
||||
this.play = function() {
|
||||
audioContext.resume().then(() => {
|
||||
scriptProcessor.onaudioprocess = onaudioprocess;
|
||||
scriptProcessor.connect( gainNode );
|
||||
});
|
||||
}
|
||||
this.stop = function() {
|
||||
if( scriptProcessor.onaudioprocess ) {
|
||||
scriptProcessor.disconnect( gainNode );
|
||||
scriptProcessor.onaudioprocess = null;
|
||||
}
|
||||
}
|
||||
this.setVolume = function( volume ) {
|
||||
gainNode.gain.value = volume;
|
||||
}
|
||||
var audioContext = new AudioContext();
|
||||
var scriptProcessor = audioContext.createScriptProcessor( 0, 0, 2 );
|
||||
var audioSource = new SineSource( audioContext.sampleRate );
|
||||
var onaudioprocess = function( event ) {
|
||||
var count = event.outputBuffer.length;
|
||||
if( callback ) {
|
||||
callback( count );
|
||||
}
|
||||
var leftBuf = event.outputBuffer.getChannelData( 0 );
|
||||
var rightBuf = event.outputBuffer.getChannelData( 1 );
|
||||
audioSource.getAudio( leftBuf, rightBuf, count );
|
||||
if( effect ) {
|
||||
effect( leftBuf, rightBuf, count );
|
||||
}
|
||||
}
|
||||
this.getSamplingRate = function() {
|
||||
return audioContext.sampleRate;
|
||||
}
|
||||
this.setAudioSource = function( audioSrc ) {
|
||||
audioSource = audioSrc;
|
||||
}
|
||||
this.play = function() {
|
||||
scriptProcessor.onaudioprocess = onaudioprocess;
|
||||
scriptProcessor.connect( audioContext.destination );
|
||||
}
|
||||
this.stop = function() {
|
||||
if( scriptProcessor.onaudioprocess ) {
|
||||
scriptProcessor.disconnect( audioContext.destination );
|
||||
scriptProcessor.onaudioprocess = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function SineSource( samplingRate ) {
|
||||
// Simple AudioSource for testing.
|
||||
var rate = samplingRate;
|
||||
var freq = 2 * Math.PI * 440 / rate;
|
||||
var phase = 0;
|
||||
this.getSamplingRate = function() {
|
||||
return rate;
|
||||
}
|
||||
this.getAudio = function( leftBuffer, rightBuffer, count ) {
|
||||
for( var idx = 0; idx < count; idx++, phase++ ) {
|
||||
leftBuffer[ idx ] = Math.sin( phase * freq );
|
||||
rightBuffer[ idx ] = Math.sin( phase * freq * 0.5 );
|
||||
}
|
||||
}
|
||||
// Simple AudioSource for testing.
|
||||
var rate = samplingRate;
|
||||
var freq = 2 * Math.PI * 440 / rate;
|
||||
var phase = 0;
|
||||
this.getSamplingRate = function() {
|
||||
return rate;
|
||||
}
|
||||
this.getAudio = function( leftBuffer, rightBuffer, count ) {
|
||||
for( var idx = 0; idx < count; idx++, phase++ ) {
|
||||
leftBuffer[ idx ] = Math.sin( phase * freq );
|
||||
rightBuffer[ idx ] = Math.sin( phase * freq * 0.5 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ PleromaModPlayer = function (attachment) {
|
|||
this.initComponents();
|
||||
this.module = null;
|
||||
this.replay = null;
|
||||
this.duration = 0;
|
||||
this.patternDisplay = null;
|
||||
this.samplePosition = 0;
|
||||
this.channel = 0;
|
||||
|
@ -47,19 +46,7 @@ PleromaModPlayer = function (attachment) {
|
|||
this.seekBar.setAttribute("type", "range");
|
||||
this.seekBar.onmousedown = () => { this.stop() };
|
||||
this.seekBar.onmouseup = () => { this.play() };
|
||||
this.seekBar.onkeydown = () => { this.stop() };
|
||||
this.seekBar.onkeyup = () => { this.play() };
|
||||
controls.appendChild(this.seekBar);
|
||||
|
||||
this.volumeBar = document.createElement("input");
|
||||
this.volumeBar.setAttribute("class", "mod-volumebar");
|
||||
this.volumeBar.setAttribute("type", "range");
|
||||
this.volumeBar.value = localStorage.getItem('volume') === null ? 25 : localStorage.getItem('volume') * 100;
|
||||
this.volumeBar.max = 100;
|
||||
this.volumeBar.onmouseup = () => { localStorage.setItem('volume', this.volumeBar.value / 100) };
|
||||
this.volumeBar.onkeyup = () => { localStorage.setItem('volume', this.volumeBar.value / 100) };
|
||||
this.volumeBar.onmousemove = () => { PleromaModTracker.player.setVolume(this.volumeBar.value / 100) };
|
||||
controls.appendChild(this.volumeBar);
|
||||
|
||||
this.attachment.appendChild(controls);
|
||||
|
||||
|
@ -105,10 +92,10 @@ PleromaModPlayer = function (attachment) {
|
|||
this.module = new IBXMModule(moduleData);
|
||||
const rate = PleromaModTracker.player.getSamplingRate();
|
||||
this.replay = new IBXMReplay(this.module, rate);
|
||||
this.duration = Math.round(this.replay.calculateSongDuration() / rate);
|
||||
const duration = Math.round(this.replay.calculateSongDuration() / rate);
|
||||
this.samplePosition = 0;
|
||||
this.seekBar.value = 0;
|
||||
this.seekBar.max = this.duration;
|
||||
this.seekBar.max = duration;
|
||||
this.songName.innerText = this.module.songName;
|
||||
let instruments = "";
|
||||
for (let idx = 1; idx < this.module.instruments.length; idx++) {
|
||||
|
@ -128,7 +115,7 @@ PleromaModPlayer = function (attachment) {
|
|||
if (count) {
|
||||
this.samplePosition += count;
|
||||
}
|
||||
this.seekBar.value = this.samplePosition / PleromaModTracker.player.getSamplingRate() % this.duration;
|
||||
this.seekBar.value = this.samplePosition / PleromaModTracker.player.getSamplingRate();
|
||||
this.patternDisplay.display(this.module, this.replay, this.channel, this.patternCanvas);
|
||||
},
|
||||
|
||||
|
@ -268,4 +255,4 @@ PleromaModTracker.currentDisplay = null;
|
|||
}
|
||||
].forEach((fn) => { PleromaModTracker[fn.name] = fn; });
|
||||
|
||||
PleromaModLoader.registerMod(PleromaModTracker);
|
||||
PleromaModLoader.registerMod(PleromaModTracker);
|
||||
|
|
Loading…
Reference in New Issue