Browse Source

Add OMEMO sessions toggles and display last-received-message bellow them for information

Update the dependencies
pull/1021/head
Timothée Jaussoin 4 years ago
parent
commit
399aa812a5
  1. 17
      app/widgets/Account/Account.php
  2. 55
      app/widgets/Account/_account_fingerprints.tpl
  3. 15
      app/widgets/Account/account.js
  4. 10
      app/widgets/ChatOmemo/chatomemo.js
  5. 14
      app/widgets/ChatOmemo/chatomemo_storage.js
  6. 2
      app/widgets/ChatOmemo/locales.ini
  7. 21
      app/widgets/ContactActions/ContactActions.php
  8. 68
      app/widgets/ContactActions/_contactactions_drawer_fingerprints.tpl
  9. 15
      app/widgets/ContactActions/contactactions.js
  10. 5
      app/widgets/Post/_post_comments.tpl
  11. 143
      composer.lock

17
app/widgets/Account/Account.php

@ -155,12 +155,27 @@ class Account extends \Movim\Widget\Base
$fingerprint->built = in_array($fingerprint->bundleid, $resolvedDeviceIds);
}
$view->assign('fingerprints', $fingerprints->sortByDesc('self'));
$fingerprints = $fingerprints->sortByDesc('self')->keyBy('bundleid');
$latests = \App\Message::selectRaw('max(published) as latest, bundleid')
->where('user_id', $this->user->id)
->where('jidfrom', $this->user->id)
->groupBy('bundleid')
->pluck('latest', 'bundleid');
foreach ($fingerprints->keys() as $key) {
$fingerprints[$key]->latest = $latests->has($key)
? $latests[$key]
: null;
}
$view->assign('fingerprints', $fingerprints);
$this->rpc('MovimTpl.fill',
'#account_fingerprints',
$view->draw('_account_fingerprints')
);
$this->rpc('Account.resolveSessionsStates');
}
public function ajaxRemoveAccountConfirm($form)

55
app/widgets/Account/_account_fingerprints.tpl

@ -1,23 +1,42 @@
{if="$fingerprints->count() > 0"}
<ul class="list middle">
<li class="subheader">
<div>
<p>{$c->__('omemo.fingerprints')}</p>
</div>
</li>
{loop="$fingerprints"}
<li>
<span class="primary icon {if="$value->self"}green{elseif="$value->built"}blue{else}gray{/if}">
<i class="material-icons">fingerprint</i>
</span>
<form>
<div>
<ul class="list middle">
<li class="subheader">
<div>
<p class="normal">
<span class="fingerprint {if="$value->self"}self{/if}">
{$value->fingerprint}
</span>
</p>
<p>{$c->__('omemo.fingerprints')}</p>
</div>
</li>
{/loop}
</ul>
{loop="$fingerprints"}
<li>
<span class="primary icon {if="$value->self"}green{elseif="$value->built"}blue{else}gray{/if}">
<i class="material-icons">fingerprint</i>
</span>
<span class="control">
<div class="checkbox">
<input
type="checkbox"
data-identifier="{$value->jid}.{$value->bundleid}"
id="accountsessionstate_{$value->bundleid}"
name="accountsessionstate_{$value->bundleid}"
onchange="Account.toggleFingerprintState(this)"/>
<label for="accountsessionstate_{$value->bundleid}"></label>
</div>
</span>
<div>
<p class="normal">
<span class="fingerprint {if="$value->self"}self{/if}">
{$value->fingerprint}
</span>
</p>
{if="isset($value->latest)"}
<p>{$c->__('omemo.last_message')}: {$value->latest|strtotime|prepareDate:true}</p>
{/if}
</div>
</li>
{/loop}
</ul>
</div>
</form>
{/if}

15
app/widgets/Account/account.js

@ -3,6 +3,21 @@ var Account = {
var form = document.querySelector('form[name=password]');
form.reset();
document.querySelector('#password_save').className = 'button color flat';
},
resolveSessionsStates : function() {
var store = new ChatOmemoStorage();
store.getSessionsIds(store.jid).map(id => {
store.getSessionState(store.jid + '.' + id).then(state => {
if (state) {
let checkbox = document.querySelector('input[name=accountsessionstate_' + id + ']');
checkbox.checked = true;
}
})
});
},
toggleFingerprintState : function(checkbox) {
var store = new ChatOmemoStorage();
store.setSessionState(checkbox.dataset.identifier, checkbox.checked);
}
}

