Browse Source

Add Accent Color in the Configuration

pull/1431/head
Timothée Jaussoin 6 months ago
parent
commit
2320e5c6c5
  1. 1
      CHANGELOG.md
  2. 13
      app/MujiCallParticipant.php
  3. 6
      app/User.php
  4. 2
      app/Widgets/Chat/_chat.tpl
  5. 2
      app/Widgets/Chat/_chat_clear.tpl
  6. 1
      app/Widgets/Colors/Colors.php
  7. 1
      app/Widgets/Colors/colors.tpl
  8. 10
      app/Widgets/Config/Config.php
  9. 6
      app/Widgets/Config/_config_accent_color.tpl
  10. 14
      app/Widgets/Config/_config_form.tpl
  11. 13
      app/Widgets/Config/config.css
  12. 9
      app/Widgets/Config/config.js
  13. 3
      app/Widgets/Config/locales.ini
  14. 11
      app/Widgets/Drawer/drawer.css
  15. 64
      app/Widgets/Rooms/Rooms.php
  16. 12
      app/Widgets/Visio/visio.css
  17. 16
      app/Widgets/Visio/visio.tpl
  18. 21
      database/migrations/20250331170107_add_accent_color_to_users_table.php
  19. 16
      public/scripts/movim_visio.js
  20. 17
      public/theme/css/color.css
  21. 4
      public/theme/css/form.css
  22. 6
      public/theme/css/notification.css
  23. 2
      public/theme/css/style.css
  24. 2
      src/Moxl/Xec/Payload/MAMResult.php

1
CHANGELOG.md

@ -19,6 +19,7 @@ v0.30 (master)
* Add Stories status on the avatars
* Add support of several simultanous Muji invites in MUC chatrooms
* Important color management CSS cleanup
* Add Accent Color in the Configuration
v0.29.2
---------------------------

13
app/MujiCallParticipant.php

@ -27,6 +27,19 @@ class MujiCallParticipant extends Model
->where('session_id', $this->session_id);
}
public function getMeAttribute(): bool
{
$jid = explodeJid($this->jid);
if ($jid['resource'] == null) {
return $this->jid == \App\User::me()->id;
}
$presence = Presence::where('jid', $jid['jid'])->where('resource', $jid['resource'])->first();
return $presence && $presence->mucjid == \App\User::me()->id;
}
public function getNameAttribute()
{
return explodeJid($this->jid)['resource'];

6
app/User.php

@ -12,7 +12,7 @@ class User extends Model
{
protected $fillable = [
'id', 'language', 'nightmode', 'chatmain', 'nsfw', 'nickname',
'notificationchat', 'notificationcall', 'omemoenabled'
'notificationchat', 'notificationcall', 'omemoenabled', 'accentcolor'
];
public $with = ['session', 'capability'];
protected $keyType = 'string';
@ -197,6 +197,10 @@ class User extends Model
$this->language = (string)$config['language'];
}
if (isset($config['accentcolor'])) {
$this->accentcolor = (string)$config['accentcolor'];
}
if (isset($config['nsfw'])) {
$this->nsfw = (bool)$config['nsfw'];
}

2
app/Widgets/Chat/_chat.tpl

@ -32,7 +32,7 @@
</section>
</div>
<div class="chat_box {if="isset($conference) && $conference->presence && $conference->presence->mucrole == 'visitor'"}disabled{/if}">
<a id="scroll_down" class="button action color small semi" onclick="Chat.scrollTotally()">
<a id="scroll_down" class="button action color transparent small" onclick="Chat.scrollTotally()">
<i class="material-symbols">expand_more</i>
</a>
<ul class="list fill">

2
app/Widgets/Chat/_chat_clear.tpl

@ -9,7 +9,7 @@
</button>
<button
name="submit"
class="button flat"
class="button color red"
onclick="Chat_ajaxClearHistoryConfirm('{$jid|echapJS}'); Dialog_ajaxClear()">
{$c->__('button.delete')}
</button>

1
app/Widgets/Colors/Colors.php

@ -10,5 +10,6 @@ class Colors extends Base
{
header('Content-Type: text/css');
$this->view->assign('colors', palette(true));
$this->view->assign('accentcolor', $this->user ? $this->user->accentcolor : 'dorange');
}
}

