chore: Consolidate date/time formatting

- simplify locale settings
- extract/fix datetime related functions into LocaleUtils
- port code to the new LocaleUtils

Closes #7230
This commit is contained in:
Lukáš Tinkl 2023-01-12 23:39:46 +01:00 committed by Lukáš Tinkl
parent b981f31591
commit b2328d6643
39 changed files with 272 additions and 439 deletions

View File

@ -89,10 +89,6 @@ const LSS_KEY_COMPATIBILITY_MODE* = "compatibilityMode"
const DEFAULT_COMPATIBILITY_MODE = true const DEFAULT_COMPATIBILITY_MODE = true
const LSS_KEY_STICKERS_ENS_ROPSTEN* = "stickersEnsRopsten" const LSS_KEY_STICKERS_ENS_ROPSTEN* = "stickersEnsRopsten"
const DEFAULT_STICKERS_ENS_ROPSTEN = false const DEFAULT_STICKERS_ENS_ROPSTEN = false
const LSS_KEY_IS_DDMMYY_DATE_FORMAT* = "is_DDMMYY_date_format"
const DEFAULT_IS_DDMMYY_DATE_FORMAT = false
const LSS_KEY_IS_24H_TIME_FORMAT* = "is_24h_time_format"
const DEFAULT_IS_24H_TIME_FORMAT = false
const LSS_KEY_USER_DECLINED_BACKUP_BANNER* = "userDeclinedBackupBanner" const LSS_KEY_USER_DECLINED_BACKUP_BANNER* = "userDeclinedBackupBanner"
const DEFAULT_USER_DECLINED_BACKUP_BANNER = false const DEFAULT_USER_DECLINED_BACKUP_BANNER = false
const LSS_KEY_IS_DISCORD_IMPORT_TOOL_ENABLED* = "isDiscordImportToolEnabled" const LSS_KEY_IS_DISCORD_IMPORT_TOOL_ENABLED* = "isDiscordImportToolEnabled"
@ -756,31 +752,6 @@ QtObject:
write = setStickersEnsRopsten write = setStickersEnsRopsten
notify = stickersEnsRopstenChanged notify = stickersEnsRopstenChanged
proc isDDMMYYDateFormatChanged*(self: LocalAccountSensitiveSettings) {.signal.}
proc getIsDDMMYYDateFormat*(self: LocalAccountSensitiveSettings): bool {.slot.} =
getSettingsProp[bool](self, LSS_KEY_IS_DDMMYY_DATE_FORMAT, newQVariant(DEFAULT_IS_DDMMYY_DATE_FORMAT))
proc setIsDDMMYYDateFormat*(self: LocalAccountSensitiveSettings, value: bool) {.slot.} =
setSettingsProp(self, LSS_KEY_IS_DDMMYY_DATE_FORMAT, newQVariant(value)):
self.isDDMMYYDateFormatChanged()
QtProperty[bool] isDDMMYYDateFormat:
read = getIsDDMMYYDateFormat
write = setIsDDMMYYDateFormat
notify = isDDMMYYDateFormatChanged
proc is24hTimeFormatChanged*(self: LocalAccountSensitiveSettings) {.signal.}
proc getIs24hTimeFormat*(self: LocalAccountSensitiveSettings): bool {.slot.} =
getSettingsProp[bool](self, LSS_KEY_IS_24H_TIME_FORMAT, newQVariant(DEFAULT_IS_24H_TIME_FORMAT))
proc setIs24hTimeFormat*(self: LocalAccountSensitiveSettings, value: bool) {.slot.} =
setSettingsProp(self, LSS_KEY_IS_24H_TIME_FORMAT, newQVariant(value)):
self.is24hTimeFormatChanged()
QtProperty[bool] is24hTimeFormat:
read = getIs24hTimeFormat
write = setIs24hTimeFormat
notify = is24hTimeFormatChanged
proc userDeclinedBackupBannerChanged*(self: LocalAccountSensitiveSettings) {.signal.} proc userDeclinedBackupBannerChanged*(self: LocalAccountSensitiveSettings) {.signal.}
proc getUserDeclinedBackupBanner*(self: LocalAccountSensitiveSettings): bool {.slot.} = proc getUserDeclinedBackupBanner*(self: LocalAccountSensitiveSettings): bool {.slot.} =
getSettingsProp[bool](self, LSS_KEY_USER_DECLINED_BACKUP_BANNER, newQVariant(DEFAULT_USER_DECLINED_BACKUP_BANNER)) getSettingsProp[bool](self, LSS_KEY_USER_DECLINED_BACKUP_BANNER, newQVariant(DEFAULT_USER_DECLINED_BACKUP_BANNER))
@ -843,6 +814,4 @@ QtObject:
of LSS_KEY_PDF_VIEWER_ENABLED: self.pdfViewerEnabledChanged() of LSS_KEY_PDF_VIEWER_ENABLED: self.pdfViewerEnabledChanged()
of LSS_KEY_COMPATIBILITY_MODE: self.compatibilityModeChanged() of LSS_KEY_COMPATIBILITY_MODE: self.compatibilityModeChanged()
of LSS_KEY_STICKERS_ENS_ROPSTEN: self.stickersEnsRopstenChanged() of LSS_KEY_STICKERS_ENS_ROPSTEN: self.stickersEnsRopstenChanged()
of LSS_KEY_IS_DDMMYY_DATE_FORMAT: self.isDDMMYYDateFormatChanged()
of LSS_KEY_IS_24H_TIME_FORMAT: self.is24hTimeFormatChanged()
of LSS_KEY_USER_DECLINED_BACKUP_BANNER: self.userDeclinedBackupBannerChanged() of LSS_KEY_USER_DECLINED_BACKUP_BANNER: self.userDeclinedBackupBannerChanged()

View File

