1
0
Fork 0
mirror of https://git.jami.net/savoirfairelinux/jami-client-qt.git synced 2025-04-21 21:52:03 +02:00

PluginView: refactor the ui to a better view

Gitlab: #1306

Change-Id: Ic3d952408c352715f2cd611dad63cf92cfb81ff0
This commit is contained in:
Xavier Jouslin de Noray 2023-08-08 11:55:20 -04:00
parent 8c728374a7
commit b1ca6cf861
24 changed files with 437 additions and 237 deletions

View file

@ -8,28 +8,34 @@
.st2{fill:url(#SVGID_3_);}
.st3{fill:url(#SVGID_4_);}
</style>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-12.6549" y1="165.4979" x2="165.4206" y2="343.5734">
<stop offset="0" style="stop-color:#3A3A3A"/>
<stop offset="1" style="stop-color:#818181"/>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-12.625" y1="262.475" x2="165.425" y2="84.425" gradientTransform="matrix(1 0 0 -1 0 428)">
<stop offset="0" style="stop-color:#7E7E7E"/>
<stop offset="1" style="stop-color:#E9FFFF"/>
</linearGradient>
<path class="st0" d="M1.6,154v21.5v1.4c0.2,0,0.4,0,0.6,0c21.8,0,39.5,17.7,39.5,39.5c0,21.8-17.7,39.5-39.5,39.5
c-0.2,0-0.4,0-0.6,0V408H101V152c0.2,0.1,0.3,0.1,0.5,0.2V51.4L1.6,154z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="227.3426" y1="84.8295" x2="405.4313" y2="262.9182">
<stop offset="0" style="stop-color:#3A3A3A"/>
<stop offset="1" style="stop-color:#717171"/>
<path class="st0" d="M1.6,154v21.5v1.4c0.2,0,0.4,0,0.6,0c21.8,0,39.5,17.7,39.5,39.5S24,255.9,2.2,255.9c-0.2,0-0.4,0-0.6,0V408
H101V152c0.2,0.1,0.3,0.1,0.5,0.2V51.4L1.6,154z"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="227.375" y1="343.175" x2="405.475" y2="165.075" gradientTransform="matrix(1 0 0 -1 0 428)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.3476" style="stop-color:#9B9B9B"/>
<stop offset="0.525" style="stop-color:#A1A3A3"/>
<stop offset="0.6639" style="stop-color:#ABB0B0"/>
<stop offset="0.7828" style="stop-color:#BAC3C3"/>
<stop offset="0.8889" style="stop-color:#CDDCDC"/>
<stop offset="0.9845" style="stop-color:#E5F9F9"/>
<stop offset="1" style="stop-color:#E9FFFF"/>
</linearGradient>
<path class="st1" d="M386.9,176.8L386.9,176.8l0-157.8h-93.7v256c-0.1-0.1-0.3-0.1-0.4-0.2v100.8l94.2-96.7v-23.2h0
<path class="st1" d="M386.9,176.8L386.9,176.8V19h-93.7v256c-0.1-0.1-0.3-0.1-0.4-0.2v100.8l94.2-96.7v-23.2l0,0
c21.8,0,39.5-17.7,39.5-39.5C426.4,194.5,408.7,176.8,386.9,176.8z"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="1.6097" y1="86.4966" x2="395.2845" y2="86.4966">
<stop offset="0" style="stop-color:#818181"/>
<stop offset="1" style="stop-color:#3A3A3A"/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="1.6" y1="341.5" x2="395.2748" y2="341.5" gradientTransform="matrix(1 0 0 -1 0 428)">
<stop offset="0" style="stop-color:#999999"/>
<stop offset="0.9889" style="stop-color:#E9FFFF"/>
</linearGradient>
<path class="st2" d="M181.3,19C126.4,19,1.6,31.5,1.6,154c0,0,49.3-42.7,136.9-25s160.9-0.7,207.6-49.1
c18.6-19.3,32.4-39.6,40.2-60.9H181.3z"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-553.2536" y1="-1072.2665" x2="-159.5788" y2="-1072.2665" gradientTransform="matrix(-1 0 0 -1 -166.3346 -728.8083)">
<stop offset="0" style="stop-color:#818181"/>
<stop offset="1" style="stop-color:#3A3A3A"/>
<linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-723.2346" y1="1360.2583" x2="-329.5598" y2="1360.2583" gradientTransform="matrix(-1 0 0 1 -336.3346 -1016.8083)">
<stop offset="0" style="stop-color:#E9FFFF"/>
<stop offset="1" style="stop-color:#999999"/>
</linearGradient>
<path class="st3" d="M207.2,408c54.9,0,179.7-11.9,179.7-129.1c0,0-49.3,40.8-136.9,23.9c-87.6-16.9-160.9,0.7-207.6,47
<path class="st3" d="M207.2,408c54.9,0,179.7-11.9,179.7-129.1c0,0-49.3,40.8-136.9,23.9s-160.9,0.7-207.6,47
C23.8,368.3,10.1,387.6,2.2,408H207.2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

View file

@ -85,7 +85,7 @@ ItemDelegate {
id: prefLlabel
Layout.fillWidth: true
Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
Layout.leftMargin: 8
Layout.leftMargin: 20
text: preferenceName
color: JamiTheme.textColor
@ -103,7 +103,7 @@ ItemDelegate {
normalColor: JamiTheme.primaryBackgroundColor
Layout.alignment: Qt.AlignRight | Qt.AlingVCenter
Layout.rightMargin: 8
Layout.rightMargin: 20
Layout.preferredWidth: preferredSize
Layout.preferredHeight: preferredSize
imageColor: JamiTheme.textColor
@ -119,7 +119,7 @@ ItemDelegate {
visible: preferenceType === PreferenceItemListModel.SWITCH
Layout.alignment: Qt.AlignRight | Qt.AlingVCenter
Layout.rightMargin: 16
Layout.rightMargin: 20
Layout.preferredHeight: 30
Layout.preferredWidth: 30
checked: preferenceCurrentValue === "1"
@ -134,7 +134,7 @@ ItemDelegate {
visible: preferenceType === PreferenceItemListModel.LIST
Layout.preferredWidth: root.width / 2 - 8
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.rightMargin: 4
Layout.rightMargin: 20
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
@ -157,7 +157,7 @@ ItemDelegate {
buttontextHeightMargin: JamiTheme.buttontextHeightMargin
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.rightMargin: 4
Layout.rightMargin: 20
text: UtilsAdapter.fileName(preferenceCurrentValue)
toolTipText: JamiStrings.chooseImageFile
@ -176,7 +176,7 @@ ItemDelegate {
Layout.preferredWidth: root.width / 2 - 8
Layout.preferredHeight: 30
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
Layout.rightMargin: 4
Layout.rightMargin: 20
visible: preferenceType === PreferenceItemListModel.EDITTEXT
width: root.width / 2 - 8

View file

@ -31,7 +31,9 @@ Item {
property alias source: image.source
property alias status: image.status
property alias fillMode: image.fillMode
property alias cache: image.cache
property alias image: image
property alias mirror: image.mirror
property string color: "transparent"
property bool hovered: false

View file

@ -427,7 +427,6 @@ Item {
property string linkDescription: qsTr("This account is created and stored locally, if you want to use it on another device you have to link the new device to this account.")
property string linkAnotherDevice: qsTr("Link device")
// NameRegistrationDialog
property string setUsername: qsTr("Set username")
property string registeringName: qsTr("Registering name")
@ -625,9 +624,13 @@ Item {
property string editPreference: qsTr("Edit preference")
property string onOff: qsTr("On/Off")
property string choosePlugin: qsTr("Choose Plugin")
property string versionPlugin: qsTr("Version %1")
property string lastUpdate: qsTr("Last update %1")
property string by: qsTr("By %1")
property string proposedBy: qsTr("Proposed by %1")
// ProfilePage
property string information: qsTr("Information")
property string moreInformation: qsTr("More information")
property string profile: qsTr("Profile")
// RevokeDevicePasswordDialog

View file

@ -58,7 +58,9 @@ Item {
property color blackColor: "#000000"
property color redColor: "red"
property color whiteColor: "#ffffff"
property color darkBlueGreen: "#123F4A"
property color darkGreyColor: "#272727"
property color darkGreyColorOpacityFade: "#cc000000" // 80%
property color darkGreyColorOpacity: "#be272727" // 77%
property color tintedBlue: darkTheme ? lightTintedBlue : darkTintedBlue
property color lightTintedBlue: "#03B9E9"
@ -386,8 +388,12 @@ Item {
property real pluginHandlersPopupViewHeight: 200
property real pluginHandlersPopupViewDelegateHeight: 50
property color pluginDefaultBackgroundColor: "#666666"
property real remotePluginWidthDelegate: 350
property real remotePluginHeightDelegate: 400
property real remotePluginMinimumDelegateWidth: 430
property real remotePluginMinimumDelegateHeight: 260
property real remotePluginMaximumDelegateWidth: 645
property real remotePluginMaximumDelegateHeight: 390
property real remotePluginDelegateWidth: remotePluginMinimumDelegateWidth * baseZoom
property real remotePluginDelegateHeight: remotePluginMinimumDelegateHeight * baseZoom
property color pluginViewBackgroundColor: darkTheme ? "#000000" : "#F0EFEF"
property real secondaryDialogDimension: 500

View file

@ -29,9 +29,11 @@ Item {
property alias source: image.source
property string defaultImage: ""
property string downloadUrl: ""
property alias imageLayer: image.layer
property string fileExtension: downloadUrl.substring(downloadUrl.lastIndexOf("."), downloadUrl.length)
property string localPath: ""
property int imageFillMode: 0
property alias image: image
AnimatedImage {
id: image

View file

@ -420,7 +420,7 @@ Control {
icon.source: JamiResources.plugins_24dp_svg
icon.color: "white"
text: JamiStrings.viewPlugin
enabled: PluginAdapter.isEnabled && PluginAdapter.callMediaHandlersListCount
enabled: PluginAdapter.callMediaHandlersListCount
onEnabledChanged: CallOverlayModel.setEnabled(this, pluginsAction.enabled)
},
Action {

View file

@ -221,7 +221,7 @@ Rectangle {
JamiPushButton {
id: selectPluginButton
visible: PluginAdapter.isEnabled && PluginAdapter.chatHandlersListCount && interactionButtonsVisibility
visible: PluginAdapter.chatHandlersListCount && interactionButtonsVisibility
source: JamiResources.plugins_24dp_svg
toolTipText: JamiStrings.showPlugins

View file

@ -131,7 +131,6 @@ Popup {
delegate: PluginHandlerItemDelegate {
id: pluginHandlerItemDelegate
visible: PluginModel.getPluginsEnabled()
width: pluginhandlerPickerListView.width
height: JamiTheme.pluginHandlersPopupViewDelegateHeight

View file

@ -44,13 +44,11 @@ PluginAdapter::PluginAdapter(LRCInstance* instance, QObject* parent, QString bas
{
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, pluginStoreListModel_, "PluginStoreListModel");
QML_REGISTERSINGLETONTYPE_POBJECT(NS_MODELS, pluginListModel_, "PluginListModel")
set_isEnabled(lrcInstance_->pluginModel().getPluginsEnabled());
updateHandlersListCount();
connect(&lrcInstance_->pluginModel(),
&lrc::api::PluginModel::modelUpdated,
this,
&PluginAdapter::updateHandlersListCount);
connect(this, &PluginAdapter::isEnabledChanged, this, &PluginAdapter::updateHandlersListCount);
connect(pluginVersionManager_,
&PluginVersionManager::versionStatusChanged,
pluginListModel_,
@ -75,6 +73,10 @@ PluginAdapter::PluginAdapter(LRCInstance* instance, QObject* parent, QString bas
&PluginListModel::setVersionStatus,
pluginStoreListModel_,
&PluginStoreListModel::onVersionStatusChanged);
connect(pluginVersionManager_,
&PluginVersionManager::newVersionAvailable,
pluginListModel_,
&PluginListModel::onNewVersionAvailable);
getPluginsFromStore();
}
@ -177,13 +179,8 @@ PluginAdapter::getPluginPreferencesCategories(const QString& pluginId,
void
PluginAdapter::updateHandlersListCount()
{
if (isEnabled_) {
set_callMediaHandlersListCount(lrcInstance_->pluginModel().getCallMediaHandlers().size());
set_chatHandlersListCount(lrcInstance_->pluginModel().getChatHandlers().size());
} else {
set_callMediaHandlersListCount(0);
set_chatHandlersListCount(0);
}
}
void
@ -203,3 +200,9 @@ PluginAdapter::getIconUrl(const QString& pluginId) const
{
return baseUrl_ + "/icons/" + pluginId + "?arch=" + Utils::getPlatformString();
}
QString
PluginAdapter::getBackgroundImageUrl(const QString& pluginId) const
{
return baseUrl_ + "/backgrounds/" + pluginId + "?arch=" + Utils::getPlatformString();
}

View file

@ -38,7 +38,6 @@ class PluginAdapter final : public QmlAdapterBase
Q_OBJECT
QML_PROPERTY(int, callMediaHandlersListCount)
QML_PROPERTY(int, chatHandlersListCount)
QML_PROPERTY(bool, isEnabled)
public:
explicit PluginAdapter(LRCInstance* instance,
@ -55,6 +54,7 @@ public:
Q_INVOKABLE void cancelDownload(const QString& pluginId);
Q_INVOKABLE void setAutoUpdate(bool state);
Q_INVOKABLE QString getIconUrl(const QString& pluginId) const;
Q_INVOKABLE QString getBackgroundImageUrl(const QString& pluginId) const;
protected:
Q_INVOKABLE QVariant getMediaHandlerSelectableModel(const QString& callId);

View file

@ -62,16 +62,24 @@ PluginListModel::data(const QModelIndex& index, int role) const
switch (role) {
case Role::PluginName:
return QVariant(details.name);
case Role::PluginVersion:
return QVariant(details.version);
case Role::PluginDescription:
return QVariant(details.description);
case Role::PluginId:
return QVariant(installedPlugins_.at(index.row()));
case Role::PluginIcon:
return QVariant(details.iconPath);
case Role::PluginImage:
return QVariant(details.imagePath);
case Role::IsLoaded:
return QVariant(details.loaded);
case Role::PluginAuthor:
return QVariant(details.author);
case Role::Status:
return QVariant(pluginStatus_.value(installedPlugins_.at(index.row())));
case Role::NewPluginAvailable:
return QVariant(newVersionAvailable_.value(installedPlugins_.at(index.row())));
}
return QVariant();
}
@ -83,9 +91,13 @@ PluginListModel::roleNames() const
roles[PluginName] = "PluginName";
roles[PluginId] = "PluginId";
roles[PluginIcon] = "PluginIcon";
roles[PluginImage] = "PluginImage";
roles[PluginVersion] = "PluginVersion";
roles[PluginAuthor] = "PluginAuthor";
roles[IsLoaded] = "IsLoaded";
roles[Status] = "Status";
roles[PluginDescription] = "PluginDescription";
roles[NewPluginAvailable] = "NewPluginAvailable";
return roles;
}
@ -164,6 +176,41 @@ PluginListModel::filterPlugins(VectorString& list) const
list.cend());
}
void
PluginListModel::onNewVersionAvailable(const QString& pluginId, const QString& version)
{
// check if pluginId exists in installedPlugins_
auto pluginIndex = -1;
for (auto& p : installedPlugins_) {
auto details = lrcInstance_->pluginModel().getPluginDetails(p);
if (details.name == pluginId) {
pluginIndex = installedPlugins_.indexOf(p, -1);
break;
}
}
if (pluginIndex == -1) {
return;
}
newVersionAvailable_[pluginId] = version;
pluginChanged(pluginIndex);
}
void
PluginListModel::deleteLatestVersion(const QString& pluginId)
{
auto pluginIndex = -1;
for (auto& p : installedPlugins_) {
auto details = lrcInstance_->pluginModel().getPluginDetails(p);
if (details.name == pluginId) {
pluginIndex = installedPlugins_.indexOf(p, -1);
break;
}
}
if (pluginIndex == -1) {
return;
}
newVersionAvailable_.remove(pluginId);
}
void
PluginListModel::onVersionStatusChanged(const QString& pluginId, PluginStatus::Role status)
{

View file

@ -32,7 +32,11 @@ public:
PluginName = Qt::UserRole + 1,
PluginDescription,
PluginId,
PluginVersion,
PluginAuthor,
PluginImage,
PluginIcon,
NewPluginAvailable,
IsLoaded,
Status
};
@ -60,6 +64,7 @@ public:
Q_INVOKABLE void pluginChanged(int index);
Q_INVOKABLE void addPlugin();
Q_INVOKABLE void disableAllPlugins();
Q_INVOKABLE void deleteLatestVersion(const QString& pluginId);
Q_SIGNALS:
void versionCheckRequested(const QString& pluginId);
@ -68,10 +73,12 @@ Q_SIGNALS:
void disabled(const QString& pluginId);
public Q_SLOTS:
void onVersionStatusChanged(const QString& pluginId, PluginStatus::Role status);
void onNewVersionAvailable(const QString& pluginId, const QString& version);
private:
LRCInstance* lrcInstance_ = nullptr;
void filterPlugins(VectorString& list) const;
VectorString installedPlugins_ {};
QMap<QString, PluginStatus::Role> pluginStatus_ {};
QMap<QString, QString> newVersionAvailable_ {};
};

View file

@ -68,6 +68,7 @@ public Q_SLOTS:
Q_SIGNALS:
void versionStatusChanged(const QString& pluginId, PluginStatus::Role status);
void newVersionAvailable(const QString& pluginId, const QString& version);
private:
QString baseUrl;

View file

@ -34,6 +34,9 @@ ItemDelegate {
property string pluginAuthor
property string pluginShortDescription
property int pluginStatus
property string backgroundLocalPath: UtilsAdapter.getCachePath() + '/backgrounds/' + pluginName + '.jpg'
property string iconLocalPath: UtilsAdapter.getCachePath() + '/icons/' + pluginName + '.svg'
readonly property real scalingFactor: 1 + hovered * 0.02
property string installButtonStatus: {
switch (pluginStatus) {
case PluginStatus.DOWNLOADING:
@ -52,8 +55,6 @@ ItemDelegate {
}
}
background: null
function presentErrorMessage() {
viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
"title": JamiStrings.installationFailed,
@ -69,9 +70,35 @@ ItemDelegate {
anchors.fill: parent
radius: 5
}
background: null
Page {
id: plugin
anchors.fill: parent
background: CachedImage {
id: background
defaultImage: JamiResources.default_plugin_background_jpg
downloadUrl: PluginAdapter.getBackgroundImageUrl(pluginName)
anchors.fill: parent
localPath: root.localPath === undefined ? '' : root.localPath
imageFillMode: Image.PreserveAspectCrop
LinearGradient {
id: gradient
anchors.fill: parent
start: Qt.point(0, height / 3)
gradient: Gradient {
GradientStop {
position: 0.0
color: JamiTheme.transparentColor
}
GradientStop {
position: 1.0
color: JamiTheme.darkGreyColorOpacityFade
}
}
}
}
layer {
enabled: true
effect: OpacityMask {
@ -81,12 +108,8 @@ ItemDelegate {
header: Control {
leftPadding: 20
rightPadding: 5
bottomPadding: 20
topPadding: 5
background: Rectangle {
id: headerBackground
color: hovered ? Qt.lighter(pluginBackground, 1.9) : Qt.lighter(pluginBackground, 2)
}
bottomPadding: 20
contentItem: ColumnLayout {
SpinningAnimation {
id: buttonContainer
@ -96,7 +119,7 @@ ItemDelegate {
Layout.topMargin: 2
Layout.preferredHeight: install.height
Layout.preferredWidth: install.width
color: "black"
color: JamiTheme.whiteColor
outerCutRadius: install.radius
spinningAnimationDuration: 5000
mode: {
@ -109,9 +132,10 @@ ItemDelegate {
MaterialButton {
id: install
hoverEnabled: pluginStatus !== PluginStatus.INSTALLING
secHoveredColor: Qt.darker(headerBackground.color, 1.1)
buttontextHeightMargin: 10.0
secHoveredColor: JamiTheme.darkBlueGreen
radius: JamiTheme.chatViewHeaderButtonRadius
TextMetrics {
id: installTextSize
@ -120,7 +144,7 @@ ItemDelegate {
font.capitalization: Font.Medium
text: install.text
}
contentColorProvider: "black"
contentColorProvider: JamiTheme.whiteColor
onClicked: installPlugin()
secondary: true
preferredWidth: installTextSize.width + JamiTheme.buttontextWizzardPadding
@ -139,56 +163,24 @@ ItemDelegate {
}
}
RowLayout {
spacing: 10
Layout.alignment: Qt.AlignCenter
CachedImage {
id: icon
defaultImage: JamiResources.plugins_default_icon_svg
onSourceChanged: {
if (source == defaultImage) {
pluginBackground = JamiTheme.pluginDefaultBackgroundColor;
return;
}
pluginBackground = PluginStoreListModel.computeAverageColorOfImage(source);
}
width: 55
height: 55
width: 65
height: 65
downloadUrl: PluginAdapter.getIconUrl(pluginName)
fileExtension: '.svg'
localPath: UtilsAdapter.getCachePath() + '/plugins/' + pluginName + '.svg'
}
ColumnLayout {
width: parent.width
Label {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
text: pluginName
font.kerning: true
color: "black"
font.pointSize: JamiTheme.tinyCreditsTextSize
textFormat: Text.PlainText
wrapMode: Text.WrapAnywhere
}
// Label {
// Layout.fillWidth: true
// color: "black"
// text: pluginShortDescription
// font.pointSize: JamiTheme.settingsFontSize
// textFormat: Text.PlainText
// wrapMode: Text.WordWrap
// }
localPath: root.iconLocalPath
}
}
}
}
Rectangle {
id: contentContainer
anchors.fill: parent
color: hovered ? JamiTheme.smartListHoveredColor : JamiTheme.pluginViewBackgroundColor
}
JamiFlickable {
anchors.fill: parent
anchors.margins: 20
contentHeight: description.height
anchors.rightMargin: 20
anchors.leftMargin: 20
anchors.bottomMargin: 5
contentHeight: body.height
clip: true
flickableDirection: Flickable.VerticalFlick
ScrollBar.vertical: JamiScrollBar {
@ -197,12 +189,24 @@ ItemDelegate {
}
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ColumnLayout {
id: body
width: parent.width
Label {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter
text: pluginName
font.kerning: true
font.bold: true
color: JamiTheme.whiteColor
font.pixelSize: hovered ? JamiTheme.popuptextSize * scalingFactor : JamiTheme.popuptextSize
textFormat: Text.PlainText
wrapMode: Text.WrapAnywhere
}
Text {
id: description
Layout.preferredWidth: contentContainer.width
font.pixelSize: JamiTheme.popuptextSize
color: JamiTheme.textColor
Layout.fillWidth: true
font.pixelSize: hovered ? JamiTheme.popuptextSize * scalingFactor : JamiTheme.popuptextSize
color: JamiTheme.whiteColor
text: pluginDescription
wrapMode: Text.WordWrap
horizontalAlignment: Qt.AlignLeft
@ -213,21 +217,19 @@ ItemDelegate {
}
}
footer: Control {
padding: 20
background: Rectangle {
color: hovered ? JamiTheme.smartListHoveredColor : JamiTheme.pluginViewBackgroundColor
}
leftPadding: 20
bottomPadding: 20
rightPadding: 20
contentItem: Text {
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
Layout.topMargin: 8
Layout.leftMargin: 8
color: JamiTheme.textColor
color: JamiTheme.whiteColor
font.pointSize: JamiTheme.settingsFontSize
font.pixelSize: hovered ? JamiTheme.settingsFontSize * scalingFactor : JamiTheme.settingsFontSize
font.kerning: true
font.italic: true
text: "By " + pluginAuthor
text: JamiStrings.by.arg(pluginAuthor)
wrapMode: Text.WordWrap
verticalAlignment: Text.AlignVCenter
}

View file

@ -32,13 +32,13 @@ Rectangle {
if (pluginLoader.item !== undefined) {
return -1;
} else {
if (pluginListView.currentIndex === null) {
if (pluginListView.currentIndex === 0) {
return -1;
}
return pluginListView.currentIndex;
}
}
visible: PluginAdapter.isEnabled && count
visible: count
color: JamiTheme.secondaryBackgroundColor
ColumnLayout {
@ -48,7 +48,6 @@ Rectangle {
RowLayout {
Layout.preferredHeight: JamiTheme.settingsHeaderpreferredHeight
Layout.fillWidth: true
Layout.bottomMargin: 20
Layout.alignment: Qt.AlignRight
Label {
Layout.fillWidth: true
@ -58,7 +57,7 @@ Rectangle {
color: JamiTheme.textColor
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
verticalAlignment: Text.AlignBottom
}
HeaderToggleSwitch {
labelText: "auto update"

View file

@ -27,6 +27,7 @@ Rectangle {
id: root
property string accountId: ""
required property string pluginId
required property bool isLoaded
width: parent.width
property int count: pluginPreferenceView.count + pluginPreferenceViewCategory.count
@ -274,7 +275,7 @@ Rectangle {
onClicked: viewCoordinator.presentDialog(appWindow, "commoncomponents/SimpleMessageDialog.qml", {
"title": JamiStrings.resetPreferences,
"infoText": JamiStrings.pluginResetConfirmation.arg(pluginName),
"infoText": JamiStrings.pluginResetConfirmation.arg(pluginId),
"buttonTitles": [JamiStrings.optionOk, JamiStrings.optionCancel],
"buttonStyles": [SimpleMessageDialog.ButtonStyle.TintedBlue, SimpleMessageDialog.ButtonStyle.TintedBlack],
"buttonCallBacks": [function () {

View file

@ -18,11 +18,13 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import net.jami.Adapters 1.1
import Qt5Compat.GraphicalEffects
import SortFilterProxyModel 0.2
import net.jami.Models 1.1
import net.jami.Adapters 1.1
import net.jami.Constants 1.1
import "../../commoncomponents"
import "../../mainview/components"
Item {
id: root
@ -49,21 +51,47 @@ Item {
color: JamiTheme.pluginViewBackgroundColor
}
header: Control {
padding: 10
background: Rectangle {
color: JamiTheme.pluginViewBackgroundColor
id: preferenceHeader
width: root.width
background: ResponsiveImage {
id: background
anchors.fill: preferenceHeader
fillMode: Image.PreserveAspectCrop
source: PluginImage === "" ? JamiResources.default_plugin_background_jpg : "file:" + PluginImage
FastBlur {
anchors.fill: parent
source: background.image
radius: 64
}
LinearGradient {
id: gradient
anchors.fill: parent
start: Qt.point(0, height / 3)
gradient: Gradient {
GradientStop {
position: 0.0
color: JamiTheme.transparentColor
}
GradientStop {
position: 1.0
color: JamiTheme.darkGreyColorOpacityFade
}
}
}
}
contentItem: ColumnLayout {
width: parent.width
PushButton {
JamiPushButton {
id: closeButton
normalColor: "transparent"
hoveredColor: JamiTheme.smartListHoveredColor
normalColor: Qt.rgba(124, 124, 124, 0.36)
hoveredColor: Qt.rgba(124, 124, 124, 0.75)
Layout.alignment: Qt.AlignRight
Layout.topMargin: 10
Layout.rightMargin: 35
Layout.preferredWidth: JamiTheme.preferredFieldHeight
Layout.preferredHeight: childrenRect.height
imageColor: JamiTheme.textColor
imageColor: JamiTheme.blackColor
toolTipText: JamiStrings.closeSettings
preferredSize: 32
@ -73,26 +101,136 @@ Item {
}
}
RowLayout {
Layout.preferredWidth: parent.width
ResponsiveImage {
Layout.bottomMargin: 10
Layout.rightMargin: 10
containerWidth: 64
containerHeight: 64
Layout.alignment: Qt.AlignCenter
containerWidth: 100
containerHeight: 100
source: PluginIcon === "" ? JamiResources.plugins_default_icon_svg : "file:" + PluginIcon
}
Label {
Layout.leftMargin: 20
text: PluginName
font.pixelSize: JamiTheme.settingsTitlePixelSize
font.pixelSize: JamiTheme.settingsDescriptionPixelSize
font.kerning: true
color: JamiTheme.textColor
font.bold: true
color: JamiTheme.whiteColor
textFormat: Text.PlainText
}
Item {
Layout.fillHeight: true
JamiFlickable {
Layout.leftMargin: 20
Layout.bottomMargin: 20
Layout.preferredWidth: root.width
Layout.preferredHeight: childrenRect.height
Layout.minimumHeight: childrenRect.height
Layout.maximumHeight: 88
contentWidth: description.width
contentHeight: description.height
clip: true
boundsBehavior: Flickable.StopAtBounds
flickableDirection: Flickable.VerticalFlick
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical: ScrollBar {
id: scrollBar
policy: ScrollBar.AsNeeded
}
Text {
id: description
width: settings.width - (2 * scrollBar.width + 20)
text: PluginDescription
font.pixelSize: JamiTheme.popuptextSize
color: JamiTheme.whiteColor
wrapMode: Text.WordWrap
textFormat: Text.MarkdownText
}
}
}
}
Rectangle {
anchors.fill: parent
color: JamiTheme.primaryBackgroundColor
}
JamiFlickable {
anchors.fill: parent
width: root.width
contentHeight: contentItem.childrenRect.height
topMargin: 20
bottomMargin: JamiTheme.preferredSettingsBottomMarginSize
boundsBehavior: Flickable.StopAtBounds
ScrollBar.horizontal.visible: false
contentItem.children: ColumnLayout {
width: root.width
ColumnLayout {
width: parent.width
Label {
Layout.leftMargin: 20
Layout.fillWidth: true
text: JamiStrings.settings
font.pixelSize: JamiTheme.settingsDescriptionPixelSize
font.bold: true
font.kerning: true
color: JamiTheme.textColor
}
PluginPreferencesListView {
id: pluginGeneralSettingsView
Layout.fillWidth: true
pluginId: PluginId
isLoaded: IsLoaded
}
PluginPreferencesListView {
id: pluginAccountSettingsView
Layout.fillWidth: true
accountId: LRCInstance.currentAccountId
pluginId: PluginId
isLoaded: IsLoaded
}
}
Rectangle {
width: parent.width
height: childrenRect.height + 40
Layout.topMargin: 20
color: JamiTheme.pluginViewBackgroundColor
ColumnLayout {
width: parent.width
anchors.top: parent.top
anchors.left: parent.left
anchors.topMargin: 20
anchors.bottomMargin: 20
anchors.leftMargin: 20
Label {
Layout.fillWidth: true
text: JamiStrings.moreInformation
font.pixelSize: JamiTheme.settingsDescriptionPixelSize
font.bold: true
font.kerning: true
color: JamiTheme.textColor
}
Label {
Layout.fillWidth: true
text: JamiStrings.versionPlugin.arg(PluginVersion)
font.pixelSize: JamiTheme.headerFontSize
font.kerning: true
color: JamiTheme.textColor
}
Item {
width: parent.width
height: childrenRect.height
visible: Status === PluginStatus.UPDATABLE
Label {
width: parent.width
text: JamiStrings.lastUpdate.arg(NewPluginAvailable)
font.pixelSize: JamiTheme.headerFontSize
font.kerning: true
color: JamiTheme.textColor
}
Item {
width: parent.width
height: childrenRect.height
anchors.right: parent.right
anchors.rightMargin: 40
MaterialButton {
id: update
anchors.right: parent.right
@ -104,67 +242,34 @@ Item {
font.capitalization: Font.AllUppercase
text: JamiStrings.updateDialogTitle
}
visible: Status === PluginStatus.UPDATABLE
secondary: true
preferredWidth: updateTextSize.width
text: JamiStrings.updateDialogTitle
fontSize: 15
onClicked: {
PluginModel.deleteLatestVersion(PluginName);
PluginAdapter.installRemotePlugin(PluginName);
}
}
}
JamiFlickable {
}
Label {
visible: PluginAuthor !== ''
Layout.fillWidth: true
Layout.preferredHeight: childrenRect.height
Layout.minimumHeight: childrenRect.height
Layout.maximumHeight: 88
contentWidth: description.width
contentHeight: description.height
clip: true
flickableDirection: Flickable.VerticalFlick
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
ScrollBar.vertical: ScrollBar {
id: scrollBar
policy: ScrollBar.AsNeeded
}
Text {
id: description
width: settings.width - 2 * scrollBar.width
text: PluginDescription
font.pixelSize: JamiTheme.popuptextSize
color: JamiTheme.textColor
font.pointSize: JamiTheme.settingsFontSize
font.kerning: true
font.italic: true
text: JamiStrings.proposedBy.arg(PluginAuthor)
wrapMode: Text.WordWrap
textFormat: Text.PlainText
verticalAlignment: Text.AlignVCenter
}
}
}
}
Rectangle {
anchors.fill: parent
color: JamiTheme.primaryBackgroundColor
}
JamiFlickable {
anchors.fill: parent
contentHeight: contentItem.childrenRect.height
topMargin: JamiTheme.preferredSettingsBottomMarginSize
bottomMargin: JamiTheme.preferredSettingsBottomMarginSize
ScrollBar.horizontal.visible: false
contentItem.children: ColumnLayout {
width: root.width
PluginPreferencesListView {
id: pluginGeneralSettingsView
Layout.fillWidth: true
pluginId: PluginId
}
PluginPreferencesListView {
id: pluginAccountSettingsView
Layout.fillWidth: true
accountId: LRCInstance.currentAccountId
pluginId: PluginId
}
MaterialButton {
id: uninstallButton
Layout.topMargin: 20
Layout.alignment: Qt.AlignCenter
preferredWidth: JamiTheme.preferredFieldWidth

View file

@ -33,7 +33,28 @@ SettingsPageBase {
anchors.leftMargin: JamiTheme.preferredSettingsMarginSize
ColumnLayout {
id: generalSettings
Layout.maximumWidth: 3 * (JamiTheme.remotePluginWidthDelegate + 20)
Layout.maximumWidth: {
let width = 0;
if (JamiTheme.remotePluginDelegateWidth < JamiTheme.remotePluginMinimumDelegateWidth) {
width = 3 * (JamiTheme.remotePluginMinimumDelegateWidth + 20);
} else if (JamiTheme.remotePluginDelegateWidth > JamiTheme.remotePluginMaximumDelegateWidth) {
width = 3 * (JamiTheme.remotePluginMaximumDelegateWidth + 20);
} else {
width = 3 * (JamiTheme.remotePluginDelegateWidth + 20);
}
return pluginRemoteList.remotePluginHovered ? width + 10 : width;
}
Layout.minimumWidth: {
let width = 0;
if (JamiTheme.remotePluginDelegateWidth < JamiTheme.remotePluginMinimumDelegateWidth) {
width = JamiTheme.remotePluginMinimumDelegateWidth + 10;
} else if (JamiTheme.remotePluginDelegateWidth > JamiTheme.remotePluginMaximumDelegateWidth) {
width = JamiTheme.remotePluginMaximumDelegateWidth + 10;
} else {
width = JamiTheme.remotePluginDelegateWidth + 10;
}
return pluginRemoteList.remotePluginHovered ? width + 10 : width;
}
Layout.preferredWidth: parent.width
Layout.rightMargin: 80
spacing: JamiTheme.settingsBlockSpacing
@ -52,6 +73,7 @@ SettingsPageBase {
}
// View of available plugins in the store
PluginStoreListView {
id: pluginRemoteList
Layout.alignment: Qt.AlignBottom | Qt.AlignHCenter
Layout.fillWidth: true
}

View file

@ -25,7 +25,9 @@ import net.jami.Constants 1.1
import "../../commoncomponents"
ColumnLayout {
id: root
property bool storeAvailable: true
property bool remotePluginHovered: false
Component.onCompleted: {
PluginAdapter.getPluginsFromStore();
}
@ -53,14 +55,37 @@ ColumnLayout {
sourceComponent: Flow {
id: pluginStoreList
height: childrenRect.height
spacing: 20
spacing: 10
Repeater {
model: PluginStoreListModel
delegate: PluginAvailableDelagate {
onCountChanged: {
root.visible = count > 0
}
delegate: Item {
id: wrapper
function widthProvider() {
if (JamiTheme.remotePluginDelegateWidth < JamiTheme.remotePluginMinimumDelegateWidth) {
return JamiTheme.remotePluginMinimumDelegateWidth;
} else if (JamiTheme.remotePluginDelegateWidth > JamiTheme.remotePluginMaximumDelegateWidth) {
return JamiTheme.remotePluginMaximumDelegateWidth;
}
return JamiTheme.remotePluginDelegateWidth;
}
function heightProvider() {
if (JamiTheme.remotePluginDelegateHeight < JamiTheme.remotePluginMinimumDelegateHeight) {
return JamiTheme.remotePluginMinimumDelegateHeight;
} else if (JamiTheme.remotePluginDelegateHeight > JamiTheme.remotePluginMaximumDelegateHeight) {
return JamiTheme.remotePluginMaximumDelegateHeight;
}
return JamiTheme.remotePluginDelegateHeight;
}
width: widthProvider() + 10
height: heightProvider() + 6
PluginAvailableDelegate {
id: pluginItemDelegate
width: JamiTheme.remotePluginWidthDelegate
height: JamiTheme.remotePluginHeightDelegate
anchors.centerIn: parent
width: wrapper.widthProvider() * scalingFactor
height: wrapper.heightProvider() * scalingFactor
pluginName: Name
pluginIcon: IconPath
pluginDescription: Description
@ -71,6 +96,7 @@ ColumnLayout {
}
}
}
}
Loader {
Layout.fillWidth: true
Layout.alignment: Qt.AlignHCenter | Qt.AlignTop

View file

@ -43,7 +43,9 @@ struct PluginDetails
QString description = "";
QString path = "";
QString version = "";
QString author = "";
QString iconPath = "";
QString imagePath = "";
bool loaded = false;
};
@ -63,18 +65,6 @@ public:
PluginModel();
~PluginModel();
/**
* Enable/disable plugins
* @param if plugin enabled
*/
Q_INVOKABLE void setPluginsEnabled(bool enable);
/**
* Get if plugins are enabled
* @return plugins enabled
*/
Q_INVOKABLE bool getPluginsEnabled() const;
/**
* Get list of installed plugins
* @return plugins installed

View file

@ -67,24 +67,6 @@ PluginModel::PluginModel()
PluginModel::~PluginModel() {}
void
PluginModel::setPluginsEnabled(bool enable)
{
PluginManager::instance().setPluginsEnabled(enable);
if (!enable)
Q_EMIT chatHandlerStatusUpdated(false);
else
Q_EMIT chatHandlerStatusUpdated(getChatHandlers().size() > 0);
Q_EMIT modelUpdated();
}
bool
PluginModel::getPluginsEnabled() const
{
return PluginManager::instance().getPluginsEnabled();
}
VectorString
PluginModel::getInstalledPlugins() const
{
@ -111,6 +93,8 @@ PluginModel::getPluginDetails(const QString& path)
result.description = details["description"];
result.path = path;
result.iconPath = details["iconPath"];
result.imagePath = details["imagePath"];
result.author = details["author"];
result.version = details["version"];
}
if (!pluginsPath_.contains(result.id)) {
@ -127,7 +111,6 @@ PluginModel::getPluginDetails(const QString& path)
bool
PluginModel::installPlugin(const QString& jplPath, bool force)
{
if (getPluginsEnabled()) {
auto result = PluginManager::instance().installPlugin(jplPath, force);
Q_EMIT modelUpdated();
if (result != 0) {
@ -152,8 +135,6 @@ PluginModel::installPlugin(const QString& jplPath, bool force)
pluginsPath_[getPluginDetails(jplPath).id] = jplPath;
return result == 0;
}
return false;
}
bool
PluginModel::uninstallPlugin(const QString& rootPath)
@ -196,7 +177,7 @@ PluginModel::loadPlugin(const QString& path)
bool status = PluginManager::instance().loadPlugin(path);
Q_EMIT modelUpdated();
if (getChatHandlers().size() > 0)
Q_EMIT chatHandlerStatusUpdated(getPluginsEnabled());
Q_EMIT chatHandlerStatusUpdated(true);
return status;
}

View file

@ -64,7 +64,6 @@ Item {
spyDownloadSuccessful.wait()
compare(findChild(cachedImage,"image").source, Qt.url("file://"+localPath), "image source")
compare(findChild(cachedImage,"default_img").visible,false, "default_img visible")
}
@ -78,8 +77,7 @@ Item {
spyDownloadFailed.wait()
compare(findChild(cachedImage,"image").source,"", "image source")
compare(findChild(cachedImage,"image").visible,true, "default_img visible")
compare(findChild(cachedImage,"image").source,cachedImage.defaultImage, "image source")
}
}
}