Skip to content

Commit d5b0a4f

Browse files
authored
[1.x] feat: add setting to disable sticky pinning on All Discussions page (#4607)
* feat: add setting to control sticky pinning on All Discussions page Adds an admin toggle (default: enabled) that gates unread-only sticky pinning on /all. When disabled, stickied discussions appear at their natural last_posted_at position. Tag pages are unaffected. * feat: add tests for sticky pinning behavior on all when setting is disabled
1 parent 7478f5f commit d5b0a4f

5 files changed

Lines changed: 99 additions & 9 deletions

File tree

extensions/sticky/extend.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@
4949

5050
new Extend\Locales(__DIR__.'/locale'),
5151

52+
(new Extend\Settings())
53+
->default('flarum-sticky.pin_sticky_on_all_discussions', true),
54+
5255
(new Extend\Event())
5356
->listen(Saving::class, SaveStickyToDatabase::class)
5457
->listen(DiscussionWasStickied::class, [Listener\CreatePostWhenDiscussionIsStickied::class, 'whenDiscussionWasStickied'])
Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
import app from 'flarum/admin/app';
22

33
app.initializers.add('flarum-sticky', () => {
4-
app.extensionData.for('flarum-sticky').registerPermission(
5-
{
6-
icon: 'fas fa-thumbtack',
7-
label: app.translator.trans('flarum-sticky.admin.permissions.sticky_discussions_label'),
8-
permission: 'discussion.sticky',
9-
},
10-
'moderate',
11-
95
12-
);
4+
app.extensionData
5+
.for('flarum-sticky')
6+
.registerSetting({
7+
setting: 'flarum-sticky.pin_sticky_on_all_discussions',
8+
label: app.translator.trans('flarum-sticky.admin.settings.pin_sticky_on_all_discussions_label'),
9+
help: app.translator.trans('flarum-sticky.admin.settings.pin_sticky_on_all_discussions_help'),
10+
type: 'boolean',
11+
})
12+
.registerPermission(
13+
{
14+
icon: 'fas fa-thumbtack',
15+
label: app.translator.trans('flarum-sticky.admin.permissions.sticky_discussions_label'),
16+
permission: 'discussion.sticky',
17+
},
18+
'moderate',
19+
95
20+
);
1321
});

extensions/sticky/locale/en.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ flarum-sticky:
1111
permissions:
1212
sticky_discussions_label: Sticky discussions
1313

14+
# These translations are used in the Settings page of the admin interface.
15+
settings:
16+
pin_sticky_on_all_discussions_label: Pin stickied discussions on the All Discussions page
17+
pin_sticky_on_all_discussions_help: When enabled (default), unread stickied discussions are pinned to the top of the All Discussions page. When disabled, stickied discussions appear at their natural position by latest activity. Tag pages always pin stickied discussions to the top regardless of this setting.
18+
1419
# Translations in this namespace are used by the forum user interface.
1520
forum:
1621

extensions/sticky/src/PinStickiedDiscussionsToTop.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,21 @@
1111

1212
use Flarum\Filter\FilterState;
1313
use Flarum\Query\QueryCriteria;
14+
use Flarum\Settings\SettingsRepositoryInterface;
1415
use Flarum\Tags\Query\TagFilterGambit;
1516

1617
class PinStickiedDiscussionsToTop
1718
{
19+
/**
20+
* @var SettingsRepositoryInterface
21+
*/
22+
protected $settings;
23+
24+
public function __construct(SettingsRepositoryInterface $settings)
25+
{
26+
$this->settings = $settings;
27+
}
28+
1829
public function __invoke(FilterState $filterState, QueryCriteria $criteria)
1930
{
2031
if ($criteria->sortIsDefault) {
@@ -36,6 +47,13 @@ public function __invoke(FilterState $filterState, QueryCriteria $criteria)
3647
return;
3748
}
3849

50+
// On "all discussions", admins can disable sticky pinning entirely.
51+
// When disabled, stickied discussions appear at their natural
52+
// last_posted_at position rather than being floated to the top.
53+
if (! $this->settings->get('flarum-sticky.pin_sticky_on_all_discussions', true)) {
54+
return;
55+
}
56+
3957
// Otherwise, if we are viewing "all discussions", only pin stickied
4058
// discussions to the top if they are unread. To do this in a
4159
// performant way we create another query which will select all

extensions/sticky/tests/integration/api/ListDiscussionsTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,60 @@ public function list_discussions_shows_stick_first_on_a_tag()
117117

118118
$this->assertEquals([3, 1, 2, 4], Arr::pluck($data['data'], 'id'));
119119
}
120+
121+
/** @test */
122+
public function list_discussions_does_not_pin_sticky_on_all_when_setting_disabled_as_guest()
123+
{
124+
$this->setting('flarum-sticky.pin_sticky_on_all_discussions', '0');
125+
126+
$response = $this->send(
127+
$this->request('GET', '/api/discussions')
128+
);
129+
130+
$this->assertEquals(200, $response->getStatusCode());
131+
132+
$data = json_decode($response->getBody()->getContents(), true);
133+
134+
$this->assertEquals([2, 4, 3, 1], Arr::pluck($data['data'], 'id'));
135+
}
136+
137+
/** @test */
138+
public function list_discussions_does_not_pin_unread_sticky_on_all_when_setting_disabled_as_user()
139+
{
140+
$this->setting('flarum-sticky.pin_sticky_on_all_discussions', '0');
141+
142+
$response = $this->send(
143+
$this->request('GET', '/api/discussions', [
144+
'authenticatedAs' => 2
145+
])
146+
);
147+
148+
$this->assertEquals(200, $response->getStatusCode());
149+
150+
$data = json_decode($response->getBody()->getContents(), true);
151+
152+
$this->assertEquals([2, 4, 3, 1], Arr::pluck($data['data'], 'id'));
153+
}
154+
155+
/** @test */
156+
public function list_discussions_pins_sticky_on_a_tag_when_setting_disabled()
157+
{
158+
$this->setting('flarum-sticky.pin_sticky_on_all_discussions', '0');
159+
160+
$response = $this->send(
161+
$this->request('GET', '/api/discussions', [
162+
'authenticatedAs' => 3
163+
])->withQueryParams([
164+
'filter' => [
165+
'tag' => 'general'
166+
]
167+
])
168+
);
169+
170+
$this->assertEquals(200, $response->getStatusCode());
171+
172+
$data = json_decode($response->getBody()->getContents(), true);
173+
174+
$this->assertEquals([3, 1, 2, 4], Arr::pluck($data['data'], 'id'));
175+
}
120176
}

0 commit comments

Comments
 (0)