1
app/Widgets/Colors/colors.tpl

@ -1,3 +1,4 @@
body {
{loop="$colors"}--p-{$key}: {$value};{/loop}
--movim-accent: var(--p-{$accentcolor});
}

10
app/Widgets/Config/Config.php

@ -36,6 +36,7 @@ class Config extends Base
$l = Locale::start();
$view->assign('languages', $l->getList());
$view->assign('accent_colors', ['blue', 'teal', 'green', 'dorange', 'red', 'pink', 'purple']);
$view->assign('conf', $this->user);
return $view->draw('_config_form');
@ -183,6 +184,15 @@ class Config extends Base
};
}
public function prepareAccentColorRadio(string $color)
{
$view = $this->tpl();
$view->assign('conf', $this->user);
$view->assign('color', $color);
return $view->draw('_config_accent_color');
}
public function display()
{
$this->view->assign('me', $this->user);

6
app/Widgets/Config/_config_accent_color.tpl

@ -0,0 +1,6 @@
<div class="radio">
<input name="accentcolor" value="{$color}" id="accentcolor_{$color}" type="radio"
{if="$conf->accentcolor == $color"}checked{/if}>
<label for="accentcolor_{$color}" style="border-color: var(--p-{$color}); background-color: var(--p-{$color})"
onclick="Config.setAccentColor('{$color}')"></label>
</div>

14
app/Widgets/Config/_config_form.tpl

@ -166,6 +166,20 @@
</span>
</div>
</li>
<li id="accent_color">
<span class="primary icon gray">
<i class="material-symbols">palette</i>
</span>
<div>
<p>{$c->__('config.accent_color')}</p>
<p></p>
<div>
{loop="$accent_colors"}
{autoescape="off"}{$c->prepareAccentColorRadio($value)}{/autoescape}
{/loop}
</div>
</div>
</li>
</ul>
</div>
</form>

13
app/Widgets/Config/config.css

@ -6,4 +6,17 @@ form div > span.supporting.night_mode_detected {
form div > span.supporting.night_mode_detected {
display: initial;
}
}
form li#accent_color div.radio {
display: inline-block;
margin-right: 0.5rem;
}
form li#accent_color div.radio label {
transform: scale(1.5);
}
form li#accent_color > div {
height: 9rem;
}

9
app/Widgets/Config/config.js

