Оформить тему в разделе «Последние» на мобильном

Я работаю над компонентом темы, который блокирует сообщения, содержащие ключевое слово из пользовательского поля. Мне удалось настроить скрытие ответов, а также тем при отображении в разделах «Последние» или «Топ» на десктопной версии, но при просмотре в приложении или на мобильном устройстве появляется уведомление о том, что тема заблокирована, однако класс blocked не применяется к контенту. Блокировка ответов внутри темы работает корректно как на мобильном, так и в приложении.

Просмотрев компоненты, я не обнаружил, что для мобильной версии используется другой файл .hbs. Не упускаю ли я что-то ещё?

const discourseComputed = require("discourse-common/utils/decorators").default;

function addIgnoredTopicClass() {
    if (currentUser) {
        api.container.lookup('store:main').find('user', currentUser.username).then((user) => {
            const blocklist = user.user_fields[1];
            const case_sensitive = user.user_fields[2];
            const whole_words = user.user_fields[3];
    
            const blocked = blocklist.split(",").map(function(item) {
                if (case_sensitive) {
                    return item.trim();
                } else {
                    return item.trim().toLowerCase();
                }
            });
            let classList = this._super(...arguments);
            let elem = document.querySelectorAll("[data-topic-id='" + this.topic.id.toString() + "']")[0];
            console.log(elem);
            const title = (case_sensitive) ? this.topic.fancy_title : this.topic.fancy_title.toLowerCase();
            const excerpt = (case_sensitive) ? this.topic.excerpt : this.topic.excerpt.toLowerCase();
            let result = "";
            
            for (let index = 0; index < blocked.length; ++index) {
                    let pattern = (whole_words) ? new RegExp('(?:\\b|\\s|^)' + blocked[index] + '(?:\\b|\\s|$)') : new RegExp(blocked[index]);
                    // console.log(pattern)
                    if (pattern.test(title)) {
                        classList += "blocker-blocked"
                        const found = blocked.filter(text => title.includes(text));
                        if (found.length >= 2) {
                            const last = found.pop();
                            result = found.join(', ') + ' and ' + last;
                        } else {
                            result = found.join(', ');
                        }
                        const newNode = document.createElement("a");
                        const textNode = document.createTextNode("Blocked for containing " + result + ".");
                        newNode.classList.add("block-notice")
                        newNode.appendChild(textNode);
                        newNode.onclick = function() { showComment(this); };
                        elem.children[0].insertBefore(newNode, elem.children[0].children[0]);
                        for (let index = 0; index < elem.children.length; ++index) {
                            if (elem.children[index].classList.contains('main-link')) {
                                elem.children[index].classList.add("blocker-blocked");
                            }
                        }
                        newNode.classList.remove("blocker-blocked");
                    }
                }
            
            // console.log(classList);
            return classList;
        });
    }
}

api.modifyClass("component:topic-list-item", {
    @discourseComputed()
    unboundClassNames() {
        return addIgnoredTopicClass.call(this);
    }
});
    
api.modifyClass("component:latest-topic-list-item", {
    
    @discourseComputed()
    unboundClassNames() {
        return addIgnoredTopicClass.call(this);
    }
});

Или, по крайней мере, я думал, что у меня это работает. Я переключился на другую задачу на время, а теперь это снова не работает :thinking: Может быть, это связано с этой проблемой в api.modifyClass?

Из чистого любопытства, чем это отличается от встроенной функции Следящиеся слова?

Насколько я понимаю, «Слежение за словами» — это настройка администратора, которая применяется ко всем пользователям, верно? Я пытаюсь реализовать возможность для пользователей иметь собственный фильтр «слежения за словами», который мог бы скрывать сообщения, соответствующие правилам форума, но которые пользователь по каким-то личным причинам не хочет видеть.

Вымышленный сценарий: на форуме о домашних животных может быть общая тема о борьбе с шерстью животных, где основная тема не помечена конкретным видом животного. Пользователь А отвечает о своей собаке, пользователь Б — о своей кошке, но пользователь А не хочет видеть ничего о кошках. Этот компонент темы позволяет пользователю А добавить слово «кошка» в свой список блокировок, после чего любое появление этого слова в теме или ответе заменяется на «Заблокировано: содержит упоминание кошек», с возможностью нажать, чтобы показать содержимое.

Это предназначено для тем, которые соответствуют тематике и правилам форума в целом, но которые могут не быть помечены или появляться в ответах в теме, помеченной тем, что пользователь А хочет видеть. Форум, который я переносил, использовал небольшой скрипт для браузера, сканирующий страницу после загрузки, и одним из преимуществ Discourse была возможность встроить функцию блокировки прямо в систему, чтобы она работала и на мобильных устройствах (используемый нами скрипт не работает в мобильных браузерах). Это сокращает количество жалоб и споров о том, что должно быть в общих темах, если пользователи могут просто решить, что не хотят видеть X, без нарушения правил.

Я не думаю, что опубликую это как полноценный компонент темы, так как для этого требуется создать три пользовательских поля в панели администратора (что, как мне кажется, потребует создания плагина для автоматического создания). Я нахожусь на базовом тарифном плане и не хочу возиться с плагинами, но могу опубликовать готовый код компонента темы и настройки пользовательских полей, когда закончу.

Звучит отлично. :slight_smile: Я могу вспомнить несколько форумов, которым это было бы полезно.

Да, вижу потенциал. Возможно, даже использовать модифицированную версию для расширения функции «заглушить пользователя». У меня один пользователь жалуется :man_facepalming:, что он всё ещё видит ответы других людей тем, кого он заглушил. lol

Много интересного потенциала. Буду следить за вашим проектом.
:vulcan_salute::smiling_face_with_sunglasses::+1:

Как мне найти, в чём проблема? В режиме эмуляции мобильных устройств через инструменты разработчика Chrome всё работает корректно, но в Chrome на реальном телефоне и в приложении для Android — нет. При использовании компонента темы Plugin Outlets подходящего выхода (outlet) не видно, так как я пытаюсь внести изменения непосредственно внутри элемента topic-list-item.

Извините, если вопрос слишком простой, это мой первый опыт работы с Ember.

У меня это заработало на мобильных устройствах, и я опубликую в #theme-component, как только получу одобрение на вступление. Проблема с мобильной версией заключалась в том, что я добавлял класс к дочернему элементу topic-list, у которого был класс “main-link”, но на мобильных устройствах этот дочерний элемент main-link находится на несколько уровней ниже в иерархии, чем на десктопе.