mirror of
https://github.com/FrankerFaceZ/FrankerFaceZ.git
synced 2025-08-10 00:00:53 +00:00
Implements an Add-on Loader so that other add-ons, such as the FFZ Add-on Pack, can be loaded directly by FFZ without requiring the user to install multiple extensions into their browser.
306 lines
No EOL
8.4 KiB
Vue
306 lines
No EOL
8.4 KiB
Vue
<template lang="html">
|
|
<div class="ffz--experiments tw-pd-t-05">
|
|
<div class="tw-pd-b-1 tw-mg-b-1 tw-border-b">
|
|
{{ t('setting.experiments.about', 'This feature allows you to override experiment values. Please note that, for most experiments, you may have to refresh the page for your changes to take effect.') }}
|
|
</div>
|
|
|
|
<div class="tw-mg-b-2 tw-flex tw-align-items-center">
|
|
<div class="tw-flex-grow-1">
|
|
{{ t('setting.experiments.unique-id', 'Unique ID: {id}', {id: unique_id}) }}
|
|
</div>
|
|
<select
|
|
ref="sort_select"
|
|
class="tw-border-radius-medium tw-font-size-6 tw-select tw-pd-l-1 tw-pd-r-3 tw-pd-y-05 tw-mg-x-05"
|
|
@change="onSort"
|
|
>
|
|
<option :selected="sort_by === 0">{{ t('setting.experiments.sort-name', 'Sort By: Name') }}</option>
|
|
<option :selected="sort_by === 1">{{ t('setting.experiments.sort-rarity', 'Sort By: Rarity') }}</option>
|
|
</select>
|
|
</div>
|
|
|
|
<h3 class="tw-mg-b-1">
|
|
{{ t('setting.experiments.ffz', 'FrankerFaceZ Experiments') }}
|
|
</h3>
|
|
|
|
<div class="ffz--experiment-list">
|
|
<section
|
|
v-for="({key, exp}) of sorted(ffz_data)"
|
|
:key="key"
|
|
:data-key="key"
|
|
>
|
|
<div class="tw-elevation-1 tw-c-background-base tw-border tw-pd-y-05 tw-pd-x-1 tw-mg-y-05 tw-flex tw-flex-nowrap">
|
|
|
|
<div class="tw-flex-grow-1">
|
|
<h4>{{ exp.name }}</h4>
|
|
<div v-if="exp.description" class="description">
|
|
{{ exp.description }}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tw-flex tw-flex-shrink-0 tw-align-items-start">
|
|
<select
|
|
:data-key="key"
|
|
class="tw-border-radius-medium tw-font-size-6 tw-select tw-pd-l-1 tw-pd-r-3 tw-pd-y-05 tw-mg-x-05"
|
|
@change="onChange($event)"
|
|
>
|
|
<option
|
|
v-for="(i, idx) in exp.groups"
|
|
:key="idx"
|
|
:selected="i.value === exp.value"
|
|
>
|
|
{{ t('setting.experiments.entry', '{value,tostring} (weight: {weight,tostring})', i) }}
|
|
</option>
|
|
</select>
|
|
|
|
<button
|
|
:disabled="exp.default"
|
|
:class="{'tw-button--disabled': exp.default}"
|
|
class="tw-mg-t-05 tw-button tw-button--text tw-tooltip-wrapper"
|
|
@click="reset(key)"
|
|
>
|
|
<span class="tw-button__text ffz-i-cancel" />
|
|
<span class="tw-tooltip tw-tooltip--down tw-tooltip--align-right">
|
|
{{ t('setting.reset', 'Reset to Default') }}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<div v-if="! Object.keys(ffz_data).length">
|
|
{{ t('setting.experiments.none', 'There are no current experiments.') }}
|
|
</div>
|
|
</div>
|
|
|
|
<h3 class="tw-mg-t-5 tw-mg-b-1">
|
|
{{ t('setting.experiments.twitch', 'Twitch Experiments') }}
|
|
</h3>
|
|
|
|
<div class="ffz--experiment-list">
|
|
<section
|
|
v-for="({key, exp}) of sorted(twitch_data)"
|
|
:key="key"
|
|
:data-key="key"
|
|
>
|
|
<div
|
|
:class="{live: exp.in_use}"
|
|
class="ffz--experiment-row tw-elevation-1 tw-c-background-base tw-border tw-pd-y-05 tw-pd-x-1 tw-mg-y-05 tw-flex"
|
|
>
|
|
<div class="tw-flex tw-flex-shrink-0 tw-align-items-center tw-border-r tw-mg-r-1 tw-pd-r-1">
|
|
<div v-if="exp.in_use" class="ffz--profile__icon ffz-i-ok tw-tooltip-wrapper">
|
|
<div class="tw-tooltip tw-tooltip--down tw-tooltip--align-left">
|
|
{{ t('setting.experiments.active', 'This experiment is active.') }}
|
|
</div>
|
|
</div>
|
|
<div v-else class="ffz--profile__icon ffz-i-cancel tw-tooltip-wrapper">
|
|
<div class="tw-tooltip tw-tooltip--down tw-tooltip--align-left">
|
|
{{ t('setting.experiments.inactive', 'This experiment is not active.') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tw-flex-grow-1">
|
|
<h4>{{ exp.name }}</h4>
|
|
<div class="description">
|
|
{{ exp.remainder }}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="tw-flex tw-flex-shrink-0 tw-align-items-start">
|
|
<select
|
|
:data-key="key"
|
|
class="tw-border-radius-medium tw-font-size-6 tw-select tw-pd-l-1 tw-pd-r-3 tw-pd-y-05 tw-mg-x-05"
|
|
@change="onTwitchChange($event)"
|
|
>
|
|
<option
|
|
v-if="exp.in_use === false"
|
|
:selected="exp.default"
|
|
>
|
|
{{ t('setting.experiments.unset', 'unset') }}
|
|
</option>
|
|
<option
|
|
v-for="(i, idx) in exp.groups"
|
|
:key="idx"
|
|
:selected="i.value === exp.value"
|
|
>
|
|
{{ t('setting.experiments.entry', '{value,tostring} (weight: {weight,tostring})', i) }}
|
|
</option>
|
|
</select>
|
|
|
|
<button
|
|
:disabled="exp.default"
|
|
:class="{'tw-button--disabled': exp.default}"
|
|
class="tw-mg-t-05 tw-button tw-button--text tw-tooltip-wrapper"
|
|
@click="resetTwitch(key)"
|
|
>
|
|
<span class="tw-button__text ffz-i-cancel" />
|
|
<span class="tw-tooltip tw-tooltip--down tw-tooltip--align-right">
|
|
{{ t('setting.reset', 'Reset to Default') }}
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<div v-if="! Object.keys(twitch_data).length">
|
|
{{ t('setting.experiments.none', 'There are no current experiments.') }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
|
|
import {has} from 'utilities/object';
|
|
|
|
export default {
|
|
props: ['item'],
|
|
|
|
data() {
|
|
return {
|
|
sort_by: 1,
|
|
unique_id: this.item.unique_id(),
|
|
ffz_data: this.item.ffz_data(),
|
|
twitch_data: this.item.twitch_data()
|
|
}
|
|
},
|
|
|
|
created() {
|
|
for(const key in this.ffz_data)
|
|
if ( has(this.ffz_data, key) ) {
|
|
const exp = this.ffz_data[key];
|
|
this.$set(exp, 'value', this.item.getAssignment(key));
|
|
this.$set(exp, 'default', ! this.item.hasOverride(key));
|
|
|
|
exp.total = exp.groups.reduce((a,b) => a + b.weight, 0);
|
|
this.calculateRarity(exp);
|
|
|
|
}
|
|
|
|
for(const key in this.twitch_data)
|
|
if ( has(this.twitch_data, key) ) {
|
|
const exp = this.twitch_data[key];
|
|
this.$set(exp, 'value', this.item.getTwitchAssignment(key));
|
|
this.$set(exp, 'default', ! this.item.hasTwitchOverride(key));
|
|
|
|
exp.in_use = this.item.usingTwitchExperiment(key);
|
|
exp.remainder = `v: ${exp.v}, t: ${exp.t}`;
|
|
exp.total = exp.groups.reduce((a,b) => a + b.weight, 0);
|
|
this.calculateRarity(exp);
|
|
}
|
|
|
|
this.item.on(':changed', this.valueChanged, this);
|
|
this.item.on(':twitch-changed', this.twitchValueChanged, this);
|
|
},
|
|
|
|
beforeDestroy() {
|
|
this.item.off(':changed', this.valueChanged, this);
|
|
this.item.off(':twitch-changed', this.twitchValueChanged, this);
|
|
},
|
|
|
|
methods: {
|
|
calculateRarity(exp) {
|
|
let rarity;
|
|
for(const group of exp.groups)
|
|
if ( group.value === exp.value ) {
|
|
rarity = group.weight / exp.total;
|
|
break;
|
|
}
|
|
|
|
this.$set(exp, 'rarity', rarity);
|
|
},
|
|
|
|
sorted(data) {
|
|
const out = Object.entries(data).map(x => ({key: x[0], exp: x[1]}));
|
|
|
|
out.sort((a,b) => {
|
|
const a_use = a.exp.in_use,
|
|
b_use = b.exp.in_use;
|
|
|
|
if ( a_use && ! b_use ) return -1;
|
|
if ( ! a_use && b_use ) return 1;
|
|
|
|
if ( this.sort_by === 1 ) {
|
|
const a_r = a.exp.rarity,
|
|
b_r = b.exp.rarity;
|
|
|
|
if ( a_r < b_r ) return -1;
|
|
if ( a_r > b_r ) return 1;
|
|
}
|
|
|
|
const a_n = a.exp.name.toLowerCase(),
|
|
b_n = b.exp.name.toLowerCase();
|
|
|
|
if ( a_n < b_n ) return -1;
|
|
if ( a_n > b_n ) return 1;
|
|
|
|
return 0;
|
|
});
|
|
|
|
return out;
|
|
},
|
|
|
|
reset(key) {
|
|
this.item.deleteOverride(key);
|
|
const exp = this.ffz_data[key];
|
|
if ( exp )
|
|
exp.default = ! this.item.hasOverride(key);
|
|
},
|
|
|
|
resetTwitch(key) {
|
|
this.item.deleteTwitchOverride(key);
|
|
const exp = this.twitch_data[key];
|
|
if ( exp )
|
|
exp.default = ! this.item.hasTwitchOverride(key);
|
|
},
|
|
|
|
onSort() {
|
|
this.sort_by = this.$refs.sort_select.selectedIndex;
|
|
},
|
|
|
|
onChange(event) {
|
|
const el = event.target,
|
|
idx = el.selectedIndex,
|
|
key = el.dataset.key;
|
|
|
|
const exp = this.ffz_data[key],
|
|
groups = exp && exp.groups,
|
|
entry = groups && groups[idx];
|
|
|
|
if ( entry )
|
|
this.item.setOverride(key, entry.value);
|
|
},
|
|
|
|
onTwitchChange(event) {
|
|
const el = event.target,
|
|
idx = el.selectedIndex,
|
|
key = el.dataset.key;
|
|
|
|
const exp = this.twitch_data[key],
|
|
offset = exp.in_use ? 0 : 1,
|
|
groups = exp && exp.groups,
|
|
entry = groups && groups[idx - offset];
|
|
|
|
if ( entry )
|
|
this.item.setTwitchOverride(key, entry.value);
|
|
},
|
|
|
|
valueChanged(key, value) {
|
|
const exp = this.ffz_data[key];
|
|
if ( exp ) {
|
|
exp.value = value;
|
|
exp.default = ! this.item.hasOverride(key);
|
|
this.calculateRarity(exp);
|
|
}
|
|
},
|
|
|
|
twitchValueChanged(key, value) {
|
|
const exp = this.twitch_data[key];
|
|
if ( exp ) {
|
|
exp.value = value;
|
|
exp.default = ! this.item.hasTwitchOverride(key);
|
|
this.calculateRarity(exp);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
</script> |