}
}
- contentItem: ColumnLayout {
- ScrollView {
- Layout.fillWidth: true
- Layout.fillHeight: true
+ contentItem: ScrollView {
+ contentWidth: availableWidth
+ clip: true
- contentWidth: availableWidth
+ ColumnLayout {
+ id: moreMenu
- clip: true
+ property int rowIconWidth: 16
+ property int indicatorItemWidth: 20
+ property int indicatorSpacing: Style.standardSpacing
+ property int itemPadding: Style.smallSpacing
- ColumnLayout {
- id: moreMenu
+ width: parent.width
- property int rowIconWidth: 16
- property int indicatorItemWidth: 20
- property int indicatorSpacing: Style.standardSpacing
- property int itemPadding: Style.smallSpacing
-
- width: parent.width
-
- RowLayout {
- Layout.fillWidth: true
- height: visible ? implicitHeight : 0
- spacing: moreMenu.indicatorSpacing
-
- visible: root.isLinkShare
-
- Image {
- Layout.preferredWidth: moreMenu.indicatorItemWidth
- Layout.fillHeight: true
-
- verticalAlignment: Image.AlignVCenter
- horizontalAlignment: Image.AlignHCenter
- fillMode: Image.Pad
-
- source: "image://svgimage-custom-color/edit.svg/" + Style.menuBorder
- sourceSize.width: moreMenu.rowIconWidth
- sourceSize.height: moreMenu.rowIconWidth
- }
-
- NCInputTextField {
- id: linkShareLabelTextField
+ RowLayout {
+ Layout.fillWidth: true
+ height: visible ? implicitHeight : 0
+ spacing: moreMenu.indicatorSpacing
- Layout.fillWidth: true
- height: visible ? implicitHeight : 0
+ visible: root.isLinkShare
- text: root.linkShareLabel
- placeholderText: qsTr("Share label")
+ Image {
+ Layout.preferredWidth: moreMenu.indicatorItemWidth
+ Layout.fillHeight: true
- enabled: root.isLinkShare &&
- !root.waitingForLinkShareLabelChange
+ verticalAlignment: Image.AlignVCenter
+ horizontalAlignment: Image.AlignHCenter
+ fillMode: Image.Pad
- onAccepted: if(text !== root.linkShareLabel) {
- root.setLinkShareLabel(text);
- root.waitingForLinkShareLabelChange = true;
- }
-
- NCBusyIndicator {
- anchors.fill: parent
- visible: root.waitingForLinkShareLabelChange
- running: visible
- z: 1
- }
- }
+ source: "image://svgimage-custom-color/edit.svg/" + Style.menuBorder
+ sourceSize.width: moreMenu.rowIconWidth
+ sourceSize.height: moreMenu.rowIconWidth
}
- // On these checkables, the clicked() signal is called after
- // the check state changes.
- CheckBox {
- id: editingAllowedMenuItem
+ NCInputTextField {
+ id: linkShareLabelTextField
Layout.fillWidth: true
+ height: visible ? implicitHeight : 0
- spacing: moreMenu.indicatorSpacing
- padding: moreMenu.itemPadding
- indicator.width: moreMenu.indicatorItemWidth
- indicator.height: moreMenu.indicatorItemWidth
+ text: root.linkShareLabel
+ placeholderText: qsTr("Share label")
- checkable: true
- checked: root.editingAllowed
- text: qsTr("Allow editing")
- enabled: !root.waitingForEditingAllowedChange
+ enabled: root.isLinkShare &&
+ !root.waitingForLinkShareLabelChange
- onClicked: {
- root.toggleAllowEditing(checked);
- root.waitingForEditingAllowedChange = true;
+ onAccepted: if(text !== root.linkShareLabel) {
+ root.setLinkShareLabel(text);
+ root.waitingForLinkShareLabelChange = true;
}
NCBusyIndicator {
anchors.fill: parent
- visible: root.waitingForEditingAllowedChange
+ visible: root.waitingForLinkShareLabelChange
running: visible
z: 1
}
}
+ }
- CheckBox {
- id: passwordProtectEnabledMenuItem
+ // On these checkables, the clicked() signal is called after
+ // the check state changes.
+ CheckBox {
+ id: editingAllowedMenuItem
- Layout.fillWidth: true
+ Layout.fillWidth: true
- spacing: moreMenu.indicatorSpacing
- padding: moreMenu.itemPadding
- indicator.width: moreMenu.indicatorItemWidth
- indicator.height: moreMenu.indicatorItemWidth
+ spacing: moreMenu.indicatorSpacing
+ padding: moreMenu.itemPadding
+ indicator.width: moreMenu.indicatorItemWidth
+ indicator.height: moreMenu.indicatorItemWidth
- checkable: true
- checked: root.passwordProtectEnabled
- text: qsTr("Password protect")
- enabled: !root.waitingForPasswordProtectEnabledChange && !root.passwordEnforced
+ checkable: true
+ checked: root.editingAllowed
+ text: qsTr("Allow editing")
+ enabled: !root.waitingForEditingAllowedChange
- onClicked: {
- root.togglePasswordProtect(checked);
- root.waitingForPasswordProtectEnabledChange = true;
- }
+ onClicked: {
+ root.toggleAllowEditing(checked);
+ root.waitingForEditingAllowedChange = true;
+ }
- NCBusyIndicator {
- anchors.fill: parent
- visible: root.waitingForPasswordProtectEnabledChange
- running: visible
- z: 1
- }
+ NCBusyIndicator {
+ anchors.fill: parent
+ visible: root.waitingForEditingAllowedChange
+ running: visible
+ z: 1
}
+ }
- RowLayout {
- Layout.fillWidth: true
+ CheckBox {
+ id: passwordProtectEnabledMenuItem
- height: visible ? implicitHeight : 0
- spacing: moreMenu.indicatorSpacing
+ Layout.fillWidth: true
- visible: root.passwordProtectEnabled
+ spacing: moreMenu.indicatorSpacing
+ padding: moreMenu.itemPadding
+ indicator.width: moreMenu.indicatorItemWidth
+ indicator.height: moreMenu.indicatorItemWidth
- Image {
- Layout.preferredWidth: moreMenu.indicatorItemWidth
- Layout.fillHeight: true
+ checkable: true
+ checked: root.passwordProtectEnabled
+ text: qsTr("Password protect")
+ enabled: !root.waitingForPasswordProtectEnabledChange && !root.passwordEnforced
- verticalAlignment: Image.AlignVCenter
- horizontalAlignment: Image.AlignHCenter
- fillMode: Image.Pad
+ onClicked: {
+ root.togglePasswordProtect(checked);
+ root.waitingForPasswordProtectEnabledChange = true;
+ }
- source: "image://svgimage-custom-color/lock-https.svg/" + Style.menuBorder
- sourceSize.width: moreMenu.rowIconWidth
- sourceSize.height: moreMenu.rowIconWidth
- }
+ NCBusyIndicator {
+ anchors.fill: parent
+ visible: root.waitingForPasswordProtectEnabledChange
+ running: visible
+ z: 1
+ }
+ }
- NCInputTextField {
- id: passwordTextField
+ RowLayout {
+ Layout.fillWidth: true
- Layout.fillWidth: true
- height: visible ? implicitHeight : 0
+ height: visible ? implicitHeight : 0
+ spacing: moreMenu.indicatorSpacing
- text: root.password !== "" ? root.password : root.passwordPlaceholder
- enabled: root.passwordProtectEnabled &&
- !root.waitingForPasswordChange &&
- !root.waitingForPasswordProtectEnabledChange
+ visible: root.passwordProtectEnabled
- onAccepted: if(text !== root.password && text !== root.passwordPlaceholder) {
- passwordErrorBoxLoader.message = "";
- root.setPassword(text);
- root.waitingForPasswordChange = true;
- }
+ Image {
+ Layout.preferredWidth: moreMenu.indicatorItemWidth
+ Layout.fillHeight: true
- NCBusyIndicator {
- anchors.fill: parent
- visible: root.waitingForPasswordChange ||
- root.waitingForPasswordProtectEnabledChange
- running: visible
- z: 1
- }
+ verticalAlignment: Image.AlignVCenter
+ horizontalAlignment: Image.AlignHCenter
+ fillMode: Image.Pad
+
+ source: "image://svgimage-custom-color/lock-https.svg/" + Style.menuBorder
+ sourceSize.width: moreMenu.rowIconWidth
+ sourceSize.height: moreMenu.rowIconWidth
+ }
+
+ NCInputTextField {
+ id: passwordTextField
+
+ Layout.fillWidth: true
+ height: visible ? implicitHeight : 0
+
+ text: root.password !== "" ? root.password : root.passwordPlaceholder
+ enabled: root.passwordProtectEnabled &&
+ !root.waitingForPasswordChange &&
+ !root.waitingForPasswordProtectEnabledChange
+
+ onAccepted: if(text !== root.password && text !== root.passwordPlaceholder) {
+ passwordErrorBoxLoader.message = "";
+ root.setPassword(text);
+ root.waitingForPasswordChange = true;
+ }
+
+ NCBusyIndicator {
+ anchors.fill: parent
+ visible: root.waitingForPasswordChange ||
+ root.waitingForPasswordProtectEnabledChange
+ running: visible
+ z: 1
}
}
+ }
- Loader {
- id: passwordErrorBoxLoader
+ Loader {
+ id: passwordErrorBoxLoader
- property string message: ""
+ property string message: ""
- Layout.fillWidth: true
- height: message !== "" ? implicitHeight : 0
+ Layout.fillWidth: true
+ height: message !== "" ? implicitHeight : 0
+
+ active: message !== ""
+ visible: active
- active: message !== ""
- visible: active
+ sourceComponent: Item {
+ anchors.top: parent.top
+ anchors.left: parent.left
+ anchors.right: parent.right
+ // Artificially add vertical padding
+ implicitHeight: passwordErrorBox.implicitHeight + (Style.smallSpacing * 2)
- sourceComponent: Item {
- anchors.top: parent.top
+ ErrorBox {
+ id: passwordErrorBox
anchors.left: parent.left
anchors.right: parent.right
- // Artificially add vertical padding
- implicitHeight: passwordErrorBox.implicitHeight + (Style.smallSpacing * 2)
+ anchors.verticalCenter: parent.verticalCenter
- ErrorBox {
- id: passwordErrorBox
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
-
- text: passwordErrorBoxLoader.message
- }
+ text: passwordErrorBoxLoader.message
}
}
+ }
- CheckBox {
- id: expireDateEnabledMenuItem
+ CheckBox {
+ id: expireDateEnabledMenuItem
- Layout.fillWidth: true
+ Layout.fillWidth: true
- spacing: moreMenu.indicatorSpacing
- padding: moreMenu.itemPadding
- indicator.width: moreMenu.indicatorItemWidth
- indicator.height: moreMenu.indicatorItemWidth
+ spacing: moreMenu.indicatorSpacing
+ padding: moreMenu.itemPadding
+ indicator.width: moreMenu.indicatorItemWidth
+ indicator.height: moreMenu.indicatorItemWidth
- checkable: true
- checked: root.expireDateEnabled
- text: qsTr("Set expiration date")
- enabled: !root.waitingForExpireDateEnabledChange && !root.expireDateEnforced
+ checkable: true
+ checked: root.expireDateEnabled
+ text: qsTr("Set expiration date")
+ enabled: !root.waitingForExpireDateEnabledChange && !root.expireDateEnforced
- onClicked: {
- root.toggleExpirationDate(checked);
- root.waitingForExpireDateEnabledChange = true;
- }
+ onClicked: {
+ root.toggleExpirationDate(checked);
+ root.waitingForExpireDateEnabledChange = true;
+ }
- NCBusyIndicator {
- anchors.fill: parent
- visible: root.waitingForExpireDateEnabledChange
- running: visible
- z: 1
- }
+ NCBusyIndicator {
+ anchors.fill: parent
+ visible: root.waitingForExpireDateEnabledChange
+ running: visible
+ z: 1
}
+ }
- RowLayout {
- Layout.fillWidth: true
- height: visible ? implicitHeight : 0
- spacing: moreMenu.indicatorSpacing
+ RowLayout {
+ Layout.fillWidth: true
+ height: visible ? implicitHeight : 0
+ spacing: moreMenu.indicatorSpacing
- visible: root.expireDateEnabled
+ visible: root.expireDateEnabled
- Image {
- Layout.preferredWidth: moreMenu.indicatorItemWidth
- Layout.fillHeight: true
+ Image {
+ Layout.preferredWidth: moreMenu.indicatorItemWidth
+ Layout.fillHeight: true
- verticalAlignment: Image.AlignVCenter
- horizontalAlignment: Image.AlignHCenter
- fillMode: Image.Pad
+ verticalAlignment: Image.AlignVCenter
+ horizontalAlignment: Image.AlignHCenter
+ fillMode: Image.Pad
- source: "image://svgimage-custom-color/calendar.svg/" + Style.menuBorder
- sourceSize.width: moreMenu.rowIconWidth
- sourceSize.height: moreMenu.rowIconWidth
+ source: "image://svgimage-custom-color/calendar.svg/" + Style.menuBorder
+ sourceSize.width: moreMenu.rowIconWidth
+ sourceSize.height: moreMenu.rowIconWidth
+ }
+
+ // QML dates are essentially JavaScript dates, which makes them very finicky and unreliable.
+ // Instead, we exclusively deal with msecs from epoch time to make things less painful when editing.
+ // We only use the QML Date when showing the nice string to the user.
+ SpinBox {
+ id: expireDateSpinBox
+
+ // Work arounds the limitations of QML's 32 bit integer when handling msecs from epoch
+ // Instead, we handle everything as days since epoch
+ readonly property int dayInMSecs: 24 * 60 * 60 * 1000
+ readonly property int expireDateReduced: Math.floor(root.expireDate / dayInMSecs)
+ // Reset the model data after binding broken on user interact
+ onExpireDateReducedChanged: value = expireDateReduced
+
+ // We can't use JS's convenient Infinity or Number.MAX_VALUE as
+ // JS Number type is 64 bits, whereas QML's int type is only 32 bits
+ readonly property IntValidator intValidator: IntValidator {}
+ readonly property int maximumExpireDateReduced: root.expireDateEnforced ?
+ Math.floor(root.maximumExpireDate / dayInMSecs) :
+ intValidator.top
+ readonly property int minimumExpireDateReduced: {
+ const currentDate = new Date();
+ const minDateUTC = new Date(Date.UTC(currentDate.getFullYear(),
+ currentDate.getMonth(),
+ currentDate.getDate() + 1));
+ return Math.floor(minDateUTC / dayInMSecs) // Start of day at 00:00:0000 UTC
}
- // QML dates are essentially JavaScript dates, which makes them very finicky and unreliable.
- // Instead, we exclusively deal with msecs from epoch time to make things less painful when editing.
- // We only use the QML Date when showing the nice string to the user.
- SpinBox {
- id: expireDateSpinBox
-
- // Work arounds the limitations of QML's 32 bit integer when handling msecs from epoch
- // Instead, we handle everything as days since epoch
- readonly property int dayInMSecs: 24 * 60 * 60 * 1000
- readonly property int expireDateReduced: Math.floor(root.expireDate / dayInMSecs)
- // Reset the model data after binding broken on user interact
- onExpireDateReducedChanged: value = expireDateReduced
-
- // We can't use JS's convenient Infinity or Number.MAX_VALUE as
- // JS Number type is 64 bits, whereas QML's int type is only 32 bits
- readonly property IntValidator intValidator: IntValidator {}
- readonly property int maximumExpireDateReduced: root.expireDateEnforced ?
- Math.floor(root.maximumExpireDate / dayInMSecs) :
- intValidator.top
- readonly property int minimumExpireDateReduced: {
- const currentDate = new Date();
- const minDateUTC = new Date(Date.UTC(currentDate.getFullYear(),
- currentDate.getMonth(),
- currentDate.getDate() + 1));
- return Math.floor(minDateUTC / dayInMSecs) // Start of day at 00:00:0000 UTC
+ // Taken from Kalendar 22.08
+ // https://invent.kde.org/pim/kalendar/-/blob/release/22.08/src/contents/ui/KalendarUtils/dateutils.js
+ function parseDateString(dateString) {
+ function defaultParse() {
+ const defaultParsedDate = Date.fromLocaleDateString(Qt.locale(), dateString, Locale.NarrowFormat);
+ // JS always generates date in system locale, eliminate timezone difference to UTC
+ const msecsSinceEpoch = defaultParsedDate.getTime() - (defaultParsedDate.getTimezoneOffset() * 60 * 1000);
+ return new Date(msecsSinceEpoch);
}
- // Taken from Kalendar 22.08
- // https://invent.kde.org/pim/kalendar/-/blob/release/22.08/src/contents/ui/KalendarUtils/dateutils.js
- function parseDateString(dateString) {
- function defaultParse() {
- const defaultParsedDate = Date.fromLocaleDateString(Qt.locale(), dateString, Locale.NarrowFormat);
- // JS always generates date in system locale, eliminate timezone difference to UTC
- const msecsSinceEpoch = defaultParsedDate.getTime() - (defaultParsedDate.getTimezoneOffset() * 60 * 1000);
- return new Date(msecsSinceEpoch);
- }
-
- const dateStringDelimiterMatches = dateString.match(/\D/);
- if(dateStringDelimiterMatches.length === 0) {
- // Let the date method figure out this weirdness
- return defaultParse();
- }
-
- const dateStringDelimiter = dateStringDelimiterMatches[0];
-
- const localisedDateFormatSplit = Qt.locale().dateFormat(Locale.NarrowFormat).split(dateStringDelimiter);
- const localisedDateDayPosition = localisedDateFormatSplit.findIndex((x) => /d/gi.test(x));
- const localisedDateMonthPosition = localisedDateFormatSplit.findIndex((x) => /m/gi.test(x));
- const localisedDateYearPosition = localisedDateFormatSplit.findIndex((x) => /y/gi.test(x));
-
- let splitDateString = dateString.split(dateStringDelimiter);
- let userProvidedYear = splitDateString[localisedDateYearPosition]
-
- const dateNow = new Date();
- const stringifiedCurrentYear = dateNow.getFullYear().toString();
-
- // If we have any input weirdness, or if we have a fully-written year
- // (e.g. 2022 instead of 22) then use default parse
- if(splitDateString.length === 0 ||
- splitDateString.length > 3 ||
- userProvidedYear.length >= stringifiedCurrentYear.length) {
-
- return defaultParse();
- }
-
- let fullyWrittenYear = userProvidedYear.split("");
- const digitsToAdd = stringifiedCurrentYear.length - fullyWrittenYear.length;
- for(let i = 0; i < digitsToAdd; i++) {
- fullyWrittenYear.splice(i, 0, stringifiedCurrentYear[i])
- }
- fullyWrittenYear = fullyWrittenYear.join("");
-
- const fixedYearNum = Number(fullyWrittenYear);
- const monthIndexNum = Number(splitDateString[localisedDateMonthPosition]) - 1;
- const dayNum = Number(splitDateString[localisedDateDayPosition]);
-
- console.log(dayNum, monthIndexNum, fixedYearNum);
-
- // Modification: return date in UTC
- return new Date(Date.UTC(fixedYearNum, monthIndexNum, dayNum));
+ const dateStringDelimiterMatches = dateString.match(/\D/);
+ if(dateStringDelimiterMatches.length === 0) {
+ // Let the date method figure out this weirdness
+ return defaultParse();
}
- Layout.fillWidth: true
- height: visible ? implicitHeight : 0
-
-
- // We want all the internal benefits of the spinbox but don't actually want the
- // buttons, so set an empty item as a dummy
- up.indicator: Item {}
- down.indicator: Item {}
-
- padding: 0
- background: null
- contentItem: NCInputTextField {
- text: expireDateSpinBox.textFromValue(expireDateSpinBox.value, expireDateSpinBox.locale)
- readOnly: !expireDateSpinBox.editable
- validator: expireDateSpinBox.validator
- inputMethodHints: Qt.ImhFormattedNumbersOnly
- onAccepted: {
- expireDateSpinBox.value = expireDateSpinBox.valueFromText(text, expireDateSpinBox.locale);
- expireDateSpinBox.valueModified();
- }
- }
+ const dateStringDelimiter = dateStringDelimiterMatches[0];
+
+ const localisedDateFormatSplit = Qt.locale().dateFormat(Locale.NarrowFormat).split(dateStringDelimiter);
+ const localisedDateDayPosition = localisedDateFormatSplit.findIndex((x) => /d/gi.test(x));
+ const localisedDateMonthPosition = localisedDateFormatSplit.findIndex((x) => /m/gi.test(x));
+ const localisedDateYearPosition = localisedDateFormatSplit.findIndex((x) => /y/gi.test(x));
- value: expireDateReduced
- from: minimumExpireDateReduced
- to: maximumExpireDateReduced
+ let splitDateString = dateString.split(dateStringDelimiter);
+ let userProvidedYear = splitDateString[localisedDateYearPosition]
- textFromValue: (value, locale) => {
- const dateFromValue = new Date(value * dayInMSecs);
- return dateFromValue.toLocaleDateString(Qt.locale(), Locale.NarrowFormat);
+ const dateNow = new Date();
+ const stringifiedCurrentYear = dateNow.getFullYear().toString();
+
+ // If we have any input weirdness, or if we have a fully-written year
+ // (e.g. 2022 instead of 22) then use default parse
+ if(splitDateString.length === 0 ||
+ splitDateString.length > 3 ||
+ userProvidedYear.length >= stringifiedCurrentYear.length) {
+
+ return defaultParse();
}
- valueFromText: (text, locale) => {
- const dateFromText = parseDateString(text);
- return Math.floor(dateFromText.getTime() / dayInMSecs);
+
+ let fullyWrittenYear = userProvidedYear.split("");
+ const digitsToAdd = stringifiedCurrentYear.length - fullyWrittenYear.length;
+ for(let i = 0; i < digitsToAdd; i++) {
+ fullyWrittenYear.splice(i, 0, stringifiedCurrentYear[i])
}
+ fullyWrittenYear = fullyWrittenYear.join("");
+
+ const fixedYearNum = Number(fullyWrittenYear);
+ const monthIndexNum = Number(splitDateString[localisedDateMonthPosition]) - 1;
+ const dayNum = Number(splitDateString[localisedDateDayPosition]);
- editable: true
- inputMethodHints: Qt.ImhDate | Qt.ImhFormattedNumbersOnly
+ console.log(dayNum, monthIndexNum, fixedYearNum);
- enabled: root.expireDateEnabled &&
- !root.waitingForExpireDateChange &&
- !root.waitingForExpireDateEnabledChange
+ // Modification: return date in UTC
+ return new Date(Date.UTC(fixedYearNum, monthIndexNum, dayNum));
+ }
- onValueModified: {
- if (!enabled || !activeFocus) {
- return;
- }
+ Layout.fillWidth: true
+ height: visible ? implicitHeight : 0
- root.setExpireDate(value * dayInMSecs);
- root.waitingForExpireDateChange = true;
- }
- NCBusyIndicator {
- anchors.fill: parent
- visible: root.waitingForExpireDateEnabledChange ||
- root.waitingForExpireDateChange
- running: visible
- z: 1
+ // We want all the internal benefits of the spinbox but don't actually want the
+ // buttons, so set an empty item as a dummy
+ up.indicator: Item {}
+ down.indicator: Item {}
+
+ padding: 0
+ background: null
+ contentItem: NCInputTextField {
+ text: expireDateSpinBox.textFromValue(expireDateSpinBox.value, expireDateSpinBox.locale)
+ readOnly: !expireDateSpinBox.editable
+ validator: expireDateSpinBox.validator
+ inputMethodHints: Qt.ImhFormattedNumbersOnly
+ onAccepted: {
+ expireDateSpinBox.value = expireDateSpinBox.valueFromText(text, expireDateSpinBox.locale);
+ expireDateSpinBox.valueModified();
}
}
- }
- CheckBox {
- id: noteEnabledMenuItem
+ value: expireDateReduced
+ from: minimumExpireDateReduced
+ to: maximumExpireDateReduced
- Layout.fillWidth: true
+ textFromValue: (value, locale) => {
+ const dateFromValue = new Date(value * dayInMSecs);
+ return dateFromValue.toLocaleDateString(Qt.locale(), Locale.NarrowFormat);
+ }
+ valueFromText: (text, locale) => {
+ const dateFromText = parseDateString(text);
+ return Math.floor(dateFromText.getTime() / dayInMSecs);
+ }
- spacing: moreMenu.indicatorSpacing
- padding: moreMenu.itemPadding
- indicator.width: moreMenu.indicatorItemWidth
- indicator.height: moreMenu.indicatorItemWidth
+ editable: true
+ inputMethodHints: Qt.ImhDate | Qt.ImhFormattedNumbersOnly
- checkable: true
- checked: root.noteEnabled
- text: qsTr("Note to recipient")
- enabled: !root.waitingForNoteEnabledChange
+ enabled: root.expireDateEnabled &&
+ !root.waitingForExpireDateChange &&
+ !root.waitingForExpireDateEnabledChange
- onClicked: {
- root.toggleNoteToRecipient(checked);
- root.waitingForNoteEnabledChange = true;
+ onValueModified: {
+ if (!enabled || !activeFocus) {
+ return;
+ }
+
+ root.setExpireDate(value * dayInMSecs);
+ root.waitingForExpireDateChange = true;
}
NCBusyIndicator {
anchors.fill: parent
- visible: root.waitingForNoteEnabledChange
+ visible: root.waitingForExpireDateEnabledChange ||
+ root.waitingForExpireDateChange
running: visible
z: 1
}
}
+ }
- RowLayout {
- Layout.fillWidth: true
- height: visible ? implicitHeight : 0
- spacing: moreMenu.indicatorSpacing
+ CheckBox {
+ id: noteEnabledMenuItem
- visible: root.noteEnabled
+ Layout.fillWidth: true
- Image {
- Layout.preferredWidth: moreMenu.indicatorItemWidth
- Layout.fillHeight: true
+ spacing: moreMenu.indicatorSpacing
+ padding: moreMenu.itemPadding
+ indicator.width: moreMenu.indicatorItemWidth
+ indicator.height: moreMenu.indicatorItemWidth
- verticalAlignment: Image.AlignVCenter
- horizontalAlignment: Image.AlignHCenter
- fillMode: Image.Pad
+ checkable: true
+ checked: root.noteEnabled
+ text: qsTr("Note to recipient")
+ enabled: !root.waitingForNoteEnabledChange
- source: "image://svgimage-custom-color/edit.svg/" + Style.menuBorder
- sourceSize.width: moreMenu.rowIconWidth
- sourceSize.height: moreMenu.rowIconWidth
- }
+ onClicked: {
+ root.toggleNoteToRecipient(checked);
+ root.waitingForNoteEnabledChange = true;
+ }
- NCInputTextEdit {
- id: noteTextEdit
+ NCBusyIndicator {
+ anchors.fill: parent
+ visible: root.waitingForNoteEnabledChange
+ running: visible
+ z: 1
+ }
+ }
- Layout.fillWidth: true
- height: visible ? Math.max(Style.talkReplyTextFieldPreferredHeight, contentHeight) : 0
- submitButton.height: Math.min(Style.talkReplyTextFieldPreferredHeight, height - 2)
+ RowLayout {
+ Layout.fillWidth: true
+ height: visible ? implicitHeight : 0
+ spacing: moreMenu.indicatorSpacing
- text: root.note
- enabled: root.noteEnabled &&
- !root.waitingForNoteChange &&
- !root.waitingForNoteEnabledChange
+ visible: root.noteEnabled
- onEditingFinished: if(text !== root.note) {
- root.setNote(text);
- root.waitingForNoteChange = true;
- }
+ Image {
+ Layout.preferredWidth: moreMenu.indicatorItemWidth
+ Layout.fillHeight: true
- NCBusyIndicator {
- anchors.fill: parent
- visible: root.waitingForNoteChange ||
- root.waitingForNoteEnabledChange
- running: visible
- z: 1
- }
- }
- }
+ verticalAlignment: Image.AlignVCenter
+ horizontalAlignment: Image.AlignHCenter
+ fillMode: Image.Pad
- CustomButton {
- height: Style.standardPrimaryButtonHeight
-
- imageSource: "image://svgimage-custom-color/close.svg/" + Style.errorBoxBackgroundColor
- imageSourceHover: "image://svgimage-custom-color/close.svg/" + Style.ncHeaderTextColor
- text: qsTr("Unshare")
- textColor: Style.errorBoxBackgroundColor
- textColorHovered: "white"
- contentsFont.bold: true
- bgNormalColor: Style.buttonBackgroundColor
- bgHoverColor: Style.errorBoxBackgroundColor
- bgNormalOpacity: 1.0
- bgHoverOpacity: 1.0
-
- onClicked: root.deleteShare()
+ source: "image://svgimage-custom-color/edit.svg/" + Style.menuBorder
+ sourceSize.width: moreMenu.rowIconWidth
+ sourceSize.height: moreMenu.rowIconWidth
}
- CustomButton {
- height: Style.standardPrimaryButtonHeight
+ NCInputTextEdit {
+ id: noteTextEdit
- imageSource: "image://svgimage-custom-color/add.svg/" + Style.ncBlue
- imageSourceHover: "image://svgimage-custom-color/add.svg/" + Style.ncHeaderTextColor
- text: qsTr("Add another link")
- textColor: Style.ncBlue
- textColorHovered: Style.ncHeaderTextColor
- contentsFont.bold: true
- bgNormalColor: Style.buttonBackgroundColor
- bgHoverColor: Style.ncBlue
- bgNormalOpacity: 1.0
- bgHoverOpacity: 1.0
+ Layout.fillWidth: true
+ height: visible ? Math.max(Style.talkReplyTextFieldPreferredHeight, contentHeight) : 0
+ submitButton.height: Math.min(Style.talkReplyTextFieldPreferredHeight, height - 2)
+
+ text: root.note
+ enabled: root.noteEnabled &&
+ !root.waitingForNoteChange &&
+ !root.waitingForNoteEnabledChange
- visible: root.isLinkShare && root.canCreateLinkShares
- enabled: visible
+ onEditingFinished: if(text !== root.note) {
+ root.setNote(text);
+ root.waitingForNoteChange = true;
+ }
- onClicked: root.createNewLinkShare()
+ NCBusyIndicator {
+ anchors.fill: parent
+ visible: root.waitingForNoteChange ||
+ root.waitingForNoteEnabledChange
+ running: visible
+ z: 1
+ }
}
}
- }
-
- RowLayout {
- Layout.fillWidth: true
+ CustomButton {
+ height: Style.standardPrimaryButtonHeight
+
+ imageSource: "image://svgimage-custom-color/close.svg/" + Style.errorBoxBackgroundColor
+ imageSourceHover: "image://svgimage-custom-color/close.svg/" + Style.ncHeaderTextColor
+ text: qsTr("Unshare")
+ textColor: Style.errorBoxBackgroundColor
+ textColorHovered: "white"
+ contentsFont.bold: true
+ bgNormalColor: Style.buttonBackgroundColor
+ bgHoverColor: Style.errorBoxBackgroundColor
+ bgNormalOpacity: 1.0
+ bgHoverOpacity: 1.0
+
+ onClicked: root.deleteShare()
+ }
+ CustomButton {
+ height: Style.standardPrimaryButtonHeight
+
+ imageSource: "image://svgimage-custom-color/add.svg/" + Style.ncBlue
+ imageSourceHover: "image://svgimage-custom-color/add.svg/" + Style.ncHeaderTextColor
+ text: qsTr("Add another link")
+ textColor: Style.ncBlue
+ textColorHovered: Style.ncHeaderTextColor
+ contentsFont.bold: true
+ bgNormalColor: Style.buttonBackgroundColor
+ bgHoverColor: Style.ncBlue
+ bgNormalOpacity: 1.0
+ bgHoverOpacity: 1.0
+
+ visible: root.isLinkShare && root.canCreateLinkShares
+ enabled: visible
+
+ onClicked: root.createNewLinkShare()
+ }
+ }
+ }
+ footer: DialogButtonBox {
+ topPadding: 0
+ bottomPadding: root.padding
+ rightPadding: root.padding
+ leftPadding: root.padding
+ alignment: Qt.AlignRight | Qt.AlignVCenter
+ visible: copyShareLinkButton.visible
+
+ CustomButton {
+ id: copyShareLinkButton
+
+ height: Style.standardPrimaryButtonHeight
+
+ imageSource: "image://svgimage-custom-color/copy.svg/" + Style.ncHeaderTextColor
+ text: qsTr("Copy share link")
+ textColor: Style.ncHeaderTextColor
+ contentsFont.bold: true
+ bgColor: Style.ncBlue
+ bgNormalOpacity: 1.0
+ bgHoverOpacity: Style.hoverOpacity
+
+ visible: root.isLinkShare
+ enabled: visible
+
+ onClicked: {
+ clipboardHelper.text = root.link;
+ clipboardHelper.selectAll();
+ clipboardHelper.copy();
+ clipboardHelper.clear();
+ }
+ TextEdit { id: clipboardHelper; visible: false }
}
}
}