10
app/widgets/ChatOmemo/chatomemo.js

@ -329,10 +329,16 @@ var ChatOmemo = {
var store = new ChatOmemoStorage();
let promises = store.filter('.session' + jid)
.map(key => key.split(/[\s.]+/).pop())
.map(deviceId => this.encryptDevice(plaintext, jid, deviceId) );
.map(deviceId => store.getSessionState(jid + '.' + deviceId).then(state => {
if (state) {
return this.encryptDevice(plaintext, jid, deviceId);
}
return Promise.resolve(false);
}));
return Promise.all(promises).then(result => {
return result;
return result.filter(encrypted => encrypted !== false);
});
},
encryptDevice: function (plaintext, jid, deviceId) {

14
app/widgets/ChatOmemo/chatomemo_storage.js

@ -194,6 +194,20 @@ ChatOmemoStorage.prototype = {
return Promise.resolve(state);
},
getSessionState: function (identifier) {
return this.loadSession(identifier).then(json => {
let session = JSON.parse(json);
return (session.state === true || session.state === undefined);
});
},
setSessionState: function (identifier, enabled) {
this.loadSession(identifier).then(json => {
let session = JSON.parse(json);
session.state = Boolean(enabled);
this.storeSession(identifier, JSON.stringify(session));
});
},
toString: function(thing) {
if (typeof thing == 'string') {
return thing;

2
app/widgets/ChatOmemo/locales.ini

@ -11,5 +11,5 @@ encrypted_disabled = Encryption disabled
encrypted_loading = Send a message to build the encrypted session
enable_contact = Enabling OMEMO for the contact
disable_contact = Disabling OMEMO for the contact
last_message = Last message received
last_message = Last message
sessions_built = %s sessions built

21
app/widgets/ContactActions/ContactActions.php

@ -95,11 +95,30 @@ class ContactActions extends Base
public function ajaxGetDrawerFingerprints($jid, $deviceId)
{
$fingerprints = $this->user->bundles()
->where('jid', $jid)
->with('sessions')
->get()
->keyBy('bundleid');
$latests = \App\Message::selectRaw('max(published) as latest, bundleid')
->where('user_id', $this->user->id)
->where('jidfrom', $jid)
->groupBy('bundleid')
->pluck('latest', 'bundleid');
foreach ($fingerprints->keys() as $key) {
$fingerprints[$key]->latest = $latests->has($key)
? $latests[$key]
: null;
}
$tpl = $this->tpl();
$tpl->assign('fingerprints', $this->user->bundles()->where('jid', $jid)->with('sessions')->get());
$tpl->assign('fingerprints', $fingerprints);
$tpl->assign('deviceid', $deviceId);
$this->rpc('MovimTpl.fill', '#omemo_fingerprints', $tpl->draw('_contactactions_drawer_fingerprints'));
$this->rpc('ContactActions.resolveSessionsStates', $jid);
}
public function ajaxAdd($form)

68
app/widgets/ContactActions/_contactactions_drawer_fingerprints.tpl

@ -1,27 +1,45 @@
<ul class="list middle">
<li class="subheader">
<div>
<p>{$c->__('omemo.fingerprints')}</p>
</div>
</li>
{loop="$fingerprints"}
<li>
{$sessionsCount = $value->sessions->count()}
<form>
<div>
<ul class="list middle">
<li class="subheader">
<div>
<p>{$c->__('omemo.fingerprints')}</p>
</div>
</li>
{loop="$fingerprints"}
<li>
{$sessionsCount = $value->sessions->count()}
<span class="primary icon {if="$sessionsCount > 0 && $value->sessions->pluck('deviceid')->contains($deviceid)"}blue{else}gray{/if}"
title="{$c->__('omemo.sessions_built', $sessionsCount)}">
<i class="material-icons">fingerprint</i>
{if="$sessionsCount > 1"}
<span class="counter alt" data-mucreceipts="true">{$sessionsCount}</span>
{/if}
</span>
<div>
<p class="normal">
<span class="fingerprint" title="{$value->bundleid}">
{$value->fingerprint}
<span class="primary icon {if="$sessionsCount > 0 && $value->sessions->pluck('deviceid')->contains($deviceid)"}blue{else}gray{/if}"
title="{$c->__('omemo.sessions_built', $sessionsCount)}">
<i class="material-icons">fingerprint</i>
{if="$sessionsCount > 1"}
<span class="counter alt" data-mucreceipts="true">{$sessionsCount}</span>
{/if}
</span>
</p>
</div>
</li>
{/loop}
</ul>
<span class="control">
<div class="checkbox">
<input
type="checkbox"
data-identifier="{$value->jid}.{$value->bundleid}"
id="sessionstate_{$value->bundleid}"
name="sessionstate_{$value->bundleid}"
onchange="ContactActions.toggleFingerprintState(this)"/>
<label for="sessionstate_{$value->bundleid}"></label>
</div>
</span>
<div>
<p class="normal">
<span class="fingerprint" title="{$value->bundleid}">
{$value->fingerprint}
</span>
</p>
{if="isset($value->latest)"}
<p>{$c->__('omemo.last_message')}: {$value->latest|strtotime|prepareDate:true}</p>
{/if}
</div>
</li>
{/loop}
</ul>
</div>
</form>

15
app/widgets/ContactActions/contactactions.js

@ -4,5 +4,20 @@ var ContactActions = {
store.getLocalRegistrationId().then(deviceId => {
ContactActions_ajaxGetDrawerFingerprints(jid, deviceId);
});
},
resolveSessionsStates : function(jid) {
var store = new ChatOmemoStorage();
store.getSessionsIds(jid).map(id => {
store.getSessionState(jid + '.' + id).then(state => {
if (state) {
let checkbox = document.querySelector('input[name=sessionstate_' + id + ']');
checkbox.checked = true;
}
})
});
},
toggleFingerprintState : function(checkbox) {
var store = new ChatOmemoStorage();
store.setSessionState(checkbox.dataset.identifier, checkbox.checked);
}
}

5
app/widgets/Post/_post_comments.tpl

@ -11,14 +11,15 @@
<p class="all">
{loop="$post->likes"}
{if="$public"}
{$value->truename}
{$value->truename}{if="$key + 1 < $post->likes->count()"},{/if}
{else}
{if="$value->isMine()"}
{$liked = [$value->server, $value->node, $value->nodeid]}
{/if}
<a title="{$value->published|strtotime|prepareDate:true,true}"
href="{$c->route('contact', $value->aid)}">
{$value->truename}</a>{/if}{if="$key + 1 < $post->likes->count()"},{/if}
{$value->truename}</a>{if="$key + 1 < $post->likes->count()"},{/if}
{/if}
{/loop}
</p>
</div>

143
composer.lock

@ -1422,7 +1422,7 @@
},
{
"name": "illuminate/bus",
"version": "v8.72.0",
"version": "v8.73.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/bus.git",
@ -1475,7 +1475,7 @@
},
{
"name": "illuminate/collections",
"version": "v8.72.0",
"version": "v8.73.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/collections.git",
@ -1529,7 +1529,7 @@
},
{
"name": "illuminate/container",
"version": "v8.72.0",
"version": "v8.73.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/container.git",
@ -1580,7 +1580,7 @@
},
{
"name": "illuminate/contracts",
"version": "v8.72.0",
"version": "v8.73.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/contracts.git",
@ -1628,16 +1628,16 @@
},
{
"name": "illuminate/database",
"version": "v8.72.0",
"version": "v8.73.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/database.git",
"reference": "c7d2dc41fd18db7dfe7cd8e760debdfb0d36841d"
"reference": "f93e5370a3d321de697755f185395bdf75e0ccc4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/database/zipball/c7d2dc41fd18db7dfe7cd8e760debdfb0d36841d",
"reference": "c7d2dc41fd18db7dfe7cd8e760debdfb0d36841d",
"url": "https://api.github.com/repos/illuminate/database/zipball/f93e5370a3d321de697755f185395bdf75e0ccc4",
"reference": "f93e5370a3d321de697755f185395bdf75e0ccc4",
"shasum": ""
},
"require": {
@ -1692,11 +1692,11 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-11-17T15:04:30+00:00"
"time": "2021-11-23T14:10:34+00:00"
},
{
"name": "illuminate/events",
"version": "v8.72.0",
"version": "v8.73.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/events.git",
@ -1751,7 +1751,7 @@
},
{
"name": "illuminate/macroable",
"version": "v8.72.0",
"version": "v8.73.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/macroable.git",
@ -1797,7 +1797,7 @@
},
{
"name": "illuminate/pipeline",
"version": "v8.72.0",
"version": "v8.73.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/pipeline.git",
@ -1845,16 +1845,16 @@
},
{
"name": "illuminate/support",
"version": "v8.72.0",
"version": "v8.73.2",
"source": {
"type": "git",
"url": "https://github.com/illuminate/support.git",
"reference": "bad652d0dfec26e9597ffb292fc728201310c113"
"reference": "ecb4d4fb01f9716b2decbb1bf584ea8164c3b222"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/illuminate/support/zipball/bad652d0dfec26e9597ffb292fc728201310c113",
"reference": "bad652d0dfec26e9597ffb292fc728201310c113",
"url": "https://api.github.com/repos/illuminate/support/zipball/ecb4d4fb01f9716b2decbb1bf584ea8164c3b222",
"reference": "ecb4d4fb01f9716b2decbb1bf584ea8164c3b222",
"shasum": ""
},
"require": {
@ -1909,7 +1909,7 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2021-11-17T15:04:30+00:00"
"time": "2021-11-23T14:10:18+00:00"
},
{
"name": "league/commonmark",
@ -3724,16 +3724,16 @@
},
{
"name": "symfony/config",
"version": "v5.3.10",
"version": "v5.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
"reference": "ac23c2f24d5634966d665d836c3933d54347e5d4"
"reference": "f080af00c441f1df40cf5c269707fdebe5740557"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/config/zipball/ac23c2f24d5634966d665d836c3933d54347e5d4",
"reference": "ac23c2f24d5634966d665d836c3933d54347e5d4",
"url": "https://api.github.com/repos/symfony/config/zipball/f080af00c441f1df40cf5c269707fdebe5740557",
"reference": "f080af00c441f1df40cf5c269707fdebe5740557",
"shasum": ""
},
"require": {
@ -3783,7 +3783,7 @@
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/config/tree/v5.3.10"
"source": "https://github.com/symfony/config/tree/v5.3.11"
},
"funding": [
{
@ -3799,20 +3799,20 @@
"type": "tidelift"
}
],
"time": "2021-10-22T09:06:52+00:00"
"time": "2021-10-29T16:05:40+00:00"
},
{
"name": "symfony/console",
"version": "v5.3.10",
"version": "v5.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3"
"reference": "3e7ab8f5905058984899b05a4648096f558bfeba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3",
"reference": "d4e409d9fbcfbf71af0e5a940abb7b0b4bad0bd3",
"url": "https://api.github.com/repos/symfony/console/zipball/3e7ab8f5905058984899b05a4648096f558bfeba",
"reference": "3e7ab8f5905058984899b05a4648096f558bfeba",
"shasum": ""
},
"require": {
@ -3825,7 +3825,6 @@
"symfony/string": "^5.1"
},
"conflict": {
"psr/log": ">=3",
"symfony/dependency-injection": "<4.4",
"symfony/dotenv": "<5.1",
"symfony/event-dispatcher": "<4.4",
@ -3882,7 +3881,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.3.10"
"source": "https://github.com/symfony/console/tree/v5.3.11"
},
"funding": [
{
@ -3898,20 +3897,20 @@
"type": "tidelift"
}
],
"time": "2021-10-26T09:30:15+00:00"
"time": "2021-11-21T19:41:05+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.4.0",
"version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627"
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"reference": "5f38c8804a9e97d23e0c8d63341088cd8a22d627",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"reference": "6f981ee24cf69ee7ce9736146d1c57c2780598a8",
"shasum": ""
},
"require": {
@ -3920,7 +3919,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -3949,7 +3948,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.4.0"
"source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.0"
},
"funding": [
{
@ -3965,7 +3964,7 @@
"type": "tidelift"
}
],
"time": "2021-03-23T23:28:01+00:00"
"time": "2021-07-12T14:48:14+00:00"
},
{
"name": "symfony/filesystem",
@ -4032,16 +4031,16 @@
},
{
"name": "symfony/http-foundation",
"version": "v5.3.10",
"version": "v5.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "9f34f02e8a5fdc7a56bafe011cea1ce97300e54c"
"reference": "d1e7059ebeb0b8f9fe5eb5b26eacd2e3c1f371cc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/9f34f02e8a5fdc7a56bafe011cea1ce97300e54c",
"reference": "9f34f02e8a5fdc7a56bafe011cea1ce97300e54c",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/d1e7059ebeb0b8f9fe5eb5b26eacd2e3c1f371cc",
"reference": "d1e7059ebeb0b8f9fe5eb5b26eacd2e3c1f371cc",
"shasum": ""
},
"require": {
@ -4085,7 +4084,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-foundation/tree/v5.3.10"
"source": "https://github.com/symfony/http-foundation/tree/v5.3.11"
},
"funding": [
{
@ -4101,7 +4100,7 @@
"type": "tidelift"
}
],
"time": "2021-10-11T15:41:55+00:00"
"time": "2021-11-04T16:37:19+00:00"
},
{
"name": "symfony/polyfill-ctype",
@ -4670,16 +4669,16 @@
},
{
"name": "symfony/routing",
"version": "v5.3.7",
"version": "v5.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/routing.git",
"reference": "be865017746fe869007d94220ad3f5297951811b"
"reference": "fcbc2b81d55984f04bb704c2269755fa5aaf5cca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/be865017746fe869007d94220ad3f5297951811b",
"reference": "be865017746fe869007d94220ad3f5297951811b",
"url": "https://api.github.com/repos/symfony/routing/zipball/fcbc2b81d55984f04bb704c2269755fa5aaf5cca",
"reference": "fcbc2b81d55984f04bb704c2269755fa5aaf5cca",
"shasum": ""
},
"require": {
@ -4740,7 +4739,7 @@
"url"
],
"support": {
"source": "https://github.com/symfony/routing/tree/v5.3.7"
"source": "https://github.com/symfony/routing/tree/v5.3.11"
},
"funding": [
{
@ -4756,25 +4755,29 @@
"type": "tidelift"
}
],
"time": "2021-08-04T21:42:42+00:00"
"time": "2021-11-04T16:37:19+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.4.0",
"version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb"
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
"reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"reference": "1ab11b933cd6bc5464b08e81e2c5b07dec58b0fc",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1"
"psr/container": "^1.1",
"symfony/deprecation-contracts": "^2.1"
},
"conflict": {
"ext-psr": "<1.1|>=2"
},
"suggest": {
"symfony/service-implementation": ""
@ -4782,7 +4785,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -4819,7 +4822,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.4.0"
"source": "https://github.com/symfony/service-contracts/tree/v2.5.0"
},
"funding": [
{
@ -4835,7 +4838,7 @@
"type": "tidelift"
}
],
"time": "2021-04-01T10:43:52+00:00"
"time": "2021-11-04T16:48:04+00:00"
},
{
"name": "symfony/string",
@ -4922,16 +4925,16 @@
},
{
"name": "symfony/translation",
"version": "v5.3.10",
"version": "v5.3.11",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation.git",
"reference": "6ef197aea2ac8b9cd63e0da7522b3771714035aa"
"reference": "17a965c8f3b1b348cf15d903ac53942984561f8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation/zipball/6ef197aea2ac8b9cd63e0da7522b3771714035aa",
"reference": "6ef197aea2ac8b9cd63e0da7522b3771714035aa",
"url": "https://api.github.com/repos/symfony/translation/zipball/17a965c8f3b1b348cf15d903ac53942984561f8a",
"reference": "17a965c8f3b1b348cf15d903ac53942984561f8a",
"shasum": ""
},
"require": {
@ -4997,7 +5000,7 @@
"description": "Provides tools to internationalize your application",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/translation/tree/v5.3.10"
"source": "https://github.com/symfony/translation/tree/v5.3.11"
},
"funding": [
{
@ -5013,20 +5016,20 @@
"type": "tidelift"
}
],
"time": "2021-10-10T06:43:24+00:00"
"time": "2021-11-04T16:37:19+00:00"
},
{
"name": "symfony/translation-contracts",
"version": "v2.4.0",
"version": "v2.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/translation-contracts.git",
"reference": "95c812666f3e91db75385749fe219c5e494c7f95"
"reference": "d28150f0f44ce854e942b671fc2620a98aae1b1e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/95c812666f3e91db75385749fe219c5e494c7f95",
"reference": "95c812666f3e91db75385749fe219c5e494c7f95",
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/d28150f0f44ce854e942b671fc2620a98aae1b1e",
"reference": "d28150f0f44ce854e942b671fc2620a98aae1b1e",
"shasum": ""
},
"require": {
@ -5038,7 +5041,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
@ -5075,7 +5078,7 @@
"standards"
],
"support": {
"source": "https://github.com/symfony/translation-contracts/tree/v2.4.0"
"source": "https://github.com/symfony/translation-contracts/tree/v2.5.0"
},
"funding": [
{
@ -5091,7 +5094,7 @@
"type": "tidelift"
}
],
"time": "2021-03-23T23:28:01+00:00"
"time": "2021-08-17T14:20:01+00:00"
},
{
"name": "voku/portable-ascii",

Loading…
Cancel
Save