Moved profile background settings out of the users table.
This commit is contained in:
parent
9f5076cc77
commit
31d89a08bf
18 changed files with 285 additions and 234 deletions
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
use Index\Db\DbConnection;
|
||||
use Index\Db\Migration\DbMigration;
|
||||
|
||||
final class CreateProfileBackgroundSettingsTable_20250208_175705 implements DbMigration {
|
||||
public function migrate(DbConnection $conn): void {
|
||||
$conn->execute(<<<SQL
|
||||
CREATE TABLE msz_profile_backgrounds (
|
||||
user_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
bg_attach ENUM('cover','stretch','tile','contain') NOT NULL,
|
||||
bg_blend TINYINT UNSIGNED NOT NULL,
|
||||
bg_slide TINYINT UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (user_id),
|
||||
CONSTRAINT profile_backgrounds_users_foreign
|
||||
FOREIGN KEY (user_id)
|
||||
REFERENCES msz_users (user_id)
|
||||
ON UPDATE CASCADE
|
||||
ON DELETE CASCADE
|
||||
) COLLATE='utf8mb4_bin';
|
||||
SQL);
|
||||
|
||||
$conn->execute(<<<SQL
|
||||
INSERT INTO msz_profile_backgrounds
|
||||
SELECT user_id,
|
||||
CASE (user_background_settings & 0x0F)
|
||||
WHEN 1 THEN 'cover'
|
||||
WHEN 2 THEN 'stretch'
|
||||
WHEN 3 THEN 'tile'
|
||||
WHEN 4 THEN 'contain'
|
||||
END,
|
||||
IF(user_background_settings & 0x10, 1, 0),
|
||||
IF(user_background_settings & 0x20, 1, 0)
|
||||
FROM msz_users
|
||||
WHERE (user_background_settings & 0x0F) BETWEEN 1 AND 4;
|
||||
SQL);
|
||||
|
||||
$conn->execute(<<<SQL
|
||||
ALTER TABLE msz_users
|
||||
DROP COLUMN user_background_settings;
|
||||
SQL);
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ use InvalidArgumentException;
|
|||
use RuntimeException;
|
||||
use Index\ByteFormat;
|
||||
use Misuzu\Parsers\TextFormat;
|
||||
use Misuzu\Profile\ProfileBackgroundAttach;
|
||||
use Misuzu\Users\{User,UsersContext};
|
||||
use Misuzu\Users\Assets\UserAvatarAsset;
|
||||
use Misuzu\Users\Assets\UserBackgroundAsset;
|
||||
|
@ -74,8 +75,9 @@ $canManageWarnings = $viewerPermsUser->check(Perm::U_WARNINGS_MANAGE);
|
|||
$canEdit = !$viewingAsGuest && ((!$isBanned && $viewingOwnProfile) || $viewerInfo->super || (
|
||||
$viewerPermsUser->check(Perm::U_USERS_MANAGE) && ($viewingOwnProfile || $viewerRank > $userRank)
|
||||
));
|
||||
$avatarInfo = new UserAvatarAsset($userInfo);
|
||||
$backgroundInfo = new UserBackgroundAsset($userInfo);
|
||||
$avatarAsset = new UserAvatarAsset($userInfo);
|
||||
$backgroundInfo = $msz->profileCtx->backgrounds->getProfileBackground($userInfo);
|
||||
$backgroundAsset = new UserBackgroundAsset($userInfo, $backgroundInfo);
|
||||
|
||||
if($isEditing) {
|
||||
if(!$canEdit)
|
||||
|
@ -92,7 +94,6 @@ if($isEditing) {
|
|||
|
||||
Template::set([
|
||||
'perms' => $perms,
|
||||
'background_attachments' => UserBackgroundAsset::getAttachmentStringOptions(),
|
||||
'birthdate_info' => $msz->usersCtx->birthdates->getUserBirthdate($userInfo),
|
||||
]);
|
||||
|
||||
|
@ -106,7 +107,7 @@ if($isEditing) {
|
|||
if(!$perms->edit_profile) {
|
||||
$notices[] = 'You\'re not allowed to edit your profile';
|
||||
} else {
|
||||
$profileFieldInfos = iterator_to_array($msz->profileFields->getFields());
|
||||
$profileFieldInfos = iterator_to_array($msz->profileCtx->fields->getFields());
|
||||
$profileFieldsSetInfos = [];
|
||||
$profileFieldsSetValues = [];
|
||||
$profileFieldsRemove = [];
|
||||
|
@ -130,9 +131,9 @@ if($isEditing) {
|
|||
}
|
||||
|
||||
if(!empty($profileFieldsRemove))
|
||||
$msz->profileFields->removeFieldValues($userInfo, $profileFieldsRemove);
|
||||
$msz->profileCtx->fields->removeFieldValues($userInfo, $profileFieldsRemove);
|
||||
if(!empty($profileFieldsSetInfos))
|
||||
$msz->profileFields->setFieldValues($userInfo, $profileFieldsSetInfos, $profileFieldsSetValues);
|
||||
$msz->profileCtx->fields->setFieldValues($userInfo, $profileFieldsSetInfos, $profileFieldsSetValues);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,7 +188,7 @@ if($isEditing) {
|
|||
|
||||
if(!empty($_FILES['avatar'])) {
|
||||
if(!empty($_POST['avatar']['delete'])) {
|
||||
$avatarInfo->delete();
|
||||
$avatarAsset->delete();
|
||||
} else {
|
||||
if(!$perms->edit_avatar) {
|
||||
$notices[] = 'You aren\'t allow to change your avatar.';
|
||||
|
@ -204,7 +205,7 @@ if($isEditing) {
|
|||
break;
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
$notices[] = sprintf('Your avatar is not allowed to be larger in file size than %s!', ByteFormat::format($avatarInfo->getMaxBytes()));
|
||||
$notices[] = sprintf('Your avatar is not allowed to be larger in file size than %s!', ByteFormat::format($avatarAsset->getMaxBytes()));
|
||||
break;
|
||||
default:
|
||||
$notices[] = 'Unable to save your avatar, contact an administator!';
|
||||
|
@ -212,14 +213,14 @@ if($isEditing) {
|
|||
}
|
||||
} else {
|
||||
try {
|
||||
$avatarInfo->setFromPath($_FILES['avatar']['tmp_name']['file']);
|
||||
$avatarAsset->setFromPath($_FILES['avatar']['tmp_name']['file']);
|
||||
} catch(InvalidArgumentException $ex) {
|
||||
$exMessage = $ex->getMessage();
|
||||
$notices[] = match($exMessage) {
|
||||
'$path is not a valid image.' => 'The file you uploaded was not an image!',
|
||||
'$path is not an allowed image file.' => 'This type of image is not supported, keep to PNG, JPG or GIF!',
|
||||
'Dimensions of $path are too large.' => sprintf('Your avatar can\'t be larger than %dx%d!', $avatarInfo->getMaxWidth(), $avatarInfo->getMaxHeight()),
|
||||
'File size of $path is too large.' => sprintf('Your avatar is not allowed to be larger in file size than %s!', ByteFormat::format($avatarInfo->getMaxBytes())),
|
||||
'Dimensions of $path are too large.' => sprintf('Your avatar can\'t be larger than %dx%d!', $avatarAsset->getMaxWidth(), $avatarAsset->getMaxHeight()),
|
||||
'File size of $path is too large.' => sprintf('Your avatar is not allowed to be larger in file size than %s!', ByteFormat::format($avatarAsset->getMaxBytes())),
|
||||
default => $exMessage,
|
||||
};
|
||||
} catch(RuntimeException $ex) {
|
||||
|
@ -230,16 +231,20 @@ if($isEditing) {
|
|||
}
|
||||
}
|
||||
|
||||
if(!empty($_FILES['background'])) {
|
||||
if((int)($_POST['background']['attach'] ?? -1) === 0) {
|
||||
$backgroundInfo->delete();
|
||||
if(filter_has_var(INPUT_POST, 'bg_attach')) {
|
||||
$bgFormat = ProfileBackgroundAttach::tryFrom((string)filter_input(INPUT_POST, 'bg_attach'));
|
||||
|
||||
if($bgFormat === null) {
|
||||
$backgroundAsset->delete();
|
||||
$msz->profileCtx->backgrounds->deleteProfileBackground($userInfo);
|
||||
$backgroundAsset = null;
|
||||
} else {
|
||||
if(!$perms->edit_background) {
|
||||
$notices[] = 'You aren\'t allow to change your background.';
|
||||
} elseif(!empty($_FILES['background']) && is_array($_FILES['background'])) {
|
||||
if(!empty($_FILES['background']['name']['file'])) {
|
||||
if($_FILES['background']['error']['file'] !== UPLOAD_ERR_OK) {
|
||||
switch($_FILES['background']['error']['file']) {
|
||||
} elseif(!empty($_FILES['bg_file']) && is_array($_FILES['bg_file'])) {
|
||||
if(!empty($_FILES['bg_file']['name'])) {
|
||||
if($_FILES['bg_file']['error'] !== UPLOAD_ERR_OK) {
|
||||
switch($_FILES['bg_file']['error']) {
|
||||
case UPLOAD_ERR_NO_FILE:
|
||||
$notices[] = 'Select a file before hitting upload!';
|
||||
break;
|
||||
|
@ -256,14 +261,14 @@ if($isEditing) {
|
|||
}
|
||||
} else {
|
||||
try {
|
||||
$backgroundInfo->setFromPath($_FILES['background']['tmp_name']['file']);
|
||||
$backgroundAsset->setFromPath($_FILES['bg_file']['tmp_name']);
|
||||
} catch(InvalidArgumentException $ex) {
|
||||
$exMessage = $ex->getMessage();
|
||||
$notices[] = match($exMessage) {
|
||||
'$path is not a valid image.' => 'The file you uploaded was not an image!',
|
||||
'$path is not an allowed image file.' => 'This type of image is not supported, keep to PNG, JPG or GIF!',
|
||||
'Dimensions of $path are too large.' => sprintf('Your background can\'t be larger than %dx%d!', $backgroundInfo->getMaxWidth(), $backgroundInfo->getMaxHeight()),
|
||||
'File size of $path is too large.' => sprintf('Your background is not allowed to be larger in file size than %s!', ByteFormat::format($backgroundInfo->getMaxBytes())),
|
||||
'Dimensions of $path are too large.' => sprintf('Your background can\'t be larger than %dx%d!', $backgroundAsset->getMaxWidth(), $backgroundAsset->getMaxHeight()),
|
||||
'File size of $path is too large.' => sprintf('Your background is not allowed to be larger in file size than %s!', ByteFormat::format($backgroundAsset->getMaxBytes())),
|
||||
default => $exMessage,
|
||||
};
|
||||
} catch(RuntimeException $ex) {
|
||||
|
@ -272,13 +277,16 @@ if($isEditing) {
|
|||
}
|
||||
}
|
||||
|
||||
$backgroundInfo->setAttachment((int)($_POST['background']['attach'] ?? 0))
|
||||
->setBlend(!empty($_POST['background']['attr']['blend']))
|
||||
->setSlide(!empty($_POST['background']['attr']['slide']));
|
||||
$backgroundInfo = $msz->profileCtx->backgrounds->updateProfileBackground(
|
||||
$userInfo,
|
||||
$bgFormat,
|
||||
filter_has_var(INPUT_POST, 'bg_blend'),
|
||||
filter_has_var(INPUT_POST, 'bg_slide')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$msz->usersCtx->users->updateUser($userInfo, backgroundSettings: $backgroundInfo->getSettings());
|
||||
$backgroundAsset = new UserBackgroundAsset($userInfo, $backgroundInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,9 +327,9 @@ if(!$viewingAsGuest) {
|
|||
);
|
||||
$activeTopicInfo = $activeTopicStats->success ? $msz->forumCtx->topics->getTopic(topicId: $activeTopicStats->topicId) : null;
|
||||
|
||||
$profileFieldValues = iterator_to_array($msz->profileFields->getFieldValues($userInfo));
|
||||
$profileFieldInfos = $profileFieldInfos ?? iterator_to_array($msz->profileFields->getFields(fieldValueInfos: $isEditing ? null : $profileFieldValues));
|
||||
$profileFieldFormats = iterator_to_array($msz->profileFields->getFieldFormats(fieldValueInfos: $profileFieldValues));
|
||||
$profileFieldValues = iterator_to_array($msz->profileCtx->fields->getFieldValues($userInfo));
|
||||
$profileFieldInfos = $profileFieldInfos ?? iterator_to_array($msz->profileCtx->fields->getFields(fieldValueInfos: $isEditing ? null : $profileFieldValues));
|
||||
$profileFieldFormats = iterator_to_array($msz->profileCtx->fields->getFieldFormats(fieldValueInfos: $profileFieldValues));
|
||||
|
||||
$profileFieldRawValues = [];
|
||||
$profileFieldLinkValues = [];
|
||||
|
@ -382,8 +390,9 @@ Template::render('profile.index', [
|
|||
'profile_is_guest' => $viewingAsGuest,
|
||||
'profile_is_deleted' => false,
|
||||
'profile_ban_info' => $activeBanInfo,
|
||||
'profile_avatar_info' => $avatarInfo,
|
||||
'profile_avatar_asset' => $avatarAsset,
|
||||
'profile_background_info' => $backgroundInfo,
|
||||
'profile_background_asset' => $backgroundAsset,
|
||||
'profile_can_send_messages' => $viewerPermsGlobal->check(Perm::G_MESSAGES_SEND),
|
||||
'profile_age' => $msz->usersCtx->birthdates->getUserAge($userInfo),
|
||||
]);
|
||||
|
|
|
@ -146,9 +146,10 @@ if(isset($_POST['action']) && is_string($_POST['action'])) {
|
|||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'oauth2_refresh', ['ref_id:s', 'app_id:s', 'user_id:s:n', 'acc_id:s:n', 'ref_token:n', 'ref_scope:s', 'ref_created:t', 'ref_expires:t']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'perms', ['user_id:s:n', 'role_id:s:n', 'forum_id:s:n', 'perms_category:s', 'perms_allow:i', 'perms_deny:i']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'perms_calculated', ['user_id:s:n', 'forum_id:s:n', 'perms_category:s', 'perms_calculated:i']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'profile_backgrounds', ['user_id:s', 'bg_attach:s', 'bg_blend:i', 'bg_slide:i']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'profile_fields_values', ['field_id:s', 'user_id:s', 'format_id:s', 'field_value:s']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'sessions', ['session_id:s', 'user_id:s', 'session_key:n', 'session_remote_addr_first:a', 'session_remote_addr_last:a:n', 'session_user_agent:s', 'session_country:s', 'session_expires:t', 'session_expires_bump:b', 'session_created:t', 'session_active:t:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users', ['user_id:s', 'user_name:s', 'user_password:n', 'user_email:s', 'user_remote_addr_first:a', 'user_remote_addr_last:a', 'user_super:b', 'user_country:s', 'user_colour:i:n', 'user_created:t', 'user_active:t:n', 'user_deleted:t:n', 'user_display_role_id:s:n', 'user_about_content:s:n', 'user_about_content_format:s', 'user_signature_content:s:n', 'user_signature_content_format:s', 'user_background_settings:i:n', 'user_title:s:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users', ['user_id:s', 'user_name:s', 'user_password:n', 'user_email:s', 'user_remote_addr_first:a', 'user_remote_addr_last:a', 'user_super:b', 'user_country:s', 'user_colour:i:n', 'user_created:t', 'user_active:t:n', 'user_deleted:t:n', 'user_display_role_id:s:n', 'user_about_content:s:n', 'user_about_content_format:s', 'user_signature_content:s:n', 'user_signature_content_format:s', 'user_title:s:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users_bans', ['ban_id:s', 'user_id:s', 'mod_id:n', 'ban_severity:i', 'ban_reason_public:s', 'ban_reason_private:s', 'ban_created:t', 'ban_expires:t:n']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users_birthdates', ['user_id:s', 'birth_year:i:n', 'birth_month:i', 'birth_day:i']);
|
||||
$tmpFiles[] = db_to_zip($archive, $userInfo, 'users_password_resets', ['reset_id:s', 'user_id:s', 'reset_remote_addr:a', 'reset_requested:t', 'reset_code:n']);
|
||||
|
|
|
@ -21,7 +21,7 @@ use Misuzu\Messages\MessagesContext;
|
|||
use Misuzu\News\NewsData;
|
||||
use Misuzu\OAuth2\OAuth2Context;
|
||||
use Misuzu\Perms\PermissionsData;
|
||||
use Misuzu\Profile\ProfileFieldsData;
|
||||
use Misuzu\Profile\ProfileContext;
|
||||
use Misuzu\Redirects\RedirectsContext;
|
||||
use Misuzu\Routing\{BackedRoutingContext,RoutingContext};
|
||||
use Misuzu\Users\{UsersContext,UserInfo};
|
||||
|
@ -52,11 +52,10 @@ class MisuzuContext {
|
|||
public private(set) ForumContext $forumCtx;
|
||||
public private(set) MessagesContext $messagesCtx;
|
||||
public private(set) OAuth2Context $oauth2Ctx;
|
||||
public private(set) ProfileContext $profileCtx;
|
||||
public private(set) UsersContext $usersCtx;
|
||||
public private(set) RedirectsContext $redirectsCtx;
|
||||
|
||||
public private(set) ProfileFieldsData $profileFields;
|
||||
|
||||
public private(set) PermissionsData $perms;
|
||||
public private(set) AuthInfo $authInfo;
|
||||
public private(set) SiteInfo $siteInfo;
|
||||
|
@ -84,6 +83,7 @@ class MisuzuContext {
|
|||
$this->deps->register($this->forumCtx = $this->deps->constructLazy(ForumContext::class));
|
||||
$this->deps->register($this->messagesCtx = $this->deps->constructLazy(MessagesContext::class));
|
||||
$this->deps->register($this->oauth2Ctx = $this->deps->constructLazy(OAuth2Context::class, config: $config->scopeTo('oauth2')));
|
||||
$this->deps->register($this->profileCtx = $this->deps->constructLazy(ProfileContext::class));
|
||||
$this->deps->register($this->usersCtx = $this->deps->constructLazy(UsersContext::class));
|
||||
$this->deps->register($this->redirectsCtx = $this->deps->constructLazy(RedirectsContext::class, config: $config->scopeTo('redirects')));
|
||||
|
||||
|
@ -93,7 +93,6 @@ class MisuzuContext {
|
|||
$this->deps->register($this->counters = $this->deps->constructLazy(CountersData::class));
|
||||
$this->deps->register($this->emotes = $this->deps->constructLazy(EmotesData::class));
|
||||
$this->deps->register($this->news = $this->deps->constructLazy(NewsData::class));
|
||||
$this->deps->register($this->profileFields = $this->deps->constructLazy(ProfileFieldsData::class));
|
||||
}
|
||||
|
||||
public function getDbQueryCount(): int {
|
||||
|
|
9
src/Profile/ProfileBackgroundAttach.php
Normal file
9
src/Profile/ProfileBackgroundAttach.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
namespace Misuzu\Profile;
|
||||
|
||||
enum ProfileBackgroundAttach: string {
|
||||
case Cover = 'cover';
|
||||
case Stretch = 'stretch';
|
||||
case Tile = 'tile';
|
||||
case Contain = 'contain';
|
||||
}
|
38
src/Profile/ProfileBackgroundInfo.php
Normal file
38
src/Profile/ProfileBackgroundInfo.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
namespace Misuzu\Profile;
|
||||
|
||||
use Index\Db\DbResult;
|
||||
|
||||
class ProfileBackgroundInfo {
|
||||
public function __construct(
|
||||
public private(set) string $userId,
|
||||
public private(set) ProfileBackgroundAttach $attach,
|
||||
public private(set) bool $blend,
|
||||
public private(set) bool $slide,
|
||||
) {}
|
||||
|
||||
public static function fromResult(DbResult $result): ProfileBackgroundInfo {
|
||||
return new ProfileBackgroundInfo(
|
||||
userId: $result->getString(0),
|
||||
attach: ProfileBackgroundAttach::tryFrom($result->getString(1)) ?? ProfileBackgroundAttach::Cover,
|
||||
blend: $result->getBoolean(2),
|
||||
slide: $result->getBoolean(3),
|
||||
);
|
||||
}
|
||||
|
||||
public bool $cover {
|
||||
get => $this->attach === ProfileBackgroundAttach::Cover;
|
||||
}
|
||||
|
||||
public bool $stretch {
|
||||
get => $this->attach === ProfileBackgroundAttach::Stretch;
|
||||
}
|
||||
|
||||
public bool $tile {
|
||||
get => $this->attach === ProfileBackgroundAttach::Tile;
|
||||
}
|
||||
|
||||
public bool $contain {
|
||||
get => $this->attach === ProfileBackgroundAttach::Contain;
|
||||
}
|
||||
}
|
63
src/Profile/ProfileBackgroundsData.php
Normal file
63
src/Profile/ProfileBackgroundsData.php
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
namespace Misuzu\Profile;
|
||||
|
||||
use RuntimeException;
|
||||
use Index\Db\{DbConnection,DbStatementCache};
|
||||
use Misuzu\Users\UserInfo;
|
||||
|
||||
class ProfileBackgroundsData {
|
||||
private DbStatementCache $cache;
|
||||
|
||||
public function __construct(DbConnection $dbConn) {
|
||||
$this->cache = new DbStatementCache($dbConn);
|
||||
}
|
||||
|
||||
public function getProfileBackground(UserInfo|string $userInfo): ?ProfileBackgroundInfo {
|
||||
$stmt = $this->cache->get(<<<SQL
|
||||
SELECT user_id, bg_attach, bg_blend, bg_slide
|
||||
FROM msz_profile_backgrounds
|
||||
WHERE user_id = ?
|
||||
SQL);
|
||||
$stmt->nextParameter($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
$stmt->execute();
|
||||
|
||||
$result = $stmt->getResult();
|
||||
return $result->next() ? ProfileBackgroundInfo::fromResult($result) : null;
|
||||
}
|
||||
|
||||
public function deleteProfileBackground(UserInfo|string $userInfo): void {
|
||||
$stmt = $this->cache->get(<<<SQL
|
||||
DELETE FROM msz_profile_backgrounds
|
||||
WHERE user_id = ?
|
||||
SQL);
|
||||
$stmt->nextParameter($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
public function updateProfileBackground(
|
||||
UserInfo|string $userInfo,
|
||||
ProfileBackgroundAttach|string $attach,
|
||||
bool $blend,
|
||||
bool $slide
|
||||
): ProfileBackgroundInfo {
|
||||
if(is_string($attach))
|
||||
$attach = ProfileBackgroundAttach::from($attach);
|
||||
|
||||
$stmt = $this->cache->get(<<<SQL
|
||||
REPLACE INTO msz_profile_backgrounds (
|
||||
user_id, bg_attach, bg_blend, bg_slide
|
||||
) VALUES (?, ?, ?, ?)
|
||||
SQL);
|
||||
$stmt->nextParameter($userInfo instanceof UserInfo ? $userInfo->id : $userInfo);
|
||||
$stmt->nextParameter($attach->value);
|
||||
$stmt->nextParameter($blend ? 1 : 0);
|
||||
$stmt->nextParameter($slide ? 1 : 0);
|
||||
$stmt->execute();
|
||||
|
||||
$bgInfo = $this->getProfileBackground($userInfo);
|
||||
if($bgInfo === null)
|
||||
throw new RuntimeException('failed to update profile background');
|
||||
|
||||
return $bgInfo;
|
||||
}
|
||||
}
|
14
src/Profile/ProfileContext.php
Normal file
14
src/Profile/ProfileContext.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
namespace Misuzu\Profile;
|
||||
|
||||
use Index\Db\DbConnection;
|
||||
|
||||
class ProfileContext {
|
||||
public private(set) ProfileBackgroundsData $backgrounds;
|
||||
public private(set) ProfileFieldsData $fields;
|
||||
|
||||
public function __construct(DbConnection $dbConn) {
|
||||
$this->backgrounds = new ProfileBackgroundsData($dbConn);
|
||||
$this->fields = new ProfileFieldsData($dbConn);
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ use Index\Http\{HttpRequest,HttpResponseBuilder};
|
|||
use Index\Http\Routing\{HttpGet,HttpMiddleware,RouteHandler,RouteHandlerCommon};
|
||||
use Misuzu\Pagination;
|
||||
use Misuzu\Forum\ForumContext;
|
||||
use Misuzu\Profile\ProfileFieldsData;
|
||||
use Misuzu\Profile\ProfileContext;
|
||||
use Misuzu\Users\UsersContext;
|
||||
|
||||
final class SatoriRoutes implements RouteHandler {
|
||||
|
@ -18,7 +18,7 @@ final class SatoriRoutes implements RouteHandler {
|
|||
private Config $config,
|
||||
private UsersContext $usersCtx,
|
||||
private ForumContext $forumCtx,
|
||||
private ProfileFieldsData $profileFields
|
||||
private ProfileContext $profileCtx
|
||||
) {}
|
||||
|
||||
/** @return void|int */
|
||||
|
@ -49,7 +49,7 @@ final class SatoriRoutes implements RouteHandler {
|
|||
$fieldId = (string)$request->getParam('field', FILTER_SANITIZE_NUMBER_INT);
|
||||
|
||||
try {
|
||||
$fieldValue = $this->profileFields->getFieldValue($fieldId, $userId);
|
||||
$fieldValue = $this->profileCtx->fields->getFieldValue($fieldId, $userId);
|
||||
} catch(RuntimeException $ex) {
|
||||
return ['error' => 105];
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use Index\Http\Routing\{HttpGet,RouteHandler,RouteHandlerCommon};
|
|||
use Index\Urls\{UrlFormat,UrlRegistry,UrlSource,UrlSourceCommon};
|
||||
use Misuzu\Perm;
|
||||
use Misuzu\Auth\AuthInfo;
|
||||
use Misuzu\Profile\ProfileContext;
|
||||
use Misuzu\Users\{UsersContext,UserInfo};
|
||||
|
||||
class AssetsRoutes implements RouteHandler, UrlSource {
|
||||
|
@ -16,7 +17,8 @@ class AssetsRoutes implements RouteHandler, UrlSource {
|
|||
public function __construct(
|
||||
private AuthInfo $authInfo,
|
||||
private UrlRegistry $urls,
|
||||
private UsersContext $usersCtx
|
||||
private UsersContext $usersCtx,
|
||||
private ProfileContext $profileCtx
|
||||
) {}
|
||||
|
||||
private function canViewAsset(HttpRequest $request, UserInfo $assetUser): bool {
|
||||
|
@ -63,7 +65,10 @@ class AssetsRoutes implements RouteHandler, UrlSource {
|
|||
} catch(InvalidArgumentException $ex) {}
|
||||
|
||||
if(!empty($userInfo)) {
|
||||
$userAssetInfo = new UserBackgroundAsset($userInfo);
|
||||
$userAssetInfo = new UserBackgroundAsset(
|
||||
$userInfo,
|
||||
$this->profileCtx->backgrounds->getProfileBackground($userInfo)
|
||||
);
|
||||
if($userAssetInfo->isPresent() && $this->canViewAsset($request, $userInfo))
|
||||
$assetInfo = $userAssetInfo;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
<?php
|
||||
namespace Misuzu\Users\Assets;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Misuzu\Profile\ProfileBackgroundInfo;
|
||||
use Misuzu\Users\UserInfo;
|
||||
|
||||
// attachment and attributes are to be stored in the same byte
|
||||
// left half is for attributes, right half is for attachments
|
||||
// this makes for 16 possible attachments and 4 possible attributes
|
||||
// since attachments are just an incrementing number and attrs are flags
|
||||
|
||||
class UserBackgroundAsset extends UserImageAsset {
|
||||
private const FORMAT = 'backgrounds/original/%d.msz';
|
||||
|
||||
|
@ -16,46 +11,11 @@ class UserBackgroundAsset extends UserImageAsset {
|
|||
private const MAX_HEIGHT = 2160;
|
||||
private const MAX_BYTES = 1500000;
|
||||
|
||||
public const ATTACH_NONE = 0x00;
|
||||
public const ATTACH_COVER = 0x01;
|
||||
public const ATTACH_STRETCH = 0x02;
|
||||
public const ATTACH_TILE = 0x03;
|
||||
public const ATTACH_CONTAIN = 0x04;
|
||||
|
||||
public const ATTRIB_BLEND = 0x10;
|
||||
public const ATTRIB_SLIDE = 0x20;
|
||||
|
||||
public const ATTACHMENT_STRINGS = [
|
||||
self::ATTACH_COVER => 'cover',
|
||||
self::ATTACH_STRETCH => 'stretch',
|
||||
self::ATTACH_TILE => 'tile',
|
||||
self::ATTACH_CONTAIN => 'contain',
|
||||
];
|
||||
|
||||
public const ATTRIBUTE_STRINGS = [
|
||||
self::ATTRIB_BLEND => 'blend',
|
||||
self::ATTRIB_SLIDE => 'slide',
|
||||
];
|
||||
|
||||
/** @return array<int, string> */
|
||||
public static function getAttachmentStringOptions(): array {
|
||||
return [
|
||||
self::ATTACH_COVER => 'Cover',
|
||||
self::ATTACH_STRETCH => 'Stretch',
|
||||
self::ATTACH_TILE => 'Tile',
|
||||
self::ATTACH_CONTAIN => 'Contain',
|
||||
];
|
||||
}
|
||||
|
||||
private int $settings;
|
||||
|
||||
public function __construct(UserInfo $userInfo) {
|
||||
public function __construct(
|
||||
UserInfo $userInfo,
|
||||
private ?ProfileBackgroundInfo $bgInfo
|
||||
) {
|
||||
parent::__construct($userInfo);
|
||||
$this->settings = (int)$userInfo->backgroundSettings;
|
||||
}
|
||||
|
||||
public function getSettings(): int {
|
||||
return $this->settings;
|
||||
}
|
||||
|
||||
public function getMaxWidth(): int {
|
||||
|
@ -78,68 +38,4 @@ class UserBackgroundAsset extends UserImageAsset {
|
|||
public function getRelativePath(): string {
|
||||
return sprintf(self::FORMAT, $this->getUserId());
|
||||
}
|
||||
|
||||
public function getAttachment(): int {
|
||||
return $this->settings & 0x0F;
|
||||
}
|
||||
public function getAttachmentString(): string {
|
||||
return self::ATTACHMENT_STRINGS[$this->getAttachment()] ?? '';
|
||||
}
|
||||
public function setAttachment(int $attach): self {
|
||||
$this->settings = $this->getAttributes() | ($attach & 0x0F);
|
||||
return $this;
|
||||
}
|
||||
public function setAttachmentString(string $attach): self {
|
||||
if(!in_array($attach, self::ATTACHMENT_STRINGS))
|
||||
throw new InvalidArgumentException;
|
||||
$this->setAttachment(array_flip(self::ATTACHMENT_STRINGS)[$attach]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAttributes(): int {
|
||||
return $this->settings & 0xF0;
|
||||
}
|
||||
public function setAttributes(int $attrib): self {
|
||||
$this->settings = $this->getAttachment() | ($attrib & 0xF0);
|
||||
return $this;
|
||||
}
|
||||
public function isBlend(): bool {
|
||||
return ($this->getAttributes() & self::ATTRIB_BLEND) > 0;
|
||||
}
|
||||
public function setBlend(bool $blend): self {
|
||||
$this->settings = $blend
|
||||
? ($this->settings | self::ATTRIB_BLEND)
|
||||
: ($this->settings & ~self::ATTRIB_BLEND);
|
||||
return $this;
|
||||
}
|
||||
public function isSlide(): bool {
|
||||
return ($this->getAttributes() & self::ATTRIB_SLIDE) > 0;
|
||||
}
|
||||
public function setSlide(bool $slide): self {
|
||||
$this->settings = $slide
|
||||
? ($this->settings | self::ATTRIB_SLIDE)
|
||||
: ($this->settings & ~self::ATTRIB_SLIDE);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/** @return string[] */
|
||||
public function getClassNames(string $format = '%s'): array {
|
||||
$names = [];
|
||||
$attachment = $this->getAttachment();
|
||||
$attributes = $this->getAttributes();
|
||||
|
||||
if(array_key_exists($attachment, self::ATTACHMENT_STRINGS))
|
||||
$names[] = sprintf($format, self::ATTACHMENT_STRINGS[$attachment]);
|
||||
|
||||
foreach(self::ATTRIBUTE_STRINGS as $flag => $name)
|
||||
if(($attributes & $flag) > 0)
|
||||
$names[] = sprintf($format, $name);
|
||||
|
||||
return $names;
|
||||
}
|
||||
|
||||
public function delete(): void {
|
||||
parent::delete();
|
||||
$this->settings = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ class UserInfo {
|
|||
public private(set) TextFormat $aboutBodyFormat,
|
||||
public private(set) ?string $signatureBody,
|
||||
public private(set) TextFormat $signatureBodyFormat,
|
||||
public private(set) ?int $backgroundSettings,
|
||||
public private(set) ?string $title,
|
||||
) {}
|
||||
|
||||
|
@ -48,8 +47,7 @@ class UserInfo {
|
|||
aboutBodyFormat: TextFormat::tryFrom($result->getString(14)) ?? TextFormat::Plain,
|
||||
signatureBody: $result->getStringOrNull(15),
|
||||
signatureBodyFormat: TextFormat::tryFrom($result->getString(16)) ?? TextFormat::Plain,
|
||||
backgroundSettings: $result->getIntegerOrNull(17),
|
||||
title: $result->getString(18),
|
||||
title: $result->getString(17),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use Index\Colour\Colour;
|
|||
use Index\Db\{DbConnection,DbStatementCache,DbTools};
|
||||
use Misuzu\Pagination;
|
||||
use Misuzu\Tools;
|
||||
use Misuzu\Parsers\Parsers;
|
||||
use Misuzu\Parsers\TextFormat;
|
||||
|
||||
class UsersData {
|
||||
private DbStatementCache $cache;
|
||||
|
@ -179,7 +179,7 @@ class UsersData {
|
|||
u.user_display_role_id,
|
||||
u.user_about_content, u.user_about_content_format,
|
||||
u.user_signature_content, u.user_signature_content_format,
|
||||
u.user_background_settings, u.user_title
|
||||
u.user_title
|
||||
FROM msz_users AS u
|
||||
SQL;
|
||||
if($hasRoleInfo)
|
||||
|
@ -288,7 +288,7 @@ class UsersData {
|
|||
user_display_role_id,
|
||||
user_about_content, user_about_content_format,
|
||||
user_signature_content, user_signature_content_format,
|
||||
user_background_settings, user_title
|
||||
user_title
|
||||
FROM msz_users
|
||||
SQL;
|
||||
if($selectId) {
|
||||
|
@ -358,10 +358,9 @@ class UsersData {
|
|||
?Colour $colour = null,
|
||||
RoleInfo|string|null $displayRoleInfo = null,
|
||||
?string $aboutBody = null,
|
||||
?int $aboutBodyFormat = null,
|
||||
TextFormat|string|null $aboutBodyFormat = null,
|
||||
?string $signatureBody = null,
|
||||
?int $signatureBodyFormat = null,
|
||||
?int $backgroundSettings = null,
|
||||
TextFormat|string|null $signatureBodyFormat = null,
|
||||
?string $title = null
|
||||
): void {
|
||||
if($userInfo instanceof UserInfo)
|
||||
|
@ -409,28 +408,27 @@ class UsersData {
|
|||
}
|
||||
|
||||
if($aboutBody !== null && $aboutBodyFormat !== null) {
|
||||
if(is_string($aboutBodyFormat))
|
||||
$aboutBodyFormat = TextFormat::tryFrom($aboutBodyFormat) ?? null;
|
||||
if(self::validateProfileAbout($aboutBodyFormat, $aboutBody) !== '')
|
||||
throw new InvalidArgumentException('$aboutBody and $aboutBodyFormat contain invalid data!');
|
||||
|
||||
$fields[] = 'user_about_content = ?';
|
||||
$values[] = $aboutBody;
|
||||
$fields[] = 'user_about_content_format = ?';
|
||||
$values[] = $aboutBodyFormat;
|
||||
$values[] = $aboutBodyFormat->value;
|
||||
}
|
||||
|
||||
if($signatureBody !== null && $signatureBodyFormat !== null) {
|
||||
if(is_string($signatureBodyFormat))
|
||||
$signatureBodyFormat = TextFormat::tryFrom($signatureBodyFormat) ?? null;
|
||||
if(self::validateForumSignature($signatureBodyFormat, $signatureBody) !== '')
|
||||
throw new InvalidArgumentException('$signatureBody and $signatureBodyFormat contain invalid data!');
|
||||
|
||||
$fields[] = 'user_signature_content = ?';
|
||||
$values[] = $signatureBody;
|
||||
$fields[] = 'user_signature_content_format = ?';
|
||||
$values[] = $signatureBodyFormat;
|
||||
}
|
||||
|
||||
if($backgroundSettings !== null) {
|
||||
$fields[] = 'user_background_settings = ?';
|
||||
$values[] = $backgroundSettings;
|
||||
$values[] = $signatureBodyFormat->value;
|
||||
}
|
||||
|
||||
if($title !== null) {
|
||||
|
@ -709,8 +707,8 @@ class UsersData {
|
|||
};
|
||||
}
|
||||
|
||||
public static function validateProfileAbout(int $parser, string $text): string {
|
||||
if(!Parsers::isValid($parser))
|
||||
public static function validateProfileAbout(?TextFormat $format, string $text): string {
|
||||
if($format === null)
|
||||
return 'parser';
|
||||
|
||||
$length = strlen($text);
|
||||
|
@ -729,8 +727,8 @@ class UsersData {
|
|||
};
|
||||
}
|
||||
|
||||
public static function validateForumSignature(int $parser, string $text): string {
|
||||
if(!Parsers::isValid($parser))
|
||||
public static function validateForumSignature(?TextFormat $format, string $text): string {
|
||||
if($format === null)
|
||||
return 'parser';
|
||||
|
||||
$length = strlen($text);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
{% if name|length > 0 %}name="{{ name }}"{% endif %}
|
||||
{% if checked %}checked{% endif %}
|
||||
{% if disabled %}disabled{% endif %}
|
||||
{% if value|length > 0 %}value="{{ value }}"{% endif %}
|
||||
{% if value is defined and value is not null %}value="{{ value }}"{% endif %}
|
||||
{% for name, value in attributes|default([]) %}
|
||||
{{ name }}{% if value|length > 0 %}="{{ value }}"{% endif %}
|
||||
{% endfor %}>
|
||||
|
@ -74,9 +74,9 @@
|
|||
Click here to select a file!
|
||||
</div>
|
||||
<script>
|
||||
const parent = document.currentScript.parentNode,
|
||||
input = parent.querySelector('input[type="file"]'),
|
||||
display = parent.querySelector('.input__upload__selection');
|
||||
const parent = document.currentScript.parentNode;
|
||||
const input = parent.querySelector('input[type="file"]');
|
||||
const display = parent.querySelector('.input__upload__selection');
|
||||
input.addEventListener('change', ev => display.textContent = Array.from(ev.target.files).map(f => f.name).join(', '));
|
||||
</script>
|
||||
</label>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
{% set is_in_manage = true %}
|
||||
{% set title = title|default('Broom Closet') %}
|
||||
{% set site_logo = '/images/logos/imouto-broom.png' %}
|
||||
{% set main_css_vars = main_css_vars|default([])|merge({'--site-logo': "url('/images/logos/imouto-broom.png')"}) %}
|
||||
|
||||
{% block content %}
|
||||
<div class="manage">
|
||||
|
|
|
@ -5,26 +5,19 @@
|
|||
<link href="/vendor/fontawesome/css/all.min.css" type="text/css" rel="stylesheet">
|
||||
<link href="{{ asset('common.css') }}" type="text/css" rel="stylesheet">
|
||||
<link href="{{ asset('misuzu.css') }}" type="text/css" rel="stylesheet">
|
||||
{% if site_background is defined %}
|
||||
{% if main_css_vars is defined and main_css_vars is iterable and main_css_vars is not empty %}
|
||||
<style>
|
||||
:root {
|
||||
--background-width: {{ site_background.width }}px;
|
||||
--background-height: {{ site_background.height }}px;
|
||||
--background-image: url('{{ site_background_url|raw }}');
|
||||
}
|
||||
</style>
|
||||
{% endif %}
|
||||
{% if site_logo is defined %}
|
||||
<style>
|
||||
:root {
|
||||
--site-logo: url('{{ site_logo }}');
|
||||
{% for name, value in main_css_vars %}
|
||||
{{ name }}: {{ value|raw }};
|
||||
{% endfor %}
|
||||
}
|
||||
</style>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% set html_body_attrs = {
|
||||
'class': 'main' ~ (site_background is defined ? (' ' ~ site_background.classNames('main--bg-%s')|join(' ')) : ''),
|
||||
'class': html_classes('main', main_body_classes|default([])),
|
||||
'style': global_accent_colour is defined ? ('--accent-colour: ' ~ global_accent_colour) : '',
|
||||
} %}
|
||||
|
||||
|
|
|
@ -47,8 +47,8 @@
|
|||
{% if perms.edit_avatar %}
|
||||
<ul class="profile__guidelines__section">
|
||||
<li class="profile__guidelines__line profile__guidelines__line--header">Avatar</li>
|
||||
<li class="profile__guidelines__line">May not exceed the <span class="profile__guidelines__emphasis">{{ profile_avatar_info.maxBytes|format_filesize }}</span> file size limit.</li>
|
||||
<li class="profile__guidelines__line">May not be larger than <span class="profile__guidelines__emphasis">{{ profile_avatar_info.maxWidth }}x{{ profile_avatar_info.maxHeight }}</span>.</li>
|
||||
<li class="profile__guidelines__line">May not exceed the <span class="profile__guidelines__emphasis">{{ profile_avatar_asset.maxBytes|format_filesize }}</span> file size limit.</li>
|
||||
<li class="profile__guidelines__line">May not be larger than <span class="profile__guidelines__emphasis">{{ profile_avatar_asset.maxWidth }}x{{ profile_avatar_asset.maxHeight }}</span>.</li>
|
||||
<li class="profile__guidelines__line">Will be centre cropped and scaled to at most <span class="profile__guidelines__emphasis">240x240</span>.</li>
|
||||
<li class="profile__guidelines__line">Animated GIF images are allowed.</li>
|
||||
</ul>
|
||||
|
@ -57,8 +57,8 @@
|
|||
{% if perms.edit_background %}
|
||||
<ul class="profile__guidelines__section">
|
||||
<li class="profile__guidelines__line profile__guidelines__line--header">Background</li>
|
||||
<li class="profile__guidelines__line">May not exceed the <span class="profile__guidelines__emphasis">{{ profile_background_info.maxBytes|format_filesize }}</span> file size limit.</li>
|
||||
<li class="profile__guidelines__line">May not be larger than <span class="profile__guidelines__emphasis">{{ profile_background_info.maxWidth }}x{{ profile_background_info.maxHeight }}</span>.</li>
|
||||
<li class="profile__guidelines__line">May not exceed the <span class="profile__guidelines__emphasis">{{ profile_background_asset.maxBytes|format_filesize }}</span> file size limit.</li>
|
||||
<li class="profile__guidelines__line">May not be larger than <span class="profile__guidelines__emphasis">{{ profile_background_asset.maxWidth }}x{{ profile_background_asset.maxHeight }}</span>.</li>
|
||||
<li class="profile__guidelines__line">GIF images, in general, are only allowed when tiling.</li>
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
@ -90,15 +90,14 @@
|
|||
{{ container_title('Background') }}
|
||||
|
||||
<div class="profile__background-settings__content">
|
||||
{{ input_file('background[file]', '', ['image/png', 'image/jpeg', 'image/gif'], {'id':'background-selection'}) }}
|
||||
{{ input_file('bg_file', '', ['image/png', 'image/jpeg', 'image/gif'], {'id':'background-selection'}) }}
|
||||
|
||||
{{ input_checkbox('background[attach]', 'None', true, '', 0, true, {'onchange':'profileChangeBackgroundAttach(this.value)'}) }}
|
||||
{% for key, value in background_attachments %}
|
||||
{{ input_checkbox('background[attach]', value, key == profile_background_info.attachment, '', key, true, {'onchange':'profileChangeBackgroundAttach(this.value)'}) }}
|
||||
{% for key, value in { '': 'None', 'cover': 'Cover', 'stretch': 'Stretch', 'tile': 'Tile', 'contain': 'Contain' } %}
|
||||
{{ input_checkbox('bg_attach', value, key == profile_background_info.attach.value|default(''), '', key, true, {'onchange':'profileChangeBackgroundAttach(this.value)'}) }}
|
||||
{% endfor %}
|
||||
|
||||
{{ input_checkbox('background[attr][blend]', 'Blend', profile_background_info.blend, '', '', false, {'onchange':'profileToggleBackgroundAttr(\'blend\', this.checked)'}) }}
|
||||
{{ input_checkbox('background[attr][slide]', 'Slide', profile_background_info.slide, '', '', false, {'onchange':'profileToggleBackgroundAttr(\'slide\', this.checked)'}) }}
|
||||
{{ input_checkbox('bg_blend', 'Blend', profile_background_info.blend|default(false), '', '', false, {'onchange':'profileToggleBackgroundAttr(\'blend\', this.checked)'}) }}
|
||||
{{ input_checkbox('bg_slide', 'Slide', profile_background_info.slide|default(false), '', '', false, {'onchange':'profileToggleBackgroundAttr(\'slide\', this.checked)'}) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -304,10 +303,10 @@
|
|||
function profileToggleBackground(checked) {
|
||||
let currentBg = document.body.style.getPropertyValue('--background-image');
|
||||
|
||||
if(currentBg != 'initial' && checked) {
|
||||
if(currentBg != '' && checked) {
|
||||
profilePreviousBackground = currentBg;
|
||||
currentBg = 'initial';
|
||||
} else if(currentBg == 'initial' && !checked) {
|
||||
currentBg = '';
|
||||
} else if(currentBg == '' && !checked) {
|
||||
currentBg = profilePreviousBackground;
|
||||
}
|
||||
|
||||
|
@ -315,47 +314,23 @@
|
|||
}
|
||||
|
||||
function profileChangeBackgroundAttach(mode) {
|
||||
const modes = {
|
||||
1: 'cover',
|
||||
2: 'stretch',
|
||||
3: 'tile',
|
||||
4: 'contain',
|
||||
};
|
||||
const modes = ['cover', 'stretch', 'tile', 'contain'];
|
||||
|
||||
profileToggleBackground(mode == 0);
|
||||
for(const m of modes)
|
||||
document.body.classList.remove(`main--bg-${m}`);
|
||||
|
||||
for(let i = 1; i <= Object.keys(modes).length; i++)
|
||||
document.body.classList.remove('main--bg-' + modes[i]);
|
||||
|
||||
if(!modes[mode])
|
||||
return;
|
||||
|
||||
document.body.classList.add('main--bg-' + modes[mode]);
|
||||
const valid = modes.includes(mode);
|
||||
profileToggleBackground(valid);
|
||||
if(valid)
|
||||
document.body.classList.add(`main--bg-${mode}`);
|
||||
}
|
||||
|
||||
function profileToggleBackgroundAttr(attr, mode) {
|
||||
let className = '';
|
||||
|
||||
switch(attr) {
|
||||
case 'blend':
|
||||
className = 'main--bg-blend';
|
||||
break;
|
||||
|
||||
case 'slide':
|
||||
className = 'main--bg-slide';
|
||||
break;
|
||||
}
|
||||
|
||||
if(className) {
|
||||
if(mode)
|
||||
document.body.classList.add(className);
|
||||
else
|
||||
document.body.classList.remove(className);
|
||||
}
|
||||
document.body.classList.toggle(`main--bg-${attr}`, mode);
|
||||
}
|
||||
|
||||
document.getElementById('background-selection').addEventListener('change', ev => {
|
||||
const image = new Image();
|
||||
const image = new Image;
|
||||
image.src = URL.createObjectURL(ev.target.files[0]);
|
||||
image.addEventListener('load', () => {
|
||||
document.body.style.setProperty('--background-image', 'url(%)'.replace('%', image.src));
|
||||
|
|
|
@ -3,9 +3,20 @@
|
|||
{% if profile_user is defined %}
|
||||
{% set image = url('user-avatar', {'user': profile_user.id, 'res': 200}) %}
|
||||
{% set manage_link = url('manage-user', {'user': profile_user.id}) %}
|
||||
{% if (not profile_is_banned or profile_can_edit) %}
|
||||
{% set site_background = profile_background_info %}
|
||||
{% set site_background_url = url('user-background', {'user': profile_user.id}) %}
|
||||
{% if (not profile_is_banned or profile_can_edit) and profile_background_info is not null %}
|
||||
{% set main_body_classes = main_body_classes|default([])|merge({
|
||||
'main--bg-cover': profile_background_info.cover,
|
||||
'main--bg-stretch': profile_background_info.stretch,
|
||||
'main--bg-tile': profile_background_info.tile,
|
||||
'main--bg-contain': profile_background_info.contain,
|
||||
'main--bg-blend': profile_background_info.blend,
|
||||
'main--bg-slide': profile_background_info.slide,
|
||||
}) %}
|
||||
{% set main_css_vars = main_css_vars|default([])|merge({
|
||||
'--background-width': '%dpx'|format(profile_background_asset.width),
|
||||
'--background-height': '%dpx'|format(profile_background_asset.height),
|
||||
'--background-image': "url('%s')"|format(url('user-background', {'user': profile_user.id})),
|
||||
}) %}
|
||||
{% endif %}
|
||||
{% set stats = [
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue