3 * @copyright Copyright (C) 2020, Friendica
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Module\Settings;
24 use Friendica\Core\Hook;
25 use Friendica\Core\Renderer;
26 use Friendica\Core\Session;
27 use Friendica\Core\Theme;
28 use Friendica\Database\DBA;
30 use Friendica\Module\BaseSettings;
31 use Friendica\Network\HTTPException;
32 use Friendica\Util\Strings;
35 * Module to update user settings
37 class Display extends BaseSettings
39 public static function post(array $parameters = [])
41 if (!local_user() || !empty(DI::app()->user['uid']) && DI::app()->user['uid'] != local_user()) {
42 throw new HTTPException\ForbiddenException(DI::l10n()->t('Permission denied.'));
45 self::checkFormSecurityTokenRedirectOnError('/settings/display', 'settings_display');
47 $theme = !empty($_POST['theme']) ? Strings::escapeTags(trim($_POST['theme'])) : DI::app()->user['theme'];
48 $mobile_theme = !empty($_POST['mobile_theme']) ? Strings::escapeTags(trim($_POST['mobile_theme'])) : '';
49 $nosmile = !empty($_POST['nosmile']) ? intval($_POST['nosmile']) : 0;
50 $first_day_of_week = !empty($_POST['first_day_of_week']) ? intval($_POST['first_day_of_week']) : 0;
51 $infinite_scroll = !empty($_POST['infinite_scroll']) ? intval($_POST['infinite_scroll']) : 0;
52 $no_auto_update = !empty($_POST['no_auto_update']) ? intval($_POST['no_auto_update']) : 0;
53 $no_smart_threading = !empty($_POST['no_smart_threading']) ? intval($_POST['no_smart_threading']) : 0;
54 $browser_update = !empty($_POST['browser_update']) ? intval($_POST['browser_update']) : 0;
55 if ($browser_update != -1) {
56 $browser_update = $browser_update * 1000;
57 if ($browser_update < 10000) {
58 $browser_update = 10000;
62 $itemspage_network = !empty($_POST['itemspage_network']) ?
63 intval($_POST['itemspage_network']) :
64 DI::config()->get('system', 'itemspage_network');
65 if ($itemspage_network > 100) {
66 $itemspage_network = 100;
68 $itemspage_mobile_network = !empty($_POST['itemspage_mobile_network']) ?
69 intval($_POST['itemspage_mobile_network']) :
70 DI::config()->get('system', 'itemspage_network_mobile');
71 if ($itemspage_mobile_network > 100) {
72 $itemspage_mobile_network = 100;
75 if ($mobile_theme !== '') {
76 DI::pConfig()->set(local_user(), 'system', 'mobile_theme', $mobile_theme);
79 DI::pConfig()->set(local_user(), 'system', 'itemspage_network' , $itemspage_network);
80 DI::pConfig()->set(local_user(), 'system', 'itemspage_mobile_network', $itemspage_mobile_network);
81 DI::pConfig()->set(local_user(), 'system', 'update_interval' , $browser_update);
82 DI::pConfig()->set(local_user(), 'system', 'no_auto_update' , $no_auto_update);
83 DI::pConfig()->set(local_user(), 'system', 'no_smilies' , $nosmile);
84 DI::pConfig()->set(local_user(), 'system', 'infinite_scroll' , $infinite_scroll);
85 DI::pConfig()->set(local_user(), 'system', 'no_smart_threading' , $no_smart_threading);
86 DI::pConfig()->set(local_user(), 'system', 'first_day_of_week' , $first_day_of_week);
88 if (in_array($theme, Theme::getAllowedList())) {
89 if ($theme == DI::app()->user['theme']) {
90 // call theme_post only if theme has not been changed
91 if (($themeconfigfile = Theme::getConfigFile($theme)) !== null) {
92 require_once $themeconfigfile;
93 theme_post(DI::app());
96 DBA::update('user', ['theme' => $theme], ['uid' => local_user()]);
99 notice(DI::l10n()->t('The theme you chose isn\'t available.'));
102 Hook::callAll('display_settings_post', $_POST);
104 DI::baseUrl()->redirect('settings/display');
107 public static function content(array $parameters = [])
109 parent::content($parameters);
112 throw new HTTPException\ForbiddenException(DI::l10n()->t('Permission denied.'));
115 $default_theme = DI::config()->get('system', 'theme');
116 if (!$default_theme) {
117 $default_theme = 'default';
120 $default_mobile_theme = DI::config()->get('system', 'mobile-theme');
121 if (!$default_mobile_theme) {
122 $default_mobile_theme = 'none';
125 $allowed_themes = Theme::getAllowedList();
128 $mobile_themes = ["---" => DI::l10n()->t('No special theme for mobile devices')];
129 foreach ($allowed_themes as $theme) {
130 $is_experimental = file_exists('view/theme/' . $theme . '/experimental');
131 $is_unsupported = file_exists('view/theme/' . $theme . '/unsupported');
132 $is_mobile = file_exists('view/theme/' . $theme . '/mobile');
133 if (!$is_experimental || (DI::config()->get('experimentals', 'exp_themes') || is_null(DI::config()->get('experimentals', 'exp_themes')))) {
134 $theme_name = ucfirst($theme);
135 if ($is_unsupported) {
136 $theme_name = DI::l10n()->t('%s - (Unsupported)', $theme_name);
137 } elseif ($is_experimental) {
138 $theme_name = DI::l10n()->t('%s - (Experimental)', $theme_name);
142 $mobile_themes[$theme] = $theme_name;
144 $themes[$theme] = $theme_name;
149 $theme_selected = DI::app()->user['theme'] ?: $default_theme;
150 $mobile_theme_selected = Session::get('mobile-theme', $default_mobile_theme);
152 $itemspage_network = intval(DI::pConfig()->get(local_user(), 'system', 'itemspage_network'));
153 $itemspage_network = (($itemspage_network > 0 && $itemspage_network < 101) ? $itemspage_network : DI::config()->get('system', 'itemspage_network'));
154 $itemspage_mobile_network = intval(DI::pConfig()->get(local_user(), 'system', 'itemspage_mobile_network'));
155 $itemspage_mobile_network = (($itemspage_mobile_network > 0 && $itemspage_mobile_network < 101) ? $itemspage_mobile_network : DI::config()->get('system', 'itemspage_network_mobile'));
157 $browser_update = intval(DI::pConfig()->get(local_user(), 'system', 'update_interval'));
158 if (intval($browser_update) != -1) {
159 $browser_update = (($browser_update == 0) ? 40 : $browser_update / 1000); // default if not set: 40 seconds
162 $no_auto_update = DI::pConfig()->get(local_user(), 'system', 'no_auto_update', 0);
163 $nosmile = DI::pConfig()->get(local_user(), 'system', 'no_smilies', 0);
164 $infinite_scroll = DI::pConfig()->get(local_user(), 'system', 'infinite_scroll', 0);
165 $no_smart_threading = DI::pConfig()->get(local_user(), 'system', 'no_smart_threading', 0);
167 $first_day_of_week = DI::pConfig()->get(local_user(), 'system', 'first_day_of_week', 0);
168 $weekdays = [0 => DI::l10n()->t("Sunday"), 1 => DI::l10n()->t("Monday")];
171 if ($themeconfigfile = Theme::getConfigFile($theme_selected)) {
172 require_once $themeconfigfile;
173 $theme_config = theme_content(DI::app());
176 $tpl = Renderer::getMarkupTemplate('settings/display.tpl');
177 $o = Renderer::replaceMacros($tpl, [
178 '$ptitle' => DI::l10n()->t('Display Settings'),
179 '$submit' => DI::l10n()->t('Save Settings'),
180 '$d_tset' => DI::l10n()->t('General Theme Settings'),
181 '$d_ctset' => DI::l10n()->t('Custom Theme Settings'),
182 '$d_cset' => DI::l10n()->t('Content Settings'),
183 '$stitle' => DI::l10n()->t('Theme settings'),
184 '$calendar_title' => DI::l10n()->t('Calendar'),
186 '$form_security_token' => self::getFormSecurityToken('settings_display'),
187 '$baseurl' => DI::baseUrl()->get(true),
188 '$uid' => local_user(),
190 '$theme' => ['theme', DI::l10n()->t('Display Theme:'), $theme_selected, '', $themes, true],
191 '$mobile_theme' => ['mobile_theme', DI::l10n()->t('Mobile Theme:'), $mobile_theme_selected, '', $mobile_themes, false],
192 '$theme_config' => $theme_config,
194 '$itemspage_network' => ['itemspage_network' , DI::l10n()->t('Number of items to display per page:'), $itemspage_network, DI::l10n()->t('Maximum of 100 items')],
195 '$itemspage_mobile_network' => ['itemspage_mobile_network', DI::l10n()->t('Number of items to display per page when viewed from mobile device:'), $itemspage_mobile_network, DI::l10n()->t('Maximum of 100 items')],
196 '$ajaxint' => ['browser_update' , DI::l10n()->t('Update browser every xx seconds'), $browser_update, DI::l10n()->t('Minimum of 10 seconds. Enter -1 to disable it.')],
197 '$no_auto_update' => ['no_auto_update' , DI::l10n()->t('Automatic updates only at the top of the network page'), $no_auto_update, DI::l10n()->t('When disabled, the network page is updated all the time, which could be confusing while reading.')],
198 '$nosmile' => ['nosmile' , DI::l10n()->t('Don\'t show emoticons'), $nosmile, DI::l10n()->t('Normally emoticons are replaced with matching symbols. This setting disables this behaviour.')],
199 '$infinite_scroll' => ['infinite_scroll' , DI::l10n()->t('Infinite scroll'), $infinite_scroll, DI::l10n()->t('Automatic fetch new items when reaching the page end.')],
200 '$no_smart_threading' => ['no_smart_threading' , DI::l10n()->t('Disable Smart Threading'), $no_smart_threading, DI::l10n()->t('Disable the automatic suppression of extraneous thread indentation.')],
202 '$first_day_of_week' => ['first_day_of_week', DI::l10n()->t('Beginning of week:'), $first_day_of_week, '', $weekdays, false],