Update 0BDFDB.plugin.js
This commit is contained in:
parent
3a81c8a3e9
commit
0d45f5f815
|
@ -2,7 +2,7 @@
|
|||
* @name BDFDB
|
||||
* @author DevilBro
|
||||
* @authorId 278543574059057154
|
||||
* @version 2.1.7
|
||||
* @version 2.1.8
|
||||
* @description Required Library for DevilBro's Plugins
|
||||
* @invite Jx3TjNS
|
||||
* @donate https://www.paypal.me/MircoWittrien
|
||||
|
@ -19,22 +19,10 @@ module.exports = (_ => {
|
|||
"info": {
|
||||
"name": "BDFDB",
|
||||
"author": "DevilBro",
|
||||
"version": "2.1.7",
|
||||
"version": "2.1.8",
|
||||
"description": "Required Library for DevilBro's Plugins"
|
||||
},
|
||||
"rawUrl": `https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js`,
|
||||
"changeLog": {
|
||||
"progress": {
|
||||
"Updates": "Yes there have been a lot of Updates in the Last Days, that's because I haven't had time to fix old stuff in the last weeks and Discord changed a lot in the last days. This is the last Update for now, since some of y'all are annoyed by update notifications"
|
||||
},
|
||||
"fixed": {
|
||||
"Context Menu Slider": "Fixed an issue where the volume slider in the User Menu couldn't be dragged properlly",
|
||||
"Context Menus Entry Spam": "Fixed an issue where in some plugin combinations, context menu entries would get mulitplicated",
|
||||
"Lazy Components": "Properly patches lazy components now, fixing issues with multiple plugins",
|
||||
"Context Menus": "Fully work again, no further crashes",
|
||||
"Better Friend List": "Fixed Crash"
|
||||
}
|
||||
}
|
||||
"rawUrl": `https://mwittrien.github.io/BetterDiscordAddons/Library/0BDFDB.plugin.js`
|
||||
};
|
||||
|
||||
const DiscordObjects = {};
|
||||
|
@ -585,7 +573,7 @@ module.exports = (_ => {
|
|||
BDFDB.PluginUtils.checkAllUpdates();
|
||||
}, 1000*60*60*4);
|
||||
|
||||
BDFDB.TimeUtils.timeout(_ => {BDFDB.ArrayUtils.remove(PluginStores.updateData.timeouts, plugin.name, true);}, 30000);
|
||||
BDFDB.TimeUtils.timeout(_ => BDFDB.ArrayUtils.remove(PluginStores.updateData.timeouts, plugin.name, true), 30000);
|
||||
}
|
||||
};
|
||||
BDFDB.PluginUtils.init = function (plugin) {
|
||||
|
@ -698,7 +686,7 @@ module.exports = (_ => {
|
|||
}
|
||||
});
|
||||
});
|
||||
return new Promise(callback => {callback(null);});
|
||||
return new Promise(callback => callback(null));
|
||||
};
|
||||
BDFDB.PluginUtils.checkAllUpdates = function () {
|
||||
return new Promise(callback => {
|
||||
|
@ -763,7 +751,7 @@ module.exports = (_ => {
|
|||
contents: BDFDB.LanguageUtils.LanguageStrings.FORM_LABEL_ALL,
|
||||
onClick: _ => {for (let notice of updateNotice.querySelectorAll(BDFDB.dotCN.noticeupdateentry)) notice.click();}
|
||||
}],
|
||||
onClose: _ => {vanishObserver.disconnect();}
|
||||
onClose: _ => vanishObserver.disconnect()
|
||||
});
|
||||
updateNotice.style.setProperty("position", "relative", "important");
|
||||
updateNotice.style.setProperty("visibility", "visible", "important");
|
||||
|
@ -1205,15 +1193,29 @@ module.exports = (_ => {
|
|||
};
|
||||
|
||||
InternalBDFDB.lazyLoadModuleImports = function (moduleString) {
|
||||
return new Promise(callback => {
|
||||
if (typeof moduleString !== "string") moduleString = InternalBDFDB.getModuleString(moduleString);
|
||||
if (!moduleString || typeof moduleString !== "string") return BDFDB.LogUtils.error("Trying to lazy load Imports but Module is not a String");
|
||||
const [, promiseMatch, menuRequest] = moduleString.match(/return (Promise\.all\(.+?\))\.then\((.+?)\)\);/) ?? [];
|
||||
if (!promiseMatch) return BDFDB.LogUtils.error("Trying to lazy load Imports but Module does not contain lazy Imports");
|
||||
const imports = promiseMatch.match(/\d+/g)?.map(e => Number(e));
|
||||
const menuIndex = menuRequest.match(/\d+/)?.[0];
|
||||
if (!imports || !menuIndex) return BDFDB.LogUtils.error("Trying to lazy load Imports but could not find Indexes");
|
||||
if (!moduleString || typeof moduleString !== "string") {
|
||||
BDFDB.LogUtils.error("Trying to lazy load Imports but Module is not a String");
|
||||
return callback(null);
|
||||
}
|
||||
let run = true, imports = [], menuIndexes = [];
|
||||
while (run) {
|
||||
const [matchString, promiseMatch, menuRequest] = moduleString.match(/return (Promise\.all\(.+?\))\.then\((.+?)\)\)/) ?? [];
|
||||
if (!promiseMatch) run = false;
|
||||
else {
|
||||
imports = imports.concat(promiseMatch.match(/\d+/g)?.map(e => Number(e)));
|
||||
menuIndexes.push(menuRequest.match(/\d+/)?.[0]);
|
||||
moduleString = moduleString.replace(matchString, "");
|
||||
}
|
||||
}
|
||||
if (!imports.length || !menuIndexes.length) {
|
||||
BDFDB.LogUtils.error("Trying to lazy load Imports but could not find Indexes");
|
||||
return callback(null);
|
||||
}
|
||||
const req = InternalBDFDB.getWebModuleReq();
|
||||
return Promise.all(imports.map(index => req.e(index))).then(() => req(menuIndex));
|
||||
Promise.all(BDFDB.ArrayUtils.removeCopies(imports).map(i => req.e(i))).then(_ => Promise.all(BDFDB.ArrayUtils.removeCopies(menuIndexes).map(i => req(i)))).then(callback);
|
||||
});
|
||||
};
|
||||
|
||||
BDFDB.ModuleUtils = {};
|
||||
|
@ -2242,14 +2244,21 @@ module.exports = (_ => {
|
|||
let exports = module && !config.exported && module.exports || module;
|
||||
exports = config.path && BDFDB.ObjectUtils.get(exports, config.path) || exports;
|
||||
exports && InternalBDFDB.patchComponent(pluginData, InternalBDFDB.isMemoOrForwardRef(exports) ? exports.default : exports, config);
|
||||
return exports ? true : false;
|
||||
};
|
||||
let found = true;
|
||||
if (config.lazyLoaded) InternalBDFDB.addChunkObserver(pluginData, config);
|
||||
else if (config.classNames.length) InternalBDFDB.searchComponent(pluginData, config);
|
||||
else if (config.subComponent && config.subComponent.strings || config.stringFind) patchSpecial("findByString", config.subComponent && config.subComponent.strings || config.stringFind);
|
||||
else if (config.subComponent && config.subComponent.props || config.propertyFind) patchSpecial("findByProperties", config.subComponent && config.subComponent.props || config.propertyFind);
|
||||
else if (config.subComponent && config.subComponent.protos || config.prototypeFind) patchSpecial("findByPrototypes", config.subComponent && config.subComponent.protos || config.prototypeFind);
|
||||
else if (config.nonRender) patchSpecial("findByName", config.name);
|
||||
else InternalBDFDB.patchComponent(pluginData, BDFDB.ModuleUtils.findByName(config.name), config);
|
||||
else if (config.subComponent && config.subComponent.strings || config.stringFind) found = patchSpecial("findByString", config.subComponent && config.subComponent.strings || config.stringFind);
|
||||
else if (config.subComponent && config.subComponent.props || config.propertyFind) found = patchSpecial("findByProperties", config.subComponent && config.subComponent.props || config.propertyFind);
|
||||
else if (config.subComponent && config.subComponent.protos || config.prototypeFind) found = patchSpecial("findByPrototypes", config.subComponent && config.subComponent.protos || config.prototypeFind);
|
||||
else if (config.nonRender) found = patchSpecial("findByName", config.name);
|
||||
else {
|
||||
let module = BDFDB.ModuleUtils.findByName(config.name);
|
||||
if (module) InternalBDFDB.patchComponent(pluginData, module, config);
|
||||
else found = false;
|
||||
}
|
||||
if (!found) InternalBDFDB.addChunkObserver(pluginData, config);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -4098,7 +4107,7 @@ module.exports = (_ => {
|
|||
if (!returnvalue || !BDFDB.ObjectUtils.is(config) || !config.label && !config.id) return [null, -1];
|
||||
config.label = config.label && [config.label].flat().filter(n => n);
|
||||
config.id = config.id && [config.id].flat().filter(n => n);
|
||||
let contextMenu = BDFDB.ReactUtils.findChild(returnvalue, {props: "navId"});
|
||||
let contextMenu = BDFDB.ReactUtils.findChild(returnvalue, {props: "navId"}) || (BDFDB.ArrayUtils.is(returnvalue) ? {props: {children: returnvalue}} : null);
|
||||
if (contextMenu) {
|
||||
for (let i in contextMenu.props.children) {
|
||||
if (contextMenu.props.children[i] && contextMenu.props.children[i].type == RealMenuItems.MenuGroup) {
|
||||
|
@ -4859,6 +4868,7 @@ module.exports = (_ => {
|
|||
}
|
||||
};
|
||||
|
||||
const loadComponents = _ => {
|
||||
for (let name in InternalData.NativeSubComponents) {
|
||||
if (InternalData.NativeSubComponents[name].name) {
|
||||
if (InternalData.NativeSubComponents[name].protos) InternalComponents.NativeSubComponents[name] = BDFDB.ModuleUtils.find(m => m && m.displayName == InternalData.NativeSubComponents[name].name && m.prototype && InternalData.NativeSubComponents[name].protos.every(proto => m.prototype[proto]) && m);
|
||||
|
@ -6448,7 +6458,7 @@ module.exports = (_ => {
|
|||
direction: InternalComponents.LibraryComponents.Flex.Direction.HORIZONTAL,
|
||||
align: InternalComponents.LibraryComponents.Flex.Align.CENTER,
|
||||
children: [
|
||||
BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.KeybindRecorder, BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
|
||||
BDFDB.ReactUtils.createElement(InternalComponents.NativeSubComponents.KeybindRecorder || BDFDB.ModuleUtils.findByName("KeybindRecorder"), BDFDB.ObjectUtils.exclude(Object.assign({}, this.props, {
|
||||
defaultValue: [this.props.defaultValue || this.props.value].flat(10).filter(n => n).map(keyCode => [BDFDB.DiscordConstants.KeyboardDeviceTypes.KEYBOARD_KEY, LibraryModules.KeyCodeUtils.keyToCode((Object.entries(LibraryModules.KeyEvents.codes).find(n => n[1] == keyCode && LibraryModules.KeyCodeUtils.keyToCode(n[0], null)) || [])[0], null) || keyCode]),
|
||||
onChange: this.handleChange.bind(this)
|
||||
}), "reset", "onReset")),
|
||||
|
@ -7996,8 +8006,6 @@ module.exports = (_ => {
|
|||
EmojiPickerListRow: "default"
|
||||
},
|
||||
after: {
|
||||
useUserVolumeItem: "default",
|
||||
useUserRolesItems : "default",
|
||||
Menu: "default",
|
||||
SettingsView: "componentDidMount",
|
||||
Shakeable: "render",
|
||||
|
@ -8223,11 +8231,10 @@ module.exports = (_ => {
|
|||
PluginStores.chunkObserver[config.mappedType].query.push(pluginData);
|
||||
}
|
||||
};
|
||||
const QueuedComponents = ["GuildHeaderContextMenu", "SystemMessageOptionContextMenu", "SystemMessageOptionToolbar", "MessageOptionContextMenu", "MessageOptionToolbar"];
|
||||
const ContextMenuTypes = ["UserSettingsCog", "UserProfileActions", "GroupDM", "DM", "User", "Developer", "Slate", "GuildSettingsRole", "GuildDirectoryEntry", "GuildFolder", "SystemMessage", "Message", "Native", "Role", "Guild", "Channel"];
|
||||
InternalBDFDB.addQueuePatches = function (plugin) {
|
||||
if (!InternalData.ModuleUtilsConfig.QueuedComponents) return;
|
||||
plugin = plugin == BDFDB && InternalBDFDB || plugin;
|
||||
for (let type of QueuedComponents) if (typeof plugin[`on${type}`] == "function") {
|
||||
for (let type of InternalData.ModuleUtilsConfig.QueuedComponents) if (typeof plugin[`on${type}`] == "function") {
|
||||
if (PluginStores.patchQueues[type].query.indexOf(plugin) == -1) {
|
||||
PluginStores.patchQueues[type].query.push(plugin);
|
||||
PluginStores.patchQueues[type].query.sort((x, y) => x.name < y.name ? -1 : x.name > y.name ? 1 : 0);
|
||||
|
@ -8240,10 +8247,11 @@ module.exports = (_ => {
|
|||
}
|
||||
};
|
||||
InternalBDFDB.addContextChunkObservers = function (plugin) {
|
||||
if (!InternalData.ModuleUtilsConfig.ContextMenuTypes) return;
|
||||
plugin = plugin == BDFDB && InternalBDFDB || plugin;
|
||||
for (let type of ContextMenuTypes) {
|
||||
for (let type of InternalData.ModuleUtilsConfig.ContextMenuTypes) {
|
||||
type = `${type}ContextMenu`;
|
||||
if (typeof plugin[`on${type}`] == "function") {
|
||||
if (typeof plugin[`on${InternalData.ModuleUtilsConfig.ContextMenuTypesMap[type] || type}`] == "function") {
|
||||
for (let module of PluginStores.contextChunkObserver[type].modules) InternalBDFDB.patchContextMenu(plugin, type, module);
|
||||
if (PluginStores.contextChunkObserver[type].query.indexOf(plugin) == -1) {
|
||||
PluginStores.contextChunkObserver[type].query.push(plugin);
|
||||
|
@ -8255,10 +8263,12 @@ module.exports = (_ => {
|
|||
InternalBDFDB.patchContextMenu = function (plugin, type, module) {
|
||||
if (!module || !module.default) return;
|
||||
plugin = plugin == BDFDB && InternalBDFDB || plugin;
|
||||
const caller = `on${InternalData.ModuleUtilsConfig.ContextMenuTypesMap[type] || type}`;
|
||||
if (!InternalData.ModuleUtilsConfig.ContextMenuSubItemsMap[type]) {
|
||||
const call = (args, props, returnValue, name) => {
|
||||
if (!returnValue || !returnValue.props || !returnValue.props.children || returnValue.props.children.__BDFDBPatchesCalled && returnValue.props.children.__BDFDBPatchesCalled[plugin.name]) return;
|
||||
returnValue.props.children.__BDFDBPatchesCalled = Object.assign({}, returnValue.props.children.__BDFDBPatchesCalled, {[plugin.name]: true});
|
||||
return plugin[`on${type}`]({
|
||||
return plugin[caller]({
|
||||
arguments: args,
|
||||
instance: {props: props},
|
||||
returnvalue: returnValue,
|
||||
|
@ -8268,12 +8278,12 @@ module.exports = (_ => {
|
|||
});
|
||||
};
|
||||
BDFDB.PatchUtils.patch(plugin, module, "default", {after: e => {
|
||||
if (typeof plugin[`on${type}`] != "function") return;
|
||||
if (typeof plugin[caller] != "function") return;
|
||||
else if (e.returnValue && e.returnValue.props.children) {
|
||||
if (BDFDB.ArrayUtils.is(e.returnValue.props.children)) call(e.methodArguments, e.methodArguments[0], e.returnValue, module.default.displayName);
|
||||
else if (e.returnValue.props.children.type && e.returnValue.props.children.type.displayName) {
|
||||
let name = e.returnValue.props.children.type.displayName;
|
||||
let originalReturn = e.returnValue.props.children.type(e.returnValue.props.children.props);
|
||||
const name = e.returnValue.props.children.type.displayName;
|
||||
const originalReturn = e.returnValue.props.children.type(e.returnValue.props.children.props);
|
||||
if (!originalReturn || !originalReturn.type) return;
|
||||
let newType = (...args) => {
|
||||
const returnValue = BDFDB.ReactUtils.createElement(originalReturn.type, originalReturn.props);
|
||||
|
@ -8288,9 +8298,30 @@ module.exports = (_ => {
|
|||
}
|
||||
}
|
||||
else BDFDB.PatchUtils.patch(plugin, e.returnValue, "type", {after: e2 => {
|
||||
if (e2.returnValue && typeof plugin[`on${type}`] == "function") call(e2.methodArguments, e2.methodArguments[0], e2.returnValue, module.default.displayName);
|
||||
if (e2.returnValue && typeof plugin[caller] == "function") call(e2.methodArguments, e2.methodArguments[0], e2.returnValue, module.default.displayName);
|
||||
}}, {noCache: true});
|
||||
}}, {name: type});
|
||||
}
|
||||
else {
|
||||
const getProps = (props, key) => {
|
||||
const store = `${LibraryModules.StringUtils.upperCaseFirstChar(key)}Store`;
|
||||
const getter = `get${LibraryModules.StringUtils.upperCaseFirstChar(key)}`;
|
||||
return Object.assign({}, BDFDB.ObjectUtils.is(props) ? props : typeof props == "string" ? {id: props} : {}, {[key]: (props && props[key] || LibraryModules[store] && typeof LibraryModules[store][getter] == "function" && LibraryModules[store][getter](props && props.id || props))});
|
||||
};
|
||||
BDFDB.PatchUtils.patch(plugin, module, "default", {after: e => {
|
||||
if (typeof plugin[caller] != "function") return;
|
||||
e.returnValue = [e.returnValue].flat(10).filter(n => n);
|
||||
return plugin[caller]({
|
||||
arguments: e.methodArguments,
|
||||
instance: {props: InternalData.ModuleUtilsConfig.ContextMenuSubItemsMap[type].key && getProps(e.methodArguments[0], InternalData.ModuleUtilsConfig.ContextMenuSubItemsMap[type].key) || e.methodArguments[0]},
|
||||
returnvalue: e.returnValue,
|
||||
component: module,
|
||||
methodname: "default",
|
||||
type: type,
|
||||
subType: module.default.displayName
|
||||
});
|
||||
}}, {name: type});
|
||||
}
|
||||
};
|
||||
|
||||
BDFDB.ReactUtils.instanceKey = Object.keys(document.querySelector(BDFDB.dotCN.app) || {}).some(n => n.startsWith("__reactInternalInstance")) ? "_reactInternalFiber" : "_reactInternals";
|
||||
|
@ -8373,11 +8404,12 @@ module.exports = (_ => {
|
|||
};
|
||||
})();
|
||||
|
||||
for (let type of ContextMenuTypes) {
|
||||
if (InternalData.ModuleUtilsConfig.ContextMenuTypes) for (let type of InternalData.ModuleUtilsConfig.ContextMenuTypes) {
|
||||
type = `${type}ContextMenu`;
|
||||
if (!PluginStores.contextChunkObserver[type]) {
|
||||
PluginStores.contextChunkObserver[type] = {query: [], modules: []};
|
||||
PluginStores.contextChunkObserver[type].filter = m => m && (m.displayName && m.displayName.endsWith("ContextMenu") && `${ContextMenuTypes.find(t => m.displayName.indexOf(t) > -1)}ContextMenu` == type || m._BDFDB_ContextMenuWrap && m._BDFDB_ContextMenuWrap.endsWith("ContextMenu") && `${ContextMenuTypes.find(t => m._BDFDB_ContextMenuWrap.indexOf(t) > -1)}ContextMenu` == type) && m;
|
||||
if (!InternalData.ModuleUtilsConfig.ContextMenuSubItemsMap[type]) PluginStores.contextChunkObserver[type].filter = m => m && (m.displayName && m.displayName.endsWith("ContextMenu") && `${InternalData.ModuleUtilsConfig.ContextMenuTypes.find(t => m.displayName.indexOf(t) > -1)}ContextMenu` == type || m._BDFDB_ContextMenuWrap && m._BDFDB_ContextMenuWrap.endsWith("ContextMenu") && `${InternalData.ModuleUtilsConfig.ContextMenuTypes.find(t => m._BDFDB_ContextMenuWrap.indexOf(t) > -1)}ContextMenu` == type) && m;
|
||||
else PluginStores.contextChunkObserver[type].filter = m => m && m.displayName && InternalData.ModuleUtilsConfig.ContextMenuSubItemsMap[type].items.indexOf(m.displayName) > -1 && m;
|
||||
PluginStores.contextChunkObserver[type].modules = BDFDB.ModuleUtils.find(PluginStores.contextChunkObserver[type].filter, {all: true});
|
||||
}
|
||||
}
|
||||
|
@ -8386,7 +8418,7 @@ module.exports = (_ => {
|
|||
InternalBDFDB.addQueuePatches(BDFDB);
|
||||
InternalBDFDB.addContextChunkObservers(BDFDB);
|
||||
|
||||
for (let type of QueuedComponents) if (!PluginStores.patchQueues[type]) PluginStores.patchQueues[type] = {query: [], modules: []};
|
||||
if (InternalData.ModuleUtilsConfig.QueuedComponents) for (let type of InternalData.ModuleUtilsConfig.QueuedComponents) if (!PluginStores.patchQueues[type]) PluginStores.patchQueues[type] = {query: [], modules: []};
|
||||
|
||||
BDFDB.PatchUtils.patch(BDFDB, BDFDB.ObjectUtils.get(BDFDB.ModuleUtils.findByString("renderReactions", "canAddNewReactions", "showMoreUtilities", false), "exports.default"), "type", {after: e => {
|
||||
if (document.querySelector(BDFDB.dotCN.emojipicker) || !BDFDB.ObjectUtils.toArray(PluginStores.loaded).filter(p => p.started).some(p => p.onSystemMessageOptionContextMenu || p.onSystemMessageOptionToolbar || p.onMessageOptionContextMenu || p.onMessageOptionToolbar)) return;
|
||||
|
@ -8797,6 +8829,26 @@ module.exports = (_ => {
|
|||
if (pluginName) BDFDB.TimeUtils.timeout(_ => BDFDB.BDUtils.reloadPlugin(pluginName));
|
||||
}
|
||||
};
|
||||
|
||||
const alreadyLoadedComponents = [];
|
||||
if (InternalData.ForceLoadedComponents) {
|
||||
let promises = [];
|
||||
for (let name in InternalData.ForceLoadedComponents) {
|
||||
let parentModule;
|
||||
if (InternalData.ForceLoadedComponents[name].name) {
|
||||
if (InternalData.ForceLoadedComponents[name].protos) parentModule = BDFDB.ModuleUtils.find(m => m && m.displayName == InternalData.ForceLoadedComponents[name].name && m.prototype && InternalData.ForceLoadedComponents[name].protos.every(proto => m.prototype[proto]) && m, {useExport: false});
|
||||
else parentModule = BDFDB.ModuleUtils.findByName(InternalData.ForceLoadedComponents[name].name, false, true);
|
||||
}
|
||||
else if (InternalData.ForceLoadedComponents[name].props) parentModule = BDFDB.ModuleUtils.findByProperties(InternalData.ForceLoadedComponents[name].props, false, true);
|
||||
if (parentModule && parentModule.exports && alreadyLoadedComponents.indexOf(parentModule.id) > -1) {
|
||||
alreadyLoadedComponents.push(parentModule.id);
|
||||
promises.push(InternalBDFDB.lazyLoadModuleImports(parentModule.exports));
|
||||
}
|
||||
}
|
||||
Promise.all(promises).then(loadComponents);
|
||||
}
|
||||
else loadComponents();
|
||||
};
|
||||
requestLibraryHashes(true);
|
||||
|
||||
return class BDFDB_Frame {
|
||||
|
@ -8895,7 +8947,7 @@ module.exports = (_ => {
|
|||
let toastInterval, toast = BDFDB.NotificationUtils.toast(loadingString, {
|
||||
type: "info",
|
||||
timeout: 0,
|
||||
onClose: _ => {BDFDB.TimeUtils.clear(toastInterval);}
|
||||
onClose: _ => BDFDB.TimeUtils.clear(toastInterval)
|
||||
});
|
||||
toastInterval = BDFDB.TimeUtils.interval(_ => {
|
||||
currentLoadingString = currentLoadingString.endsWith(".....") ? loadingString : currentLoadingString + ".";
|
||||
|
|
Loading…
Reference in New Issue