@ -1,15 +1,18 @@
var Config = {
switchNightMode: function()
{
switchNightMode: function () {
document.body.classList.toggle('nightmode');
},
setAccentColor: function (color) {
document.body.style.setProperty('--movim-accent', 'var(--p-' + color + ')');
},
updateSystemVariable: function (variable, value) {
window[variable] = value;
}
}
MovimWebsocket.attach(function() {
MovimWebsocket.attach(function () {
Notif.current('conf');
Config_ajaxMAMGetConfig();

3
app/Widgets/Config/locales.ini

@ -30,4 +30,5 @@ blog_saved = Personal blog confidentiality saved
confidentiality = Confidentiality
audio_title = Audio notifications
audio_call = Incoming call
audio_chat = Incoming message
audio_chat = Incoming message
accent_color = Accent color

11
app/Widgets/Drawer/drawer.css

@ -5,7 +5,7 @@
left: 0;
width: 100%;
max-height: calc(100% - 7rem);
box-shadow: var(--elevation-3);
box-shadow: var(--elevation-5);
transition: transform .3s ease-in-out;
display: flex;
flex-direction: column;
@ -35,3 +35,12 @@
left: calc(50% - 35rem);
}
}
#drawer ul.list>li.search form div:after {
background-color: rgb(var(--movim-background));
}
#drawer ul.list>li.search form div:focus-within:after {
background-color: rgba(var(--movim-background), 0.8);
}

64
app/Widgets/Rooms/Rooms.php

@ -74,7 +74,7 @@ class Rooms extends Base
{
$muji = $packet->content;
if ($muji->jidfrom && $muji->conference) {
if ($muji->jidfrom && $muji->conference && !$muji->inviter->me) {
Notif::append(
'chat|' . $muji->jidfrom,
($muji->conference != null && $muji->conference->name)
@ -85,7 +85,9 @@ class Rooms extends Base
: "📞 " . __('muji.call_audio_invite'),
$muji->conference->getPicture(),
5,
$this->route('chat', [$muji->jidfrom, 'room'])
$this->route('chat', [$muji->jidfrom, 'room']),
null,
'Search.chat(\'' . echapJS($muji->jidfrom) . '\', true)'
);
$this->onCallInvite($packet);
@ -147,9 +149,11 @@ class Rooms extends Base
public function onBookmarkGet($packet)
{
foreach ($this->user->session->conferences()
->where('bookmarkversion', (int)$packet->content)
->get() as $room) {
foreach (
$this->user->session->conferences()
->where('bookmarkversion', (int)$packet->content)
->get() as $room
) {
if ($room->autojoin && !$room->connected) {
$this->ajaxJoin($room->conference, $room->nick);
}
@ -181,7 +185,7 @@ class Rooms extends Base
$composing
? 'MovimUtils.addClass'
: 'MovimUtils.removeClass',
'#' . cleanupId($room.'_rooms_primary'),
'#' . cleanupId($room . '_rooms_primary'),
'composing'
);
}
@ -189,15 +193,15 @@ class Rooms extends Base
private function setCounter(string $room)
{
$conference = $this->user->session
->conferences()
->where('conference', $room)
->withCount('unreads', 'quoted')
->first();
->conferences()
->where('conference', $room)
->withCount('unreads', 'quoted')
->first();
if ($conference) {
$this->rpc(
'MovimTpl.fill',
'#' . cleanupId($room.'_rooms_primary'),
'#' . cleanupId($room . '_rooms_primary'),
$this->prepareRoomCounter($conference, $conference->getPicture())
);
@ -209,10 +213,10 @@ class Rooms extends Base
public function onPresence(string $room, bool $callSecond = true)
{
$conference = $this->user->session->conferences()
->where('conference', $room)
->with('info', 'contact', 'presence')
->withCount('unreads', 'quoted', 'presences')
->first();
->where('conference', $room)
->with('info', 'contact', 'presence')
->withCount('unreads', 'quoted', 'presences')
->first();
if ($conference) {
$this->rpc('Rooms.setRoom', \cleanupId($conference->conference), $this->prepareConference($conference), $callSecond);
@ -227,9 +231,9 @@ class Rooms extends Base
public function ajaxHttpGet()
{
$conferences = $this->user->session->conferences()
->with('info', 'contact', 'presence')
->withCount('unreads', 'quoted', 'presences')
->get();
->with('info', 'contact', 'presence')
->withCount('unreads', 'quoted', 'presences')
->get();
$this->rpc('Rooms.clearRooms');
@ -258,7 +262,7 @@ class Rooms extends Base
$r = new Request;
$r->setTo($room)
->request();
->request();
$p = new Muc;
$p->setTo($room);
@ -269,8 +273,8 @@ class Rooms extends Base
$jid = explodeJid($room);
$capability = \App\Info::where('server', $jid['server'])
->where('node', '')
->first();
->where('node', '')
->first();
if ($capability && ($capability->isMAM() || $capability->isMAM2())) {
$this->rpc('MovimUtils.addClass', '#chat_widget .contained', 'loading');
@ -283,12 +287,12 @@ class Rooms extends Base
} else {
$r = new Request;
$r->setTo($jid['server'])
->request();
->request();
}
$m = new GetMembers;
$m->setTo($room)
->request();
->request();
$p->setNickname($nickname);
$p->request();
@ -319,8 +323,8 @@ class Rooms extends Base
$jid = explodeJid($room);
$capability = \App\Info::where('server', $jid['server'])
->where('node', '')
->first();
->where('node', '')
->first();
if (!$capability || !$capability->isMAM()) {
$this->user->messages()->where('jidfrom', $room)->delete();
@ -331,19 +335,19 @@ class Rooms extends Base
// We clear the presences from the buffer cache and then the DB
$this->user->session->conferences()
->where('conference', $room)
->first()->presences()->delete();
->where('conference', $room)
->first()->presences()->delete();
$this->ajaxHttpGet();
if ($resource) {
$session = Session::instance();
$session->delete($room . '/' .$resource);
$session->delete($room . '/' . $resource);
$pu = new Unavailable;
$pu->setTo($room)
->setResource($resource)
->request();
->setResource($resource)
->request();
}
}

12
app/Widgets/Visio/visio.css

@ -198,7 +198,7 @@ body>#visio:not(:fullscreen) .participant img.avatar {
position: absolute;
width: 100%;
z-index: 1;
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.8), transparent);
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.4), transparent);
}
#visio header ul.list li {
@ -225,6 +225,8 @@ body>#visio:not(:fullscreen) .participant img.avatar {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: white;
opacity: 0.6;
}
#visio .button.action {
@ -278,8 +280,11 @@ body>#visio:not(:fullscreen) #participants .participant:not(.active) {
/** Grid view **/
#visio #participants:not(.active) .participant.active {
background-color: rgba(var(--movim-font), 0.1);
#visio #participants:not(.active) .participant.active:not(.audio_off)::after {
color: var(--p-green);
opacity: calc(1 - var(--level));
transform: scale(1.5) translateX(0.25rem) translateY(-0.25rem);
transition: opacity 0.5s ease-in-out, transform .3s cubic-bezier(.4,0,.2,1);
}
#visio #participants:not(.active):has(.participant:nth-child(2)) .participant {
@ -324,6 +329,7 @@ body>#visio #participants:not(.active):has(.participant:nth-child(7)) .participa
color: white;
text-shadow: 0 0 1rem rgba(0, 0, 0, 0.85);
font-size: 2rem;
transition: opacity 0.5s ease-in-out, transform .3s cubic-bezier(.4,0,.2,1);
}
#visio .participant::after {

16
app/Widgets/Visio/visio.tpl

@ -2,30 +2,30 @@
<header>
<ul class="list">
<li>
<span id="switch_chat" class="primary icon color transparent active" onclick="VisioUtils.switchChat()">
<span id="switch_chat" class="primary icon color none active" onclick="VisioUtils.switchChat()">
<i class="material-symbols">back_to_tab</i>
</span>
<span id="toggle_fullscreen" class="control icon color transparent active" onclick="VisioUtils.toggleFullScreen()">
<span id="toggle_fullscreen" class="control icon color none active" onclick="VisioUtils.toggleFullScreen()">
<i class="material-symbols">fullscreen</i>
</span>
<span id="toggle_mode" class="control icon color transparent active" onclick="VisioUtils.toggleMode()">
<span id="toggle_mode" class="control icon color none active" onclick="VisioUtils.toggleMode()">
<i class="material-symbols">tile_small</i>
</span>
<span id="toggle_dtmf" class="control icon color transparent active" onclick="VisioUtils.toggleDtmf()">
<span id="toggle_dtmf" class="control icon color none active" onclick="VisioUtils.toggleDtmf()">
<i class="material-symbols">dialpad</i>
</span>
<span id="toggle_audio" class="divided control icon color transparent active" onclick="VisioUtils.toggleAudio()">
<span id="toggle_audio" class="divided control icon color none active" onclick="VisioUtils.toggleAudio()">
<i class="material-symbols">mic</i>
</span>
<span id="toggle_video" class="control icon color transparent active" onclick="VisioUtils.toggleVideo()">
<span id="toggle_video" class="control icon color none active" onclick="VisioUtils.toggleVideo()">
<i class="material-symbols">videocam</i>
</span>
<span id="switch_camera" class="control icon color transparent active">
<span id="switch_camera" class="control icon color none active">
<i class="material-symbols">switch_camera</i>
</span>
<span id="screen_sharing" class="control icon color transparent active toggleable" onclick="VisioUtils.toggleScreenSharing()">
<span id="screen_sharing" class="control icon color none active toggleable" onclick="VisioUtils.toggleScreenSharing()">
<i class="material-symbols">screen_share</i>
</span>

21
database/migrations/20250331170107_add_accent_color_to_users_table.php

@ -0,0 +1,21 @@
<?php
use Movim\Migration;
use Illuminate\Database\Schema\Blueprint;
class AddAccentColorToUsersTable extends Migration
{
public function up()
{
$this->schema->table('users', function (Blueprint $table) {
$table->string('accentcolor')->default('dorange');
});
}
public function down()
{
$this->schema->table('users', function (Blueprint $table) {
$table->dropColumn('accentcolor');
});
}
}

16
public/scripts/movim_visio.js

@ -272,20 +272,20 @@ var MovimVisio = {
}
if (MovimVisio.localAudio) {
let localStream = MovimVisio.localAudio.srcObject;
let stream = MovimVisio.localAudio.srcObject;
if (localStream) {
localStream.getTracks().forEach(track => track.stop());
localStream = null;
if (stream) {
stream.getTracks().forEach(track => track.stop());
stream = null;
}
}
if (MovimVisio.localVideo) {
let localStream = MovimVisio.localVideo.srcObject;
let stream = MovimVisio.localVideo.srcObject;
if (localStream) {
localStream.getTracks().forEach(track => track.stop());
localStream = null;
if (stream) {
stream.getTracks().forEach(track => track.stop());
stream = null;
}
}

17
public/theme/css/color.css

@ -1,7 +1,6 @@
/* Color */
body {
--movim-accent: var(--p-dorange);
--movim-background-main: 255, 255, 255;
--movim-background: 238, 238, 238;
--movim-gray: 35, 35, 35;
@ -34,8 +33,9 @@ body.nightmode {
}
}
body {
background-color: rgb(var(--movim-background));
body,
.drawer {
background-color: rgb(var(--movim-background-main));
}
body > *,
@ -67,7 +67,7 @@ table tr th {
}
ul li.date > div > p.normal,
.dialog, .drawer, ul.context_menu,
.dialog, ul.context_menu,
.card > .block:not(.subheader):not(.simple) {
background-color: rgb(var(--movim-background-main));
}
@ -90,8 +90,13 @@ form > div .radio > input[type="radio"]:checked + label {
color: white;
}
span.icon span.counter:not(.alt) {
color: white;
}
span.icon span.counter.alt {
background-color: var(--movim-accent);
color: var(--movim-font);
background-color: rgb(var(--movim-background-main));
}
/* Elements */
@ -154,7 +159,7 @@ span.icon:not(.composing):not([data-counter]):not(.story).status.server_error:af
.color.steam,
.color.bgray { color: white; background-color: var(--p-bgray); border-color: var(--p-bgray) }
.color.transparent { color: white; backdrop-filter: blur(1rem); background-color: rgba(0, 0, 0, 0.25); }
.color.none { color: white; background-color: transparent; }
.color.semi { color: rgba(var(--movim-font), 0.87); background-color: rgba(var(--movim-background-main), 0.75); }
form > div > input:focus:invalid,

4
public/theme/css/form.css

@ -257,8 +257,8 @@ form > div .radio > input[type="radio"] + label {
border-style: solid;
border-color: gray;
transition: box-shadow 0.1s ease;
margin: 1.25rem;
margin-bottom: 0;
margin: 0 1.25rem;
position: relative;
}
form > div .radio > input[type="radio"] + label:hover {

6
public/theme/css/notification.css

@ -11,7 +11,7 @@
color: white;
box-sizing: border-box;
pointer-events: none;
transition: opacity 0.2s ease, transform 0.4s ease;
transition: opacity 0.2s ease, transform 0.4s ease, box-shadow .3s cubic-bezier(.4,0,.2,1);
background-color: rgb(var(--movim-gray));
transform: translateY(0);
}
@ -35,6 +35,10 @@
top: 1rem;
}
.snackbar:hover {
box-shadow: var(--elevation-4);
}
.toast {
left: calc(50% - 24rem);
line-height: 2.5rem;

2
public/theme/css/style.css

@ -77,7 +77,7 @@ body>div.dialog:not(:empty)~main,
body>div.dialog:not(:empty)~nav,
body>div.dialog:not(:empty)~#visio,
body>nav.active~main {
opacity: 0.15;
opacity: 0.05;
pointer-events: none;
}

2
src/Moxl/Xec/Payload/MAMResult.php

@ -18,7 +18,7 @@ class MAMResult extends Payload
$stanza->forwarded->delay
&& isset($stanza->attributes()->queryid)
&& $messagesCounter >= 0
) {\logDebug($stanza->asXML());
) {
$session->set('mamid' . (string)$stanza->attributes()->queryid, $messagesCounter + 1);
if ($stanza->forwarded->message->retract

Loading…
Cancel
Save