@ -19,12 +19,6 @@ method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} =
method changeLanguage*(self: AccessInterface, language: string) {.base.} = method changeLanguage*(self: AccessInterface, language: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")
method setIsDDMMYYDateFormat*(self: AccessInterface, isDDMMYYDateFormat: bool) {.slot.} =
raise newException(ValueError, "No implementation available")
method setIs24hTimeFormat*(self: AccessInterface, is24hTimeFormat: bool) {.slot.} =
raise newException(ValueError, "No implementation available")
method onCurrentLanguageChanged*(self: AccessInterface, language: string) {.base.} = method onCurrentLanguageChanged*(self: AccessInterface, language: string) {.base.} =
raise newException(ValueError, "No implementation available") raise newException(ValueError, "No implementation available")

View File

@ -70,12 +70,4 @@ method changeLanguage*(self: Module, language: string) =
method onCurrentLanguageChanged*(self: Module, language: string) = method onCurrentLanguageChanged*(self: Module, language: string) =
self.view.setLanguage(language) self.view.setLanguage(language)
method setIsDDMMYYDateFormat*(self: Module, isDDMMYYDateFormat: bool) =
if(isDDMMYYDateFormat != singletonInstance.localAccountSensitiveSettings.getIsDDMMYYDateFormat()):
singletonInstance.localAccountSensitiveSettings.setIsDDMMYYDateFormat(isDDMMYYDateFormat)
method setIs24hTimeFormat*(self: Module, is24hTimeFormat: bool) =
if(is24hTimeFormat != singletonInstance.localAccountSensitiveSettings.getIs24hTimeFormat()):
singletonInstance.localAccountSensitiveSettings.setIs24hTimeFormat(is24hTimeFormat)

View File

@ -34,12 +34,6 @@ QtObject:
QtProperty[QVariant] model: QtProperty[QVariant] model:
read = getModel read = getModel
proc setIsDDMMYYDateFormat*(self: View, isDDMMYYDateFormat: bool) {.slot.} =
self.delegate.setIsDDMMYYDateFormat(isDDMMYYDateFormat)
proc setIs24hTimeFormat*(self: View, is24hTimeFormat: bool) {.slot.} =
self.delegate.setIs24hTimeFormat(is24hTimeFormat)
proc changeLanguage*(self: View, language: string) {.slot.} = proc changeLanguage*(self: View, language: string) {.slot.} =
self.delegate.changeLanguage(language) self.delegate.changeLanguage(language)

View File

@ -23,8 +23,6 @@ SplitView {
languageStore: LanguageStore { languageStore: LanguageStore {
property string currentLanguage: "en" property string currentLanguage: "en"
readonly property bool isDDMMYYDateFormat: true
readonly property bool is24hTimeFormat: true
readonly property ListModel languageModel: ListModel { readonly property ListModel languageModel: ListModel {
ListElement { ListElement {
@ -49,14 +47,6 @@ SplitView {
logs.logEvent("languageStore::changeLanguage", ["language"], arguments) logs.logEvent("languageStore::changeLanguage", ["language"], arguments)
currentLanguage = language currentLanguage = language
} }
function setIsDDMMYYDateFormat(isDDMMYYDateFormat) {
logs.logEvent("languageStore::setIsDDMMYYDateFormat", ["isDDMMYYDateFormat"], arguments)
}
function setIs24hTimeFormat(is24hTimeFormat) {
logs.logEvent("languageStore::setIs24hTimeFormat", ["is24hTimeFormat"], arguments)
}
} }
currencyStore: QtObject { currencyStore: QtObject {

View File

@ -27,10 +27,9 @@ StatusComboBox {
\qmlproperty string StatusDatePicker::dateFormat \qmlproperty string StatusDatePicker::dateFormat
This property specifies how the selected date will be displayed to the user. This property specifies how the selected date will be displayed to the user.
By default it is current locale's short date format. For a list of available types Either Locale.ShortFormat (default) or Locale.LongFormat
and formatting characters, see https://doc.qt.io/qt-5/qdate.html#toString-2
*/ */
property string dateFormat: Qt.locale().dateFormat(Locale.ShortFormat) property int dateFormat: Locale.ShortFormat
/*! /*!
\qmlproperty date StatusDatePicker::selectedDate \qmlproperty date StatusDatePicker::selectedDate
@ -46,7 +45,7 @@ StatusComboBox {
} }
control.delegate: null control.delegate: null
control.displayText: root.selectedDate.toLocaleDateString(Qt.locale(), root.dateFormat) control.displayText: LocaleUtils.formatDate(root.selectedDate, root.dateFormat)
control.popup.horizontalPadding: 8 control.popup.horizontalPadding: 8
control.popup.onAboutToShow: { control.popup.onAboutToShow: {

View File

@ -63,8 +63,8 @@ Control {
property StatusMessageDetails messageDetails: StatusMessageDetails {} property StatusMessageDetails messageDetails: StatusMessageDetails {}
property StatusMessageDetails replyDetails: StatusMessageDetails {} property StatusMessageDetails replyDetails: StatusMessageDetails {}
property string timestampString: new Date(timestamp).toLocaleTimeString(Qt.locale(), Locale.ShortFormat) property string timestampString: LocaleUtils.formatTime(timestamp, Locale.ShortFormat)
property string timestampTooltipString: new Date(timestamp).toLocaleString() property string timestampTooltipString: LocaleUtils.formatDateTime(timestamp)
signal clicked(var sender, var mouse) signal clicked(var sender, var mouse)
signal profilePictureClicked(var sender, var mouse) signal profilePictureClicked(var sender, var mouse)

View File

@ -23,6 +23,8 @@ CheckBox {
property bool leftSide: true property bool leftSide: true
opacity: enabled ? 1.0 : 0.3
QtObject { QtObject {
id: d id: d
@ -66,7 +68,6 @@ CheckBox {
contentItem: StatusBaseText { contentItem: StatusBaseText {
text: root.text text: root.text
font: root.font font: root.font
opacity: enabled ? 1.0 : 0.3
verticalAlignment: Text.AlignVCenter verticalAlignment: Text.AlignVCenter
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
width: parent.width width: parent.width

View File

@ -0,0 +1,196 @@
pragma Singleton
import QtQml 2.14
import Qt.labs.settings 1.0
QtObject {
id: root
function fractionalPartLength(num) {
if (Number.isInteger(num))
return 0
return num.toString().split('.')[1].length
}
function stripTrailingZeroes(numStr, locale) {
let regEx = locale.decimalPoint == "." ? /(\.[0-9]*[1-9])0+$|\.0*$/ : /(\,[0-9]*[1-9])0+$|\,0*$/
return numStr.replace(regEx, '$1')
}
function numberToLocaleString(num, precision = -1, locale = null) {
locale = locale || Qt.locale()
if (precision === -1)
precision = fractionalPartLength(num)
return num.toLocaleString(locale, 'f', precision)
}
function currencyAmountToLocaleString(currencyAmount, locale) {
if (!locale) {
console.log("Unspecified locale for: " + JSON.stringify(currencyAmount))
locale = Qt.locale()
}
if (typeof(currencyAmount) !== "object") {
console.log("Wrong type for currencyAmount: " + JSON.stringify(currencyAmount))
return NaN
}
var amountStr = numberToLocaleString(currencyAmount.amount, currencyAmount.displayDecimals, locale)
if (currencyAmount.stripTrailingZeroes) {
amountStr = stripTrailingZeroes(amountStr, locale)
}
if (currencyAmount.symbol) {
amountStr = "%1 %2".arg(amountStr).arg(currencyAmount.symbol)
}
return amountStr
}
// DATE/TIME
readonly property var d: QtObject {
id: d
readonly property var amPmFormatChars: ["AP", "A", "ap", "a"]
// try to parse date from a number or ISO string timestamp
function readDate(value) {
if (typeof value === "undefined") // default to "now" if omitted
return new Date()
if (typeof value === "string" || typeof value === "number") // support reading ISO string or numeric timestamps
return new Date(value)
return value
}
// enforce correct 12/24 time format when not using defaults
function fixupTimeFormatString(formatString) {
if (settings.timeFormatUsesDefaults) // OS defaults, nothing to change
return formatString
if (settings.timeFormatUses24Hours) { // enforce 24h time format
// remove any amPmFormatChars from the format string and use 0-23 hours (h->H, hh->HH)
return formatString.replace(/\ba\b|\bap\b/ig, "").replace(/h/g, "H")
} else { // enforce 12hr time format
// use 0-12 hours (H->h, HH->h) and append any of amPmFormatChars to the format string
var result = formatString.replace(/H/g, "h")
if (!d.amPmFormatChars.some(ampm => result.includes(ampm)))
result = result.concat(" ap")
return result
}
}
}
readonly property Settings settings: Settings {
category: "Locale"
property bool timeFormatUsesDefaults: true
property bool timeFormatUses24Hours: is24hTimeFormatDefault()
}
function is24hTimeFormatDefault() {
const timeFormatString = Qt.locale().timeFormat(Locale.LongFormat)
return !d.amPmFormatChars.some(ampm => timeFormatString.includes(ampm))
}
/**
Converts the Date to a string containing the date suitable for the specified locale in the specified format.
- 'value' can be either a Date object, or a string containing a number or ISO string timestamp, or empty for "now"
- 'format' can be one of Locale.LongFormat (default), Locale.ShortFormat
*/
function formatDate(value, format = Locale.LongFormat) {
value = d.readDate(value)
const loc = Qt.locale()
if (format === Locale.ShortFormat) { // replace 2-digit year with 4-digits (yy -> yyyy) in short format
const dateFormatStr = loc.dateFormat(Locale.ShortFormat)
if (!dateFormatStr.includes("yyyy")) {
format = dateFormatStr.replace("yy", "yyyy")
}
}
return value.toLocaleDateString(loc, format)
}
/**
Converts the Date to a string containing the time suitable for the specified locale in the specified format.
- 'value' can be either a Date object, or a string containing a number or ISO string timestamp, or empty for "now"
- 'format' can be one of Locale.LongFormat (default), Locale.ShortFormat
*/
function formatTime(value, format = Locale.LongFormat) {
value = d.readDate(value)
const loc = Qt.locale()
const formatString = d.fixupTimeFormatString(loc.timeFormat(format))
return value.toLocaleTimeString(loc, formatString)
}
/**
Converts the Date to a string containing both the date and time suitable for the specified locale in the specified format.
- 'value' can be either a Date object, or a string containing a number or ISO string timestamp, or empty for "now"
- 'format' can be one of Locale.LongFormat (default), Locale.ShortFormat
*/
function formatDateTime(value, format = Locale.LongFormat) {
value = d.readDate(value)
const loc = Qt.locale()
var formatString = d.fixupTimeFormatString(loc.dateTimeFormat(format))
if (format === Locale.ShortFormat && !formatString.includes("yyyy")) // replace 2-digit year with 4-digits (yy -> yyyy) in short format
formatString = formatString.replace("yy", "yyyy")
return value.toLocaleString(loc, formatString)
}
function getTimeDifference(d1, d2) {
const day1Year = d1.getFullYear()
const day1Month = d1.getMonth()
const day1Time = d1.getTime()
const day2Year = d2.getFullYear()
const day2Month = d2.getMonth()
const day2Time = d2.getTime()
const inYears = day2Year-day1Year
if (inYears > 0) {
return qsTr("%n year(s) ago", "", inYears)
}
const inMonths = (day2Month+12*day2Year)-(day1Month+12*day1Year)
if (inMonths > 0) {
return qsTr("%n month(s) ago", "", inMonths)
}
const inWeeks = parseInt((day2Time-day2Time)/(24*3600*1000*7))
if (inWeeks > 0) {
return qsTr("%n week(s) ago", "", inWeeks)
}
const inDays = parseInt((day2Time-day1Time)/(24*3600*1000))
if (inDays > 0) {
return qsTr("%n day(s) ago", "", inDays)
}
const inHours = parseInt((day2Time-day1Time)/(3600*1000));
if (inHours > 0) {
return qsTr("%n hour(s) ago", "", inHours)
}
const inMins = parseInt((day2Time-day1Time)/(60*1000))
if (inMins > 0) {
return qsTr("%n min(s) ago", "x minute(s) ago", inMins)
}
const inSecs = parseInt((day2Time-day1Time)/1000);
if (inSecs > 0) {
return qsTr("%n sec(s) ago", "x second(s) ago", inSecs)
}
return qsTr("now")
}
// FIXME Qt6 use IntlFormat (partial string)
function getDayMonth(value) {
const currentFormat = is24hTimeFormatDefault() ? "d MMM" : "MMM d"
return formatDate(value, currentFormat)
}
// FIXME Qt6 use IntlFormat (partial string)
function getMonthYear(value) {
return formatDate(value, "MMM yyyy")
}
}

View File

@ -14,3 +14,4 @@ StatusProfileImageSettings 0.1 StatusProfileImageSettings.qml
StatusRollArea 0.1 StatusRollArea.qml StatusRollArea 0.1 StatusRollArea.qml
StatusScrollView 0.1 StatusScrollView.qml StatusScrollView 0.1 StatusScrollView.qml
StatusTooltipSettings 0.1 StatusTooltipSettings.qml StatusTooltipSettings 0.1 StatusTooltipSettings.qml
singleton LocaleUtils 0.1 LocaleUtils.qml

View File

@ -128,6 +128,7 @@
<file>StatusQ/Core/Utils/qmldir</file> <file>StatusQ/Core/Utils/qmldir</file>
<file>StatusQ/Core/Utils/Utils.qml</file> <file>StatusQ/Core/Utils/Utils.qml</file>
<file>StatusQ/Core/qmldir</file> <file>StatusQ/Core/qmldir</file>
<file>StatusQ/Core/LocaleUtils.qml</file>
<file>StatusQ/Core/StatusAnimatedStack.qml</file> <file>StatusQ/Core/StatusAnimatedStack.qml</file>
<file>StatusQ/Core/StatusBaseText.qml</file> <file>StatusQ/Core/StatusBaseText.qml</file>
<file>StatusQ/Core/StatusFontSettings.qml</file> <file>StatusQ/Core/StatusFontSettings.qml</file>

View File

@ -7,6 +7,7 @@ import Qt.labs.settings 1.0
import QtQuick.Controls.Styles 1.0 import QtQuick.Controls.Styles 1.0
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2
import StatusQ.Core 0.1
import StatusQ.Layout 0.1 import StatusQ.Layout 0.1
import utils 1.0 import utils 1.0

View File

@ -1,6 +1,7 @@
import QtQuick 2.0 import QtQuick 2.0
import AppLayouts.Chat.controls.community 1.0 import AppLayouts.Chat.controls.community 1.0
import StatusQ.Core 0.1
import StatusQ.Core.Utils 0.1 as SQ import StatusQ.Core.Utils 0.1 as SQ
import utils 1.0 import utils 1.0

View File

@ -28,7 +28,7 @@ QtObject {
property bool discordImportHasCommunityImage: root.communitiesModuleInst.discordImportHasCommunityImage property bool discordImportHasCommunityImage: root.communitiesModuleInst.discordImportHasCommunityImage
property var discordImportTasks: root.communitiesModuleInst.discordImportTasks property var discordImportTasks: root.communitiesModuleInst.discordImportTasks
property bool downloadingCommunityHistoryArchives: root.communitiesModuleInst.downloadingCommunityHistoryArchives property bool downloadingCommunityHistoryArchives: root.communitiesModuleInst.downloadingCommunityHistoryArchives
property var locale: Qt.locale(localAppSettings.language) property var locale: Qt.locale()
property var advancedModule: profileSectionModule.advancedModule property var advancedModule: profileSectionModule.advancedModule
// TODO: Could the backend provide directly 2 filtered models?? // TODO: Could the backend provide directly 2 filtered models??

View File

@ -8,18 +8,8 @@ QtObject {
readonly property var languageModel: languageModule ? languageModule.model : null readonly property var languageModel: languageModule ? languageModule.model : null
readonly property string currentLanguage: languageModule ? languageModule.currentLanguage : null readonly property string currentLanguage: languageModule ? languageModule.currentLanguage : null
readonly property bool isDDMMYYDateFormat: localAccountSensitiveSettings.isDDMMYYDateFormat
readonly property bool is24hTimeFormat: localAccountSensitiveSettings.is24hTimeFormat
function changeLanguage(language) { function changeLanguage(language) {
root.languageModule.changeLanguage(language) root.languageModule.changeLanguage(language)
} }
function setIsDDMMYYDateFormat(isDDMMYYDateFormat) {
root.languageModule.setIsDDMMYYDateFormat(isDDMMYYDateFormat)
}
function setIs24hTimeFormat(is24hTimeFormat) {
root.languageModule.setIs24hTimeFormat(is24hTimeFormat)
}
} }

View File

@ -218,7 +218,7 @@ Item {
anchors.left: parent.left anchors.left: parent.left
anchors.leftMargin: 24 anchors.leftMargin: 24
text: { text: {
const formattedDate = Utils.formatShortDate(d.expirationTimestamp, localAccountSensitiveSettings.isDDMMYYDateFormat) const formattedDate = LocaleUtils.formatDate(d.expirationTimestamp, Locale.ShortFormat)
return qsTr("Username locked. You won't be able to release it until %1").arg(formattedDate) return qsTr("Username locked. You won't be able to release it until %1").arg(formattedDate)
} }
color: Style.current.darkGrey color: Style.current.darkGrey

View File

@ -10,7 +10,6 @@ import StatusQ.Components 0.1
import shared 1.0 import shared 1.0
import shared.panels 1.0 import shared.panels 1.0
import shared.views.chat 1.0 import shared.views.chat 1.0
import shared.panels.chat 1.0
import shared.controls.chat 1.0 import shared.controls.chat 1.0
import utils 1.0 import utils 1.0

View File

@ -46,20 +46,16 @@ SettingsContentBase {
spacing: Constants.settingsSection.itemSpacing spacing: Constants.settingsSection.itemSpacing
width: root.contentWidth width: root.contentWidth
Item { RowLayout {
id: currency
Layout.fillWidth: true Layout.fillWidth: true
Layout.leftMargin: Style.current.padding Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding Layout.rightMargin: Style.current.padding
height: 38
z: root.z + 2 z: root.z + 2
StatusBaseText { StatusBaseText {
text: qsTr("Set Display Currency") text: qsTr("Set Display Currency")
anchors.left: parent.left
font.pixelSize: 15
color: Theme.palette.directColor1
} }
Item { Layout.fillWidth: true }
StatusListPicker { StatusListPicker {
id: currencyPicker id: currencyPicker
@ -75,9 +71,6 @@ SettingsContentBase {
} }
z: root.z + 2 z: root.z + 2
width: 104
height: parent.height
anchors.right: parent.right
inputList: root.currencyStore.currenciesModel inputList: root.currencyStore.currenciesModel
printSymbol: true printSymbol: true
placeholderSearchText: qsTr("Search Currencies") placeholderSearchText: qsTr("Search Currencies")
@ -92,23 +85,18 @@ SettingsContentBase {
} }
} }
Item { RowLayout {
id: language
Layout.fillWidth: true Layout.fillWidth: true
Layout.leftMargin: Style.current.padding Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding Layout.rightMargin: Style.current.padding
height: 38
z: root.z + 1 z: root.z + 1
StatusBaseText { StatusBaseText {
text: qsTr("Language") text: qsTr("Language")
anchors.left: parent.left
font.pixelSize: 15
color: Theme.palette.directColor1
} }
Item { Layout.fillWidth: true }
StatusListPicker { StatusListPicker {
id: languagePicker id: languagePicker
property string newKey property string newKey
function descriptionForState(state) { function descriptionForState(state) {
@ -161,9 +149,6 @@ SettingsContentBase {
} }
z: root.z + 1 z: root.z + 1
width: 104
height: parent.height
anchors.right: parent.right
placeholderSearchText: qsTr("Search Languages") placeholderSearchText: qsTr("Search Languages")
maxPickerHeight: 350 maxPickerHeight: 350
@ -175,7 +160,6 @@ SettingsContentBase {
//if (Qt.platform.os === Constants.linux) { //if (Qt.platform.os === Constants.linux) {
root.changeLanguage(key) root.changeLanguage(key)
linuxConfirmationDialog.active = true linuxConfirmationDialog.active = true
linuxConfirmationDialog.item.newLocale = key
linuxConfirmationDialog.item.open() linuxConfirmationDialog.item.open()
// } // }
@ -192,34 +176,6 @@ SettingsContentBase {
Layout.bottomMargin: Style.current.padding Layout.bottomMargin: Style.current.padding
} }
// Date format options:
Column {
Layout.fillWidth: true
Layout.leftMargin: Style.current.padding
Layout.rightMargin: Style.current.padding
spacing: Style.current.padding
StatusBaseText {
text: qsTr("Date Format")
anchors.left: parent.left
font.pixelSize: 15
color: Theme.palette.directColor1
}
StatusRadioButton {
text: qsTr("DD/MM/YY")
font.pixelSize: 13
checked: root.languageStore.isDDMMYYDateFormat
onToggled: root.languageStore.setIsDDMMYYDateFormat(checked)
}
StatusRadioButton {
text: qsTr("MM/DD/YY")
font.pixelSize: 13
checked: !root.languageStore.isDDMMYYDateFormat
onToggled: root.languageStore.setIsDDMMYYDateFormat(!checked)
}
}
// Time format options: // Time format options:
Column { Column {
Layout.fillWidth: true Layout.fillWidth: true
@ -229,23 +185,24 @@ SettingsContentBase {
spacing: Style.current.padding spacing: Style.current.padding
StatusBaseText { StatusBaseText {
text: qsTr("Time Format") text: qsTr("Time Format")
anchors.left: parent.left
font.pixelSize: 15
color: Theme.palette.directColor1
} }
StatusCheckBox {
StatusRadioButton { id: use24hDefault
text: qsTr("24-Hour Time") text: qsTr("Use System Settings")
font.pixelSize: 13 font.pixelSize: 13
checked: root.languageStore.is24hTimeFormat checked: LocaleUtils.settings.timeFormatUsesDefaults
onToggled: root.languageStore.setIs24hTimeFormat(checked) onToggled: {
LocaleUtils.settings.timeFormatUsesDefaults = checked
if (checked)
LocaleUtils.settings.timeFormatUses24Hours = LocaleUtils.is24hTimeFormatDefault()
}
} }
StatusCheckBox {
StatusRadioButton { text: qsTr("Use 24-Hour Time")
text: qsTr("12-Hour Time")
font.pixelSize: 13 font.pixelSize: 13
checked: !root.languageStore.is24hTimeFormat enabled: !use24hDefault.checked
onToggled: root.languageStore.setIs24hTimeFormat(!checked) checked: LocaleUtils.settings.timeFormatUses24Hours
onToggled: LocaleUtils.settings.timeFormatUses24Hours = checked
} }
} }
@ -254,13 +211,11 @@ SettingsContentBase {
id: linuxConfirmationDialog id: linuxConfirmationDialog
active: false active: false
sourceComponent: ConfirmationDialog { sourceComponent: ConfirmationDialog {
property string newLocale
header.title: qsTr("Change language") header.title: qsTr("Change language")
confirmationText: qsTr("Display language has been changed. You must restart the application for changes to take effect.") confirmationText: qsTr("Display language has been changed. You must restart the application for changes to take effect.")
confirmButtonLabel: qsTr("Close the app now") confirmButtonLabel: qsTr("Close the app now")
onConfirmButtonClicked: { onConfirmButtonClicked: {
loader.active = false linuxConfirmationDialog.active = false
Qt.quit() Qt.quit()
} }
} }

View File

@ -7,7 +7,7 @@ import "../Profile/stores"
QtObject { QtObject {
id: root id: root
property var locale: Qt.locale(localAppSettings.language) property var locale: Qt.locale()
property var mainModuleInst: mainModule property var mainModuleInst: mainModule
property var aboutModuleInst: aboutModule property var aboutModuleInst: aboutModule

View File

@ -1,9 +1,11 @@
import QtQuick 2.13 import QtQuick 2.13
import QtQuick.Controls 2.13 import QtQuick.Controls 2.13
import StatusQ.Core 0.1
import StatusQ.Popups 0.1
import shared.stores 1.0 import shared.stores 1.0
import utils 1.0 import utils 1.0
import StatusQ.Popups 0.1
Item { Item {
id: appSearch id: appSearch
@ -75,7 +77,7 @@ Item {
searchOptionsPopupMenu: searchPopupMenu searchOptionsPopupMenu: searchPopupMenu
searchResults: appSearch.store.resultModel searchResults: appSearch.store.resultModel
formatTimestampFn: function (ts) { formatTimestampFn: function (ts) {
return Utils.formatLongDateTime(parseInt(ts, 10), RootStore.accountSensitiveSettings.isDDMMYYDateFormat, RootStore.accountSensitiveSettings.is24hTimeFormat) return LocaleUtils.formatDateTime(parseInt(ts, 10))
} }
onSearchTextChanged: { onSearchTextChanged: {
if (searchPopup.searchText !== "") { if (searchPopup.searchText !== "") {

View File

@ -156,7 +156,7 @@ Popup {
hideReadNotifications: activityCenterStore.hideReadNotifications hideReadNotifications: activityCenterStore.hideReadNotifications
currentActivityCategory: root.currentActivityCategory currentActivityCategory: root.currentActivityCategory
onCategoryTriggered: root.currentActivityCategory = category onCategoryTriggered: root.currentActivityCategory = category
onMarkAllReadClicked: errorText = root.activityCenterStore.markAllActivityCenterNotificationsRead() onMarkAllReadClicked: root.activityCenterStore.markAllActivityCenterNotificationsRead()
onShowHideReadNotifications: activityCenterStore.hideReadNotifications = hideReadNotifications onShowHideReadNotifications: activityCenterStore.hideReadNotifications = hideReadNotifications
} }

View File

@ -1,6 +1,8 @@
import QtQuick 2.13 import QtQuick 2.13
import QtQml 2.14 import QtQml 2.14
import StatusQ.Core 0.1
import utils 1.0 import utils 1.0
import shared 1.0 import shared 1.0

View File

@ -1,5 +1,6 @@
import QtQuick 2.13 import QtQuick 2.13
import StatusQ.Core 0.1
import StatusQ.Components 0.1 import StatusQ.Components 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1

View File

@ -1,5 +1,6 @@
import QtQuick 2.13 import QtQuick 2.13
import StatusQ.Core 0.1
import StatusQ.Components 0.1 import StatusQ.Components 0.1
import shared.panels 1.0 import shared.panels 1.0
@ -19,8 +20,7 @@ Item {
QtObject { QtObject {
id: d id: d
readonly property string formattedDate: nextMessageIndex > -1 ? Utils.formatLongDate(nextMsgTimestamp, RootStore.accountSensitiveSettings.isDDMMYYDateFormat) : readonly property string formattedDate: nextMessageIndex > -1 ? LocaleUtils.formatDate(nextMsgTimestamp) : LocaleUtils.formatDate()
Utils.formatLongDate(undefined, RootStore.accountSensitiveSettings.isDDMMYYDateFormat)
} }
Timer { Timer {

View File

@ -1,4 +1,7 @@
import QtQuick 2.13 import QtQuick 2.13
import StatusQ.Core 0.1
import shared 1.0 import shared 1.0
import shared.panels 1.0 import shared.panels 1.0
import shared.stores 1.0 import shared.stores 1.0
@ -44,8 +47,7 @@ Item {
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
color: Style.current.secondaryText color: Style.current.secondaryText
text: qsTr("Between %1 and %2").arg(Utils.formatLongDate(root.gapFrom * 1000, RootStore.accountSensitiveSettings.isDDMMYYDateFormat)) text: qsTr("Between %1 and %2").arg(LocaleUtils.formatDate(root.gapFrom * 1000)).arg(LocaleUtils.formatDate(root.gapTo * 1000))
.arg(Utils.formatLongDate(root.gapTo * 1000, RootStore.accountSensitiveSettings.isDDMMYYDateFormat))
} }
Separator { Separator {
anchors.top: fetchDate.bottom anchors.top: fetchDate.bottom

View File

@ -3,6 +3,8 @@ import QtQuick.Controls 2.13
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0 import QtGraphicalEffects 1.0
import StatusQ.Core 0.1
import utils 1.0 import utils 1.0
import shared 1.0 import shared 1.0
import shared.popups 1.0 import shared.popups 1.0

View File

@ -1,5 +1,7 @@
import QtQuick 2.13 import QtQuick 2.13
import StatusQ.Core 0.1
import utils 1.0 import utils 1.0
ChartStoreBase { ChartStoreBase {
@ -75,8 +77,8 @@ ChartStoreBase {
let dataEntry = response.historicalData[i] let dataEntry = response.historicalData[i]
let dateString = response.timeInterval == ChartStoreBase.TimeRange.Weekly || response.timeInterval == ChartStoreBase.TimeRange.Monthly let dateString = response.timeInterval == ChartStoreBase.TimeRange.Weekly || response.timeInterval == ChartStoreBase.TimeRange.Monthly
? Utils.getDayMonth(dataEntry.time * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat) ? LocaleUtils.getDayMonth(dataEntry.time * 1000)
: Utils.getMonthYear(dataEntry.time * 1000) : LocaleUtils.getMonthYear(dataEntry.time * 1000)
tmpTimeRange.push(dateString) tmpTimeRange.push(dateString)
tmpDataValues.push(parseFloat(globalUtils.wei2Eth(dataEntry.value, 18))) tmpDataValues.push(parseFloat(globalUtils.wei2Eth(dataEntry.value, 18)))
@ -86,4 +88,4 @@ ChartStoreBase {
root.updateRequestTime(response.timeInterval) root.updateRequestTime(response.timeInterval)
} }
} }
} }

View File

@ -1,5 +1,7 @@
import QtQuick 2.13 import QtQuick 2.13
import StatusQ.Core 0.1
import utils 1.0 import utils 1.0
ChartStoreBase { ChartStoreBase {
@ -12,8 +14,8 @@ ChartStoreBase {
marketValues[i] = data[i].close; marketValues[i] = data[i].close;
timeRanges[i] = range === ChartStoreBase.TimeRange.Weekly || range === ChartStoreBase.TimeRange.Monthly ? timeRanges[i] = range === ChartStoreBase.TimeRange.Weekly || range === ChartStoreBase.TimeRange.Monthly ?
Utils.getDayMonth(data[i].time * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat): LocaleUtils.getDayMonth(data[i].time * 1000):
Utils.getMonthYear(data[i].time * 1000) LocaleUtils.getMonthYear(data[i].time * 1000)
} }
switch(range) { switch(range) {

View File

@ -103,7 +103,7 @@ ColumnLayout {
StatusListItem { StatusListItem {
property var modelData property var modelData
height: 40 height: 40
title: modelData !== undefined && !!modelData ? Utils.formatShortDate(modelData.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat) : "" title: modelData !== undefined && !!modelData ? LocaleUtils.formatDate(modelData.timestamp * 1000, Locale.ShortFormat) : ""
statusListItemTitle.color: Theme.palette.baseColor1 statusListItemTitle.color: Theme.palette.baseColor1
color: Theme.palette.statusListItem.backgroundColor color: Theme.palette.statusListItem.backgroundColor
sensor.enabled: false sensor.enabled: false
@ -122,7 +122,7 @@ ColumnLayout {
networkName: modelData !== undefined && !!modelData ? RootStore.getNetworkShortName(modelData.chainId) : "" networkName: modelData !== undefined && !!modelData ? RootStore.getNetworkShortName(modelData.chainId) : ""
symbol: modelData !== undefined && !!modelData ? !!modelData.symbol ? modelData.symbol : RootStore.findTokenSymbolByAddress(modelData.contract) : "" symbol: modelData !== undefined && !!modelData ? !!modelData.symbol ? modelData.symbol : RootStore.findTokenSymbolByAddress(modelData.contract) : ""
transferStatus: modelData !== undefined && !!modelData ? RootStore.hex2Dec(modelData.txStatus) : "" transferStatus: modelData !== undefined && !!modelData ? RootStore.hex2Dec(modelData.txStatus) : ""
shortTimeStamp: modelData !== undefined && !!modelData ? Utils.formatShortTime(modelData.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat) : "" shortTimeStamp: modelData !== undefined && !!modelData ? LocaleUtils.formatTime(modelData.timestamp * 1000, Locale.ShortFormat) : ""
savedAddressName: modelData !== undefined && !!modelData ? RootStore.getNameForSavedWalletAddress(modelData.to) : "" savedAddressName: modelData !== undefined && !!modelData ? RootStore.getNameForSavedWalletAddress(modelData.to) : ""
onClicked: launchTransactionDetail(modelData) onClicked: launchTransactionDetail(modelData)
} }

View File

@ -198,7 +198,7 @@ Item {
implicitWidth: parent.width implicitWidth: parent.width
height: visible ? 64 : 0 height: visible ? 64 : 0
title: isIncoming ? from : to title: isIncoming ? from : to
subTitle: Utils.getTimeDifference(new Date(parseInt(timestamp) * 1000), new Date()) subTitle: LocaleUtils.getTimeDifference(new Date(parseInt(timestamp) * 1000), new Date())
statusListItemTitle.elide: Text.ElideMiddle statusListItemTitle.elide: Text.ElideMiddle
statusListItemTitle.wrapMode: Text.NoWrap statusListItemTitle.wrapMode: Text.NoWrap
radius: 0 radius: 0

View File

@ -67,7 +67,7 @@ Item {
networkName: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkShortName(transaction.chainId): "" networkName: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkShortName(transaction.chainId): ""
symbol: root.transaction !== undefined && !!root.transaction ? RootStore.findTokenSymbolByAddress(transaction.contract): "" symbol: root.transaction !== undefined && !!root.transaction ? RootStore.findTokenSymbolByAddress(transaction.contract): ""
transferStatus: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Dec(transaction.txStatus): "" transferStatus: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Dec(transaction.txStatus): ""
shortTimeStamp: root.transaction !== undefined && !!root.transaction ? Utils.formatShortTime(transaction.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat): "" shortTimeStamp: root.transaction !== undefined && !!root.transaction ? LocaleUtils.formatTime(transaction.timestamp * 1000, Locale.ShortFormat): ""
savedAddressName: root.transaction !== undefined && !!root.transaction ? RootStore.getNameForSavedWalletAddress(transaction.to): "" savedAddressName: root.transaction !== undefined && !!root.transaction ? RootStore.getNameForSavedWalletAddress(transaction.to): ""
title: d.isIncoming ? qsTr("Received %1 %2 from %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.from) : title: d.isIncoming ? qsTr("Received %1 %2 from %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.from) :
qsTr("Sent %1 %2 to %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.to) qsTr("Sent %1 %2 to %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.to)
@ -164,10 +164,10 @@ Item {
networkName: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkShortName(transaction.chainId): "" networkName: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkShortName(transaction.chainId): ""
symbol: root.transaction !== undefined && !!root.transaction ? RootStore.findTokenSymbolByAddress(transaction.contract): "" symbol: root.transaction !== undefined && !!root.transaction ? RootStore.findTokenSymbolByAddress(transaction.contract): ""
transferStatus: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Dec(transaction.txStatus): "" transferStatus: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Dec(transaction.txStatus): ""
shortTimeStamp: root.transaction !== undefined && !!root.transaction ? Utils.formatShortTime(transaction.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat): "" shortTimeStamp: root.transaction !== undefined && !!root.transaction ? LocaleUtils.formatTime(transaction.timestamp * 1000, Locale.ShortFormat): ""
savedAddressName: root.transaction !== undefined && !!root.transaction ? RootStore.getNameForSavedWalletAddress(transaction.to): "" savedAddressName: root.transaction !== undefined && !!root.transaction ? RootStore.getNameForSavedWalletAddress(transaction.to): ""
title: d.isIncoming ? qsTr("Received %1 %2 from %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.from) : title: d.isIncoming ? qsTr("Received %1 %2 from %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.from) :
qsTr("Sent %1 %2 to %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.to) qsTr("Sent %1 %2 to %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.to)
sensor.enabled: false sensor.enabled: false
color: Theme.palette.statusListItem.backgroundColor color: Theme.palette.statusListItem.backgroundColor
border.width: 1 border.width: 1
@ -179,8 +179,8 @@ Item {
maxWidth: parent.width maxWidth: parent.width
primaryText: qsTr("Time") primaryText: qsTr("Time")
secondaryText: root.transaction !== undefined && !!root.transaction ? qsTr("%1 <font color=\"#939BA1\">on</font> %2"). secondaryText: root.transaction !== undefined && !!root.transaction ? qsTr("%1 <font color=\"#939BA1\">on</font> %2").
arg(Utils.formatShortTime(transaction.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat)). arg(LocaleUtils.formatTime(transaction.timestamp * 1000, Locale.ShortFormat)).
arg(Utils.formatShortDate(transaction.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat)): "" arg(LocaleUtils.formatDate(transaction.timestamp * 1000, Locale.ShortFormat)): ""
} }
InformationTile { InformationTile {
maxWidth: parent.width maxWidth: parent.width

View File

@ -11,7 +11,6 @@ import StatusQ.Controls 0.1
import shared.status 1.0 import shared.status 1.0
import shared.panels 1.0 import shared.panels 1.0
import shared.stores 1.0 import shared.stores 1.0
import shared.panels.chat 1.0
import shared.controls.chat 1.0 import shared.controls.chat 1.0
Column { Column {

View File

@ -6,7 +6,6 @@ import shared.panels 1.0
import shared.status 1.0 import shared.status 1.0
import shared.controls 1.0 import shared.controls 1.0
import shared.popups 1.0 import shared.popups 1.0
import shared.panels.chat 1.0
import shared.views.chat 1.0 import shared.views.chat 1.0
import shared.controls.chat 1.0 import shared.controls.chat 1.0

View File

@ -4,6 +4,8 @@ import QtQuick.Layouts 1.14
import StatusQ.Core 0.1 import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1 import StatusQ.Core.Theme 0.1
import utils 1.0
Item { Item {
id: root id: root
@ -30,7 +32,7 @@ Item {
} }
StatusBaseText { StatusBaseText {
text: qsTr("%n missed message(s) since %1", "", count).arg(new Date(timestamp).toLocaleDateString()) text: qsTr("%n missed message(s) since %1", "", count).arg(LocaleUtils.formatDate(timestamp))
color: Theme.palette.primaryColor1 color: Theme.palette.primaryColor1
font.weight: Font.Bold font.weight: Font.Bold
font.pixelSize: 13 font.pixelSize: 13

View File

@ -25,10 +25,8 @@ RowLayout {
} }
} }
readonly property string timestampString: timestamp !== 0 ? readonly property string timestampString: timestamp ? LocaleUtils.formatTime(timestamp, Locale.ShortFormat) : ""
new Date(timestamp).toLocaleTimeString(Qt.locale(), Locale.ShortFormat) : "" readonly property string timestampTooltipString: timestamp ? LocaleUtils.formatDateTime(timestamp) : ""
readonly property string timestampTooltipString: timestamp !== 0 ?
new Date(timestamp).toLocaleString() : ""
signal openProfilePopup() signal openProfilePopup()
@ -97,4 +95,4 @@ RowLayout {
} }
} }
} }
} }

View File

@ -1,4 +1,7 @@
import QtQuick 2.3 import QtQuick 2.3
import StatusQ.Core 0.1
import utils 1.0 import utils 1.0
import shared 1.0 import shared 1.0
import shared.panels 1.0 import shared.panels 1.0
@ -250,7 +253,7 @@ Item {
StyledText { StyledText {
id: timeText id: timeText
color: Style.current.secondaryText color: Style.current.secondaryText
text: Utils.formatShortTime(messageTimestamp, RootStore.accountSensitiveSettings.is24hTimeFormat) text: LocaleUtils.formatTime(messageTimestamp, Locale.ShortFormat)
anchors.left: bubbleLoader.active ? bubbleLoader.right : undefined anchors.left: bubbleLoader.active ? bubbleLoader.right : undefined
anchors.leftMargin: bubbleLoader.active ? 13 : 0 anchors.leftMargin: bubbleLoader.active ? 13 : 0
anchors.right: bubbleLoader.active ? undefined : parent.right anchors.right: bubbleLoader.active ? undefined : parent.right

View File

@ -1,46 +0,0 @@
pragma Singleton
import QtQml 2.14
QtObject {
function fractionalPartLength(num) {
if (Number.isInteger(num))
return 0
return num.toString().split('.')[1].length
}
function stripTrailingZeroes(numStr, locale) {
let regEx = locale.decimalPoint == "." ? /(\.[0-9]*[1-9])0+$|\.0*$/ : /(\,[0-9]*[1-9])0+$|\,0*$/
return numStr.replace(regEx, '$1')
}
function numberToLocaleString(num, precision = -1, locale = null) {
locale = locale || Qt.locale()
if (precision === -1)
precision = fractionalPartLength(num)
return num.toLocaleString(locale, 'f', precision)
}
function currencyAmountToLocaleString(currencyAmount, locale) {
if (!locale) {
console.log("Unspecified locale for: " + JSON.stringify(currencyAmount))
locale = Qt.locale()
}
if (typeof(currencyAmount) !== "object") {
console.log("Wrong type for currencyAmount: " + JSON.stringify(currencyAmount))
return NaN
}
var amountStr = numberToLocaleString(currencyAmount.amount, currencyAmount.displayDecimals, locale)
if (currencyAmount.stripTrailingZeroes) {
amountStr = stripTrailingZeroes(amountStr, locale)
}
if (currencyAmount.symbol) {
amountStr = "%1 %2".arg(amountStr).arg(currencyAmount.symbol)
}
return amountStr
}
}

View File

@ -149,161 +149,6 @@ QtObject {
return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha) return Qt.hsla(color.hslHue, color.hslSaturation, color.hslLightness, alpha)
} }
function checkTimestamp(value, errorLocation) {
if(Number.isInteger(value) && value > 0) {
return true;
}
return false;
}
function formatTime(value, is24hTimeFormat) {
const format24h = "hh:mm:ss t"
const format12h = "h:mm:ss AP t"
const currentTimeFormat = is24hTimeFormat ? format24h : format12h
return checkTimestamp(value, "formatTime") ? Qt.formatTime(new Date(value), currentTimeFormat) :
Qt.formatTime(new Date(), currentTimeFormat)
}
function formatShortTime(value, is24hTimeFormat) {
const format24h = "hh:mm"
const format12h = "h:mm AP"
const currentTimeFormat = is24hTimeFormat ? format24h : format12h
return checkTimestamp(value, "formatShortTime") ? Qt.formatTime(new Date(value), currentTimeFormat) :
Qt.formatTime(new Date(), currentTimeFormat)
}
function formatShortDateStr(longStr) {
const dmKeys = {
// Days
Sunday: qsTr("Sun"),
Monday: qsTr("Mon"),
Tuesday: qsTr("Tue"),
Wednesday: qsTr("Wed"),
Thursday: qsTr("Thu"),
Friday: qsTr("Fri"),
Saturday: qsTr("Sat"),
// Months
January: qsTr("Jan"),
February: qsTr("Feb"),
March: qsTr("Mar"),
April: qsTr("Apr"),
May: qsTr("May"),
June: qsTr("Jun"),
July: qsTr("Jul"),
August: qsTr("Aug"),
September: qsTr("Sep"),
October: qsTr("Oct"),
November: qsTr("Nov"),
December: qsTr("Dec")
};
let shortStr = longStr;
for (const [key, value] of Object.entries(dmKeys)) {
shortStr = shortStr.replace(key, value);
shortStr = shortStr.replace(key.toLowerCase(), value);
shortStr = shortStr.replace(key.toUpperCase(), value);
}
return shortStr;
}
function formatLongDate(value, isDDMMYYDateFormat) {
const formatDDMMYY = "dddd d MMMM yyyy"
const formatMMDDYY = "dddd, MMMM d, yyyy"
const currentFormat = isDDMMYYDateFormat ? formatDDMMYY : formatMMDDYY
return checkTimestamp(value, "formatLongDate") ? Qt.formatDate(new Date(value), currentFormat) :
Qt.formatDate(new Date(), currentFormat)
}
function formatLongDateTime(value, isDDMMYYDateFormat, is24hTimeFormat) {
const formatDDMMYY = "dddd d MMMM yyyy"
const formatMMDDYY = "dddd, MMMM d, yyyy"
const format24h = "hh:mm:ss t"
const format12h = "h:mm:ss AP t"
const currentDateFormat = isDDMMYYDateFormat ? formatDDMMYY : formatMMDDYY
const currentTimeFormat = is24hTimeFormat ? format24h : format12h
return checkTimestamp(value, "formatLongDateTime") ? Qt.formatDateTime(new Date(value), currentDateFormat + " " + currentTimeFormat) :
Qt.formatDateTime(new Date(), currentDateFormat + " " + currentTimeFormat)
}
// WARN: It is not used!! TO BE REMOVE??
function formatDateTime(timestamp, locale) {
let now = new Date()
let yesterday = new Date()
yesterday.setDate(now.getDate()-1)
let messageDate = new Date(Math.floor(timestamp))
let lastWeek = new Date()
lastWeek.setDate(now.getDate()-7)
let minutes = messageDate.getMinutes();
let hours = messageDate.getHours();
if (now.toDateString() === messageDate.toDateString()) {
return (hours < 10 ? "0" + hours : hours) + ":" + (minutes < 10 ? "0" + minutes : minutes)
} else if (yesterday.toDateString() === messageDate.toDateString()) {
return qsTr("Yesterday")
} else if (lastWeek.getTime() < messageDate.getTime()) {
let days = [qsTr("Sunday"),
qsTr("Monday"),
qsTr("Tuesday"),
qsTr("Wednesday"),
qsTr("Thursday"),
qsTr("Friday"),
qsTr("Saturday")];
return days[messageDate.getDay()];
} else {
return formatShortDateStr(new Date().toLocaleDateString(Qt.locale(locale)))
}
}
// WARN: It is not used!! TO BE REMOVE??
function formatAgeFromTime(timestamp, epoch) {
epoch++ // pretending the parameter is not unused
const now = new Date()
const messageDate = new Date(Math.floor(timestamp))
const diffMs = now - messageDate
const diffMin = Math.floor(diffMs / 60000)
if (diffMin < 1) {
return qsTr("NOW")
}
const diffHour = Math.floor(diffMin / 60)
if (diffHour < 1) {
return qsTr("%1M").arg(diffMin)
}
const diffDay = Math.floor(diffHour / 24)
if (diffDay < 1) {
return qsTr("%1H").arg(diffHour)
}
return qsTr("%1D").arg(diffDay)
}
function getDayMonth(value, isDDMMYYDateFormat) {
const formatDDMMYY = "d MMMM"
const formatMMDDYY = "MMMM d"
const currentFormat = isDDMMYYDateFormat ? formatDDMMYY : formatMMDDYY
var timeStamp = checkTimestamp(value, "formatLongDate") ? Qt.formatDate(new Date(value), currentFormat) :
Qt.formatDate(new Date(), currentFormat)
return formatShortDateStr(timeStamp)
}
function getMonthYear(value) {
const formatDDMMYY = "MMMM yyyy"
var timeStamp = checkTimestamp(value, "formatLongDate") ? Qt.formatDate(new Date(value), formatDDMMYY) :
Qt.formatDate(new Date(), formatDDMMYY)
return formatShortDateStr(timeStamp)
}
function formatShortDate(value, isDDMMYYDateFormat) {
const formatDDMMYY = "d MMMM yyyy"
const formatMMDDYY = "MMMM d yyyy"
const currentFormat = isDDMMYYDateFormat ? formatDDMMYY : formatMMDDYY
var timeStamp = checkTimestamp(value, "formatLongDate") ? Qt.formatDate(new Date(value), currentFormat) :
Qt.formatDate(new Date(), currentFormat)
return formatShortDateStr(timeStamp)
}
// To-do move to Wallet Store, this should not be under Utils. // To-do move to Wallet Store, this should not be under Utils.
function findAssetByChainAndSymbol(chainIdToFind, assets, symbolToFind) { function findAssetByChainAndSymbol(chainIdToFind, assets, symbolToFind) {
for(var i=0; i<assets.rowCount(); i++) { for(var i=0; i<assets.rowCount(); i++) {
@ -668,68 +513,6 @@ QtObject {
return getElidedPk(compressedPk, 6, 3) return getElidedPk(compressedPk, 6, 3)
} }
function getTimeDifference(d1, d2) {
var timeString = ""
var day1Year = d1.getFullYear()
var day1Month = d1.getMonth()
var day1Time = d1.getTime()
var day2Year = d2.getFullYear()
var day2Month = d2.getMonth()
var day2Time = d2.getTime()
var inYears = day2Year-day1Year
if(inYears > 0) {
timeString = inYears > 1 ? qsTr("years ago") : qsTr("year ago")
return inYears + " " + timeString
}
var inMonths = (day2Month+12*day2Year)-(day1Month+12*day1Year)
if(inMonths > 0) {
timeString = inMonths > 1 ? qsTr("months ago") : qsTr("month ago")
return inMonths + " " + timeString
}
var inWeeks = parseInt((day2Time-day2Time)/(24*3600*1000*7))
if(inWeeks > 0) {
timeString = inWeeks > 1 ? qsTr("weeks ago") : qsTr("week ago")
return inWeeks + " " + timeString
}
var inDays = parseInt((day2Time-day1Time)/(24*3600*1000))
if(inDays > 0) {
timeString = inDays > 1 ? qsTr("days ago") : qsTr("day ago")
return inDays + " " + timeString
}
var inHours = parseInt((day2Time-day1Time)/(3600*1000));
if(inHours > 0) {
timeString = inHours > 1 ? qsTr("hours ago") : qsTr("hour ago")
return inHours + " " + timeString
}
var inMins = parseInt((day2Time-day1Time)/(60*1000))
if(inMins > 0) {
timeString = inMins > 1 ? qsTr("mins ago") : qsTr("min ago")
return inMins + " " + timeString
}
var inSecs = parseInt((day2Time-day1Time)/(1000));
if(inSecs > 0) {
timeString = inSecs > 1 ? qsTr("secs ago") : qsTr("sec ago")
return inSecs + " " + timeString
}
return qsTr("now")
}
function elideIfTooLong(str, maxLength) { function elideIfTooLong(str, maxLength) {
return (str.length > maxLength) ? str.substr(0, maxLength-4) + '...' : str; return (str.length > maxLength) ? str.substr(0, maxLength-4) + '...' : str;
} }

View File

@ -3,7 +3,6 @@ Tracer 1.0 Tracer.qml
singleton Backpressure 1.0 Backpressure/Backpressure.qml singleton Backpressure 1.0 Backpressure/Backpressure.qml
singleton Constants 1.0 Constants.qml singleton Constants 1.0 Constants.qml
singleton Global 1.0 Global.qml singleton Global 1.0 Global.qml
singleton LocaleUtils 1.0 LocaleUtils.qml
singleton SelectedMessage 1.0 SelectedMessage.qml singleton SelectedMessage 1.0 SelectedMessage.qml
singleton Style 1.0 Style.qml singleton Style 1.0 Style.qml
singleton Utils 1.0 Utils.qml singleton Utils 1.0 Utils.qml