Другая тема для списка тем личных сообщений?

Привет, есть ли способ использовать другую тему только для списка тем личных сообщений? В данный момент я использую тему Сэма Sam's Simple Theme, которую я и мое сообщество очень предпочитаем для списка /latest, так как она отображает имена автора оригинального поста и последнего участника в виде текста, а также убирает визуальный шум в виде списка аватаров активных участников, который никому не нужен. К сожалению, тот же подход не работает для списка /my/messages, особенно когда создатель темы личных сообщений совпадает с последним участником:

image

Поэтому для раздела /my/messages в идеале я хотел бы просто внедрить колонку td.posters.topic-list-data из темы Discourse по умолчанию в этот вид. Но если это слишком сложно, было бы неплохо иметь возможность переключаться на тему Discourse по умолчанию для просмотра личных сообщений.

Эта же проблема наблюдается и в других пользовательских темах, например, в теме Криса Minima Theme.

Привет :wave:

Это возможно, если переопределить тему, поэтому сначала нужно сделать её форк или создать запрос к теме. В пользовательском шаблоне вы можете использовать следующий код, чтобы изменить только элементы списка тем личных сообщений.

{{#if topic.isPrivateMessage}}
...
{{/if}}

Скрыть что-либо в элементе списка тем личных сообщений.

{{#unless topic.isPrivateMessage}}
...
{{/unless}}

Большое спасибо, мне удалось почти всё настроить с помощью компонента темы:

<script type='text/x-handlebars' data-template-name='topic-list-header.raw'>
    <tr class="topic-list-header-row">
      {{~raw-plugin-outlet name="topic-list-header-before"~}}
      {{#if bulkSelectEnabled}}
        <div class="bulk-select">
          {{#if canBulkSelect}}
            {{raw "flat-button" class="bulk-select" icon="list" title="topics.bulk.toggle"}}
          {{/if}}
        </div>
      {{/if}}
      {{raw "topic-list-header-column" order='default' name='topic.title' bulkSelectEnabled=bulkSelectEnabled showBulkToggle=toggleInTitle canBulkSelect=canBulkSelect}}
      {{#if showLikes}}
          {{raw "topic-list-header-column" sortable='true' order='likes' number='true' forceName=(theme-i18n 'likes')}}
      {{/if}}
      {{#if showOpLikes}}
          {{raw "topic-list-header-column" sortable='true' order='op_likes' number='true' forceName=(theme-i18n 'likes')}}
      {{/if}}
      {{#if topic.isPrivateMessage}}
          {{raw "topic-list-header-column" order='posters' forceName='Participants'}}
      {{/if}}
      {{raw "topic-list-header-column" sortable='true' number='true' order='posts' forceName='Replies'}}
      {{raw "topic-list-header-column" sortable='true' order='activity' forceName='Last Post'}}
    </tr>
</script>


<script type='text/x-handlebars' data-template-name='list/topic-list-item.raw'>
    {{#if bulkSelectEnabled}}
      <td class="bulk-select topic-list-data">
        <label for="bulk-select-{{topic.id}}">
          <input type="checkbox" class="bulk-select" id="bulk-select-{{topic.id}}">
        </label>
      </td>
    {{/if}}
    
    <td class='main-link clearfix topic-list-data'>
      {{~raw-plugin-outlet name="topic-list-before-status"}}
      {{raw "topic-status" topic=topic}}
      {{~topic-link topic class="raw-link raw-topic-link"}}
      {{~#if showTopicPostBadges}}
        {{~raw "topic-post-badges" unreadPosts=topic.unread_posts unseen=topic.unseen url=topic.lastUnreadUrl newDotText=newDotText}}
      {{~/if}}
      {{discourse-tags topic mode="list" tagsForUser=tagsForUser}}
      {{#if expandPinned}}
        {{raw "list/topic-excerpt" topic=topic}}
      {{/if}}
      <div class='creator'>
        {{#unless hideCategory}}
          {{#unless topic.isPinnedUncategorized}}
            {{category-link topic.category}}
          {{/unless}}
        {{/unless}}
        {{~#if topic.creator ~}}
          <a href="/u/{{topic.creator.username}}" data-auto-route="true" data-user-card="{{topic.creator.username}}">{{topic.creator.username}}</a> <a href={{topic.url}}>{{format-date topic.createdAt format="tiny"}}</a>
        {{~/if ~}}
        {{raw "list/action-list" topic=topic postNumbers=topic.liked_post_numbers className="likes" icon="heart"}}
      </div>
    </td>
    
    {{#if showLikes}}
      <td class="num likes topic-list-data">
        {{#if hasLikes}}
          <a href='{{topic.summaryUrl}}'>
            {{number topic.like_count}} {{d-icon "heart"}}
          </a>
        {{/if}}
      </td>
    {{/if}}
    
    {{#if showOpLikes}}
      <td class="num likes topic-list-data">
        {{#if hasOpLikes}}
          <a href='{{topic.summaryUrl}}'>
            {{number topic.op_like_count}} {{d-icon "heart"}}
          </a>
        {{/if}}
      </td>
    {{/if}}
    
    {{#if topic.isPrivateMessage}}
      {{raw "list/posters-column" posters=topic.featuredUsers}}
    {{/if}}
    
    {{raw "list/posts-count-column" topic=topic}}
    
    <td class="last-post topic-list-data">
      <div class='poster-avatar'>
        <a href="{{topic.lastPostUrl}}" data-user-card="{{topic.last_poster_username}}">{{avatar topic.lastPosterUser imageSize="medium"}}</a>
      </div>
      <div class='poster-info'>
        <a href="{{topic.lastPostUrl}}">
          {{format-date topic.bumpedAt format="tiny"}}
        </a>
        <span class='editor'><a href="/u/{{topic.last_poster_username}}" data-auto-route="true" data-user-card="{{topic.last_poster_username}}">{{topic.last_poster_username}}</a></span>
      </div>
    </td>
</script>

Похоже, что условие #if topic.isPrivateMessage не работает для topic-list-header, поэтому аватары участников личных сообщений отображаются как ожидалось, но в заголовках отсутствует тег <td>, из-за чего всё смещается.

Поэтому моё ленивое решение — не использовать логику {{#if topic.isPrivateMessage}}, а просто добавить posters.topic-list-data и в /latest, и в /my/messages.

<script type='text/x-handlebars' data-template-name='topic-list-header.raw'>
<tr class="topic-list-header-row">
  {{~raw-plugin-outlet name="topic-list-header-before"~}}

{{#if bulkSelectEnabled}}
  <th class="bulk-select topic-list-data">
    {{#if canBulkSelect}}
      {{raw "flat-button" class="bulk-select" icon="list" title="topics.bulk.toggle"}}
    {{/if}}
  </th>
{{/if}}
{{raw "topic-list-header-column" order='default' name=listTitle bulkSelectEnabled=bulkSelectEnabled showBulkToggle=toggleInTitle canBulkSelect=canBulkSelect canDoBulkActions=canDoBulkActions showTopicsAndRepliesToggle=showTopicsAndRepliesToggle newListSubset=newListSubset newRepliesCount=newRepliesCount newTopicsCount=newTopicsCount}}

{{#if showPosters}}
  {{raw "topic-list-header-column" order='posters' forceName='Participants'}}
{{/if}}
  {{#if showLikes}}
      {{raw "topic-list-header-column" sortable='true' order='likes' number='true' forceName='thanks'}}
  {{/if}}
  {{#if showOpLikes}}
      {{raw "topic-list-header-column" sortable='true' order='op_likes' number='true' forceName='thanks'}}
  {{/if}}
  {{raw "topic-list-header-column" sortable='true' number='true' order='posts' forceName='Replies'}}
  {{raw "topic-list-header-column" sortable='true' order='activity' forceName='Last Post'}}
</tr>
</script>



<script type='text/x-handlebars' data-template-name='list/topic-list-item.raw'>
{{~raw-plugin-outlet name="topic-list-before-columns"}}

{{#if bulkSelectEnabled}}
  <td class="bulk-select topic-list-data">
    <label for="bulk-select-{{topic.id}}">
      <input type="checkbox" class="bulk-select" id="bulk-select-{{topic.id}}">
    </label>
  </td>
{{/if}}

<td class='main-link clearfix topic-list-data'>
  {{~raw-plugin-outlet name="topic-list-before-status"}}
  {{raw "topic-status" topic=topic}}
  {{~topic-link topic class="raw-link raw-topic-link"}}
  {{~#if showTopicPostBadges}}
    {{~raw "topic-post-badges" unreadPosts=topic.unread_posts unseen=topic.unseen url=topic.lastUnreadUrl newDotText=newDotText}}
  {{~/if}}
  {{discourse-tags topic mode="list" tagsForUser=tagsForUser}}
  {{#if expandPinned}}
    {{raw "list/topic-excerpt" topic=topic}}
  {{/if}}
  <div class='creator'>
    {{#unless hideCategory}}
      {{#unless topic.isPinnedUncategorized}}
        {{category-link topic.category}}
      {{/unless}}
    {{/unless}}
    {{~#if topic.creator ~}}
      <a href="/u/{{topic.creator.username}}" data-auto-route="true" data-user-card="{{topic.creator.username}}">{{topic.creator.username}}</a> <a href={{topic.url}}>{{format-date topic.createdAt format="tiny"}}</a>
    {{~/if ~}}
    {{raw "list/action-list" topic=topic postNumbers=topic.liked_post_numbers className="likes" icon="heart"}}
  </div>
</td>

{{#if showPosters}}
  {{raw "list/posters-column" posters=topic.featuredUsers}}
{{/if}}

{{#if showLikes}}
  <td class="num likes topic-list-data">
    {{#if hasLikes}}
      <a href='{{topic.summaryUrl}}'>
        {{number topic.like_count}} {{d-icon "heart"}}
      </a>
    {{/if}}
  </td>
{{/if}}

{{#if showOpLikes}}
  <td class="num likes topic-list-data">
    {{#if hasOpLikes}}
      <a href='{{topic.summaryUrl}}'>
        {{number topic.op_like_count}} {{d-icon "heart"}}
      </a>
    {{/if}}
  </td>
{{/if}}

{{raw "list/posts-count-column" topic=topic}}

<td class="last-post topic-list-data">
  <div class='poster-avatar'>
    <a href="{{topic.lastPostUrl}}" data-user-card="{{topic.last_poster_username}}">{{avatar topic.lastPosterUser imageSize="medium"}}</a>
  </div>
  <div class='poster-info'>
    <a href="{{topic.lastPostUrl}}">
      {{format-date topic.bumpedAt format="tiny"}}
    </a>
    <span class='editor'><a href="/u/{{topic.last_poster_username}}" data-auto-route="true" data-user-card="{{topic.last_poster_username}}">{{topic.last_poster_username}}</a></span>
  </div>
</td>

</script>

Однако мои пользователи не любят визуальный шум в /latest, поэтому я скрываю его там через CSS:

.navigation-topics .topic-list .topic-list-data.posters {
    display: none;
}

Если у кого-то есть советы по реализации логики в переопределении Handlebars, я всё же предпочту такой вариант, чем тратить циклы процессора на генерацию posters.topic-list-data и последующее его скрытие.

Вы правы; данные о теме недоступны в заголовке, что логично!

CSS может стать решением. Оставьте условие в topic-list-item и по умолчанию отобразите его в заголовке.

{{raw "topic-list-header-column" order='posters' forceName='Участники'}}

А с помощью CSS можно сказать: «Выберите список, у которого нет (не имеет) строк с постерами, и скройте его».

.topic-list:not(:has(.topic-list-body .topic-list-data.posters))
  .topic-list-header
  .topic-list-data.posters {
  display: none;
}

Сработает ли это у вас?

Привет, большое спасибо, это отличная идея. Что-то не сработало с CSS, как было предложено, так как пустой столбец Участники всё ещё отображается в /latest, но мой исходный CSS, похоже, работает отлично, скрывая его только там:

.navigation-topics .topic-list .topic-list-data.posters {
    display: none;
}

Есть ли у этого какие-либо недостатки?

Я в замешательстве, у меня всё работает :thinking:

Последнее:

Сообщение:

Хм, может быть, потому что у вас нет условия в topic-list-item?

У меня действительно есть это условие. Иначе вы бы не увидели столбец «Участники» в списке сообщений на моих скриншотах!

Думаю, описанное вами выше — это проблема с неприменением CSS.
Вот что у меня есть:

Вы можете видеть, что CSS применён на странице /latest.

Убедитесь, что вы правильно скопировали и вставили CSS в нужное место!

Большое спасибо за конкретную помощь. Прямо сейчас я не за компьютером, но как только вернусь, попробую снова.

Не знаю, что и думать, у меня это точно не работает.

Подтвердите, пожалуйста, вы тоже используете простую тему Сэма?

Также, вы разместили код Handlebars в разделе Head или Header?

Большое спасибо за ваше время и помощь.

Да, я использую тему Сэма.

Я создал компонент темы, чтобы разместить там CSS и скрипт, и привязал его к теме Сэма.

CSS
.topic-list:not(:has(.topic-list-body .topic-list-data.posters))
  .topic-list-header-row
  .topic-list-data.posters {
  display: none;
}
Head
<script type='text/x-handlebars' data-template-name='topic-list-header.raw'>
    <tr class="topic-list-header-row">
      {{~raw-plugin-outlet name="topic-list-header-before"~}}
      {{#if bulkSelectEnabled}}
        <div class="bulk-select">
          {{#if canBulkSelect}}
            {{raw "flat-button" class="bulk-select" icon="list" title="topics.bulk.toggle"}}
          {{/if}}
        </div>
      {{/if}}
      {{raw "topic-list-header-column" order='default' name='topic.title' bulkSelectEnabled=bulkSelectEnabled showBulkToggle=toggleInTitle canBulkSelect=canBulkSelect}}
      {{#if showLikes}}
          {{raw "topic-list-header-column" sortable='true' order='likes' number='true' forceName=(theme-i18n 'likes')}}
      {{/if}}
      {{#if showOpLikes}}
          {{raw "topic-list-header-column" sortable='true' order='op_likes' number='true' forceName=(theme-i18n 'likes')}}
      {{/if}}
      {{raw "topic-list-header-column" order='posters' forceName='Participants'}}
      {{raw "topic-list-header-column" sortable='true' number='true' order='posts' forceName='Replies'}}
      {{raw "topic-list-header-column" sortable='true' order='activity' forceName='Last Post'}}
    </tr>
</script>

<script type='text/x-handlebars' data-template-name='list/topic-list-item.raw'>
    {{#if bulkSelectEnabled}}
      <td class="bulk-select topic-list-data">
        <label for="bulk-select-{{topic.id}}">
          <input type="checkbox" class="bulk-select" id="bulk-select-{{topic.id}}">
        </label>
      </td>
    {{/if}}
    
    <td class='main-link clearfix topic-list-data'>
      {{~raw-plugin-outlet name="topic-list-before-status"}}
      {{raw "topic-status" topic=topic}}
      {{~topic-link topic class="raw-link raw-topic-link"}}
      {{~#if showTopicPostBadges}}
        {{~raw "topic-post-badges" unreadPosts=topic.unread_posts unseen=topic.unseen url=topic.lastUnreadUrl newDotText=newDotText}}
      {{~/if}}
      {{discourse-tags topic mode="list" tagsForUser=tagsForUser}}
      {{#if expandPinned}}
        {{raw "list/topic-excerpt" topic=topic}}
      {{/if}}
      <div class='creator'>
        {{#unless hideCategory}}
          {{#unless topic.isPinnedUncategorized}}
            {{category-link topic.category}}
          {{/unless}}
        {{/unless}}
        {{~#if topic.creator ~}}
          <a href="/u/{{topic.creator.username}}" data-auto-route="true" data-user-card="{{topic.creator.username}}">{{topic.creator.username}}</a> <a href={{topic.url}}>{{format-date topic.createdAt format="tiny"}}</a>
        {{~/if ~}}
        {{raw "list/action-list" topic=topic postNumbers=topic.liked_post_numbers className="likes" icon="heart"}}
      </div>
    </td>
    
    {{#if showLikes}}
      <td class="num likes topic-list-data">
        {{#if hasLikes}}
          <a href='{{topic.summaryUrl}}'>
            {{number topic.like_count}} {{d-icon "heart"}}
          </a>
        {{/if}}
      </td>
    {{/if}}
    
    {{#if showOpLikes}}
      <td class="num likes topic-list-data">
        {{#if hasOpLikes}}
          <a href='{{topic.summaryUrl}}'>
            {{number topic.op_like_count}} {{d-icon "heart"}}
          </a>
        {{/if}}
      </td>
    {{/if}}
    
    {{#if topic.isPrivateMessage}}
      {{raw "list/posters-column" posters=topic.featuredUsers}}
    {{/if}}
    
    {{raw "list/posts-count-column" topic=topic}}
    
    <td class="last-post topic-list-data">
      <div class='poster-avatar'>
        <a href="{{topic.lastPostUrl}}" data-user-card="{{topic.last_poster_username}}">{{avatar topic.lastPosterUser imageSize="medium"}}</a>
      </div>
      <div class='poster-info'>
        <a href="{{topic.lastPostUrl}}">
          {{format-date topic.bumpedAt format="tiny"}}
        </a>
        <span class='editor'><a href="/u/{{topic.last_poster_username}}" data-auto-route="true" data-user-card="{{topic.last_poster_username}}">{{topic.last_poster_username}}</a></span>
      </div>
    </td>
</script>

Спасибо еще раз за помощь. Проблема сохраняется: в /latest есть заголовок столбца Участники, из-за чего столбцы не совпадают со столбцами списка тем. Вероятно, у меня есть другие кастомизации в других компонентах, которые конфликтуют.

Есть ли какие-либо потенциальные проблемы или недостатки у этого CSS-решения?

Как я вижу, вы используете Firefox, поэтому селектор :has может не работать на вашей стороне. Он поддерживается только начиная с версии Firefox 121.

Это всё объясняет! И это работало в Chromium, но я предполагал, что это потому, что я там не был авторизован как администратор. Я использую Firefox 115 ESR из Debian 12. Большое спасибо, я уже сходил с ума от этого. :wink:

О, правда. Я не знал, и, честно говоря, это довольно разочаровывает :sweat_smile:. В следующий раз я обязательно буду чаще тестировать в Firefox. Спасибо за обратную связь!

Я хотел бы внедрить ещё одно улучшение CSS, чтобы сделать это более полезным: на широких окнах браузера теперь, как и ожидалось, отображаются участники личных сообщений:

Однако на узких окнах количество аватарок участников сокращается до одной, и мы сталкиваемся с той же проблемой, о которой говорилось в первом посте этой темы:

Есть ли способ исправить это с помощью CSS, чтобы на узких окнах скрывался столбец Ответы и скрывалась аватарка в столбце Последний пост, тем самым освобождая больше места для столбца Участники?

Попробуйте этот CSS?

@include breakpoint(extra-large, $sidebar: true) {
  .user-messages-page .topic-list {
    .posts {
      display: none;
    }
    
    .posters {
      width: 146px;
      text-align: inherit;
    }
    
    .last-post {
        width: auto;
        
        .poster-avatar {
            display: none;
        }
    }
    
    .topic-list-header .topic-list-data.activity {
      width: auto;
    }
    
    .topic-list-data.posters {
      a:not(.latest) {
        display: inherit;
      }
      
      a.latest {
        width: auto;
      }
    }
  }
}

Спасибо! Почти идеально, за исключением того, что при ширинах примерно от 1380 пикселей до 1020 пикселей по-прежнему отображаются все колонки, а аватары участников сводятся к одной. Уже этой ширины работает отлично.

Замените medium на extra-large в функции breakpoint(). Теперь она должна начинаться с <= 1140px. На самом деле, исходное поведение, скрывающее аватары участников, происходит именно на этой точке останова. Это работает?