wallpaper safety

This commit is contained in:
end-4
2025-09-21 12:08:09 +02:00
parent b4cced68f1
commit 16995d2ae5
3 changed files with 140 additions and 63 deletions
@@ -45,6 +45,10 @@ Variants {
|| Config.options.background.wallpaperPath.endsWith(".avi")
|| Config.options.background.wallpaperPath.endsWith(".mov")
property string wallpaperPath: wallpaperIsVideo ? Config.options.background.thumbnailPath : Config.options.background.wallpaperPath
property bool wallpaperSafetyTriggered: Config.options.background.wallpaperSafety.enable && (
CF.StringUtils.stringListContainsSubstring(wallpaperPath.toLowerCase(), Config.options.background.wallpaperSafety.triggerCondition.wallpaperKeywords) &&
CF.StringUtils.stringListContainsSubstring(Network.networkName.toLowerCase(), Config.options.background.wallpaperSafety.triggerCondition.networkNameKeywords)
)
property real wallpaperToScreenRatio: Math.min(wallpaperWidth / screen.width, wallpaperHeight / screen.height)
property real preferredWallpaperScale: Config.options.background.parallax.workspaceZoom
property real effectiveWallpaperScale: 1 // Some reasonable init value, to be updated
@@ -57,7 +61,7 @@ Variants {
property real clockX: (modelData.width / 2)
property real clockY: (modelData.height / 2)
property var textHorizontalAlignment: {
if (Config.options.background.lockBlur.enable && Config.options.background.lockBlur.centerClock && GlobalStates.screenLocked)
if ((Config.options.background.lockBlur.enable && Config.options.background.lockBlur.centerClock && GlobalStates.screenLocked) || wallpaperSafetyTriggered)
return Text.AlignHCenter;
if (clockX < screen.width / 3)
return Text.AlignLeft;
@@ -69,11 +73,61 @@ Variants {
property bool shouldBlur: (GlobalStates.screenLocked && Config.options.background.lockBlur.enable)
property color dominantColor: Appearance.colors.colPrimary
property bool dominantColorIsDark: dominantColor.hslLightness < 0.5
property color colText: (GlobalStates.screenLocked && shouldBlur) ? Appearance.colors.colOnLayer0 : CF.ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (dominantColorIsDark ? 0.8 : 0.12))
property color colText: {
if (wallpaperSafetyTriggered) return CF.ColorUtils.mix(Appearance.colors.colOnLayer0, Appearance.colors.colPrimary, 0.75);
return (GlobalStates.screenLocked && shouldBlur) ? Appearance.colors.colOnLayer0 : CF.ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (dominantColorIsDark ? 0.8 : 0.12))
}
Behavior on colText {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
// Components
component ClockText: StyledText {
Layout.fillWidth: true
horizontalAlignment: bgRoot.textHorizontalAlignment
font {
family: Appearance.font.family.expressive
pixelSize: 20
weight: Font.DemiBold
}
color: bgRoot.colText
style: Text.Raised
styleColor: Appearance.colors.colShadow
animateChange: true
}
component ClockStatusText: RowLayout {
id: statusTextRow
property alias statusIcon: statusIconWidget.text
property alias statusText: statusTextWidget.text
property bool shown: true
opacity: shown ? 1 : 0
visible: opacity > 0
Behavior on opacity {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
}
Layout.fillWidth: false
MaterialSymbol {
id: statusIconWidget
Layout.fillWidth: false
iconSize: Appearance.font.pixelSize.huge
color: bgRoot.colText
style: Text.Raised
styleColor: Appearance.colors.colShadow
}
ClockText {
id: statusTextWidget
Layout.fillWidth: false
color: bgRoot.colText
font {
family: Appearance.font.family.main
pixelSize: Appearance.font.pixelSize.large
weight: Font.Normal
}
style: Text.Raised
styleColor: Appearance.colors.colShadow
}
}
// Layer props
screen: modelData
exclusionMode: ExclusionMode.Ignore
@@ -86,7 +140,10 @@ Variants {
left: true
right: true
}
color: "transparent"
color: CF.ColorUtils.mix(Appearance.colors.colLayer0, Appearance.colors.colPrimary, 0.75);
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
onWallpaperPathChanged: {
bgRoot.updateZoomScale()
@@ -206,7 +263,12 @@ Variants {
property real effectiveValueY: Math.max(0, Math.min(1, valueY))
x: -(bgRoot.movableXSpace) - (effectiveValueX - 0.5) * 2 * bgRoot.movableXSpace
y: -(bgRoot.movableYSpace) - (effectiveValueY - 0.5) * 2 * bgRoot.movableYSpace
source: bgRoot.wallpaperPath
source: {
print("-----------------")
print("Safety triggered:", bgRoot.wallpaperSafetyTriggered);
print("Wallpaper path:", bgRoot.wallpaperPath);
return bgRoot.wallpaperSafetyTriggered ? "" : bgRoot.wallpaperPath
}
fillMode: Image.PreserveAspectCrop
Behavior on x {
NumberAnimation {
@@ -278,13 +340,14 @@ Variants {
}
states: State {
name: "centered"
when: bgRoot.shouldBlur && Config.options.background.lockBlur.centerClock
when: (bgRoot.shouldBlur && Config.options.background.lockBlur.centerClock) || bgRoot.wallpaperSafetyTriggered
AnchorChanges {
target: clockLoader
anchors {
left: undefined
right: undefined
top: parent.top
top: undefined
verticalCenter: parent.verticalCenter
horizontalCenter: parent.horizontalCenter
}
}
@@ -306,46 +369,27 @@ Variants {
anchors.centerIn: parent
spacing: 6
StyledText {
Layout.fillWidth: true
horizontalAlignment: bgRoot.textHorizontalAlignment
font {
family: Appearance.font.family.expressive
pixelSize: 90
weight: Font.Bold
}
color: bgRoot.colText
style: Text.Raised
styleColor: Appearance.colors.colShadow
ClockText {
font.pixelSize: 90
text: DateTime.time
}
StyledText {
Layout.fillWidth: true
ClockText {
Layout.topMargin: -5
horizontalAlignment: bgRoot.textHorizontalAlignment
font {
family: Appearance.font.family.expressive
pixelSize: 20
weight: Font.DemiBold
}
color: bgRoot.colText
style: Text.Raised
styleColor: Appearance.colors.colShadow
text: DateTime.date
animateChange: true
}
StyledText {
StyledText { // Somehow gets fucked up if made a ClockText???
Layout.fillWidth: true
horizontalAlignment: bgRoot.textHorizontalAlignment
font {
family: Appearance.font.family.expressive
pixelSize: 20
weight: Font.DemiBold
family: Appearance.font.family.main
pixelSize: Appearance.font.pixelSize.normal
weight: 350
italic: true
}
color: bgRoot.colText
style: Text.Raised
visible: Config.options.background.quote !== ""
styleColor: Appearance.colors.colShadow
// visible: Config.options.background.quote.length > 0
text: Config.options.background.quote
}
}
@@ -356,31 +400,21 @@ Variants {
left: bgRoot.textHorizontalAlignment === Text.AlignLeft ? clockColumn.left : undefined
right: bgRoot.textHorizontalAlignment === Text.AlignRight ? clockColumn.right : undefined
horizontalCenter: bgRoot.textHorizontalAlignment === Text.AlignHCenter ? clockColumn.horizontalCenter : undefined
topMargin: 5
leftMargin: -5
rightMargin: -5
}
opacity: GlobalStates.screenLocked && (!Config.options.background.lockBlur.enable || Config.options.background.lockBlur.showLockedText) ? 1 : 0
visible: opacity > 0
Behavior on opacity {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
topMargin: 14
leftMargin: -6
rightMargin: -6
}
spacing: 16
Item { Layout.fillWidth: bgRoot.textHorizontalAlignment !== Text.AlignLeft; implicitWidth: 1 }
MaterialSymbol {
text: "lock"
Layout.fillWidth: false
iconSize: Appearance.font.pixelSize.huge
color: bgRoot.colText
style: Text.Raised
styleColor: Appearance.colors.colShadow
ClockStatusText {
shown: bgRoot.wallpaperSafetyTriggered
statusIcon: "hide_image"
statusText: qsTr("Wallpaper safety enforced")
}
StyledText {
Layout.fillWidth: false
text: "Locked"
color: bgRoot.colText
font.pixelSize: Appearance.font.pixelSize.larger
style: Text.Raised
styleColor: Appearance.colors.colShadow
ClockStatusText {
shown: GlobalStates.screenLocked && (!Config.options.background.lockBlur.enable || Config.options.background.lockBlur.showLockedText)
statusIcon: "lock"
statusText: qsTr("Locked")
}
Item { Layout.fillWidth: bgRoot.textHorizontalAlignment !== Text.AlignRight; implicitWidth: 1 }
@@ -128,6 +128,8 @@ Singleton {
property bool showClock: true
property string wallpaperPath: ""
property string thumbnailPath: ""
property string quote: ""
property bool hideWhenFullscreen: true
property JsonObject parallax: JsonObject {
property bool vertical: false
property bool autoVertical: false
@@ -142,8 +144,13 @@ Singleton {
property bool showLockedText: true
property real extraZoom: 1.1
}
property string quote: ""
property bool hideWhenFullscreen: true
property JsonObject wallpaperSafety: JsonObject {
property bool enable: true
property JsonObject triggerCondition: JsonObject {
property list<string> wallpaperKeywords: ["anime", "ecchi", "hentai", "yande.re", "konachan", "breast", "nipples", "pussy", "nsfw", "spoiler", "girl"]
property list<string> networkNameKeywords: ["guest", "public", "free", "airport"]
}
}
}
property JsonObject bar: JsonObject {
@@ -8,7 +8,7 @@ Singleton {
* Formats a string according to the args that are passed inc
* @param { string } str
* @param {...any} args
* @returns
* @returns { string }
*/
function format(str, ...args) {
return str.replace(/{(\d+)}/g, (match, index) => typeof args[index] !== 'undefined' ? args[index] : match);
@@ -35,10 +35,10 @@ Singleton {
}
/**
* Escapes single quotes in shell commands
* @param { string } str
* @returns { string }
*/
* Escapes single quotes in shell commands
* @param { string } str
* @returns { string }
*/
function shellSingleQuoteEscape(str) {
return String(str)
// .replace(/\\/g, '\\\\')
@@ -48,6 +48,7 @@ Singleton {
/**
* Splits markdown blocks into three different types: text, think, and code.
* @param { string } markdown
* @returns {Array<{type: "text" | "think" | "code", content: string, lang?: string, completed?: boolean}>}
*/
function splitMarkdownBlocks(markdown) {
const regex = /```(\w+)?\n([\s\S]*?)```|<think>([\s\S]*?)<\/think>/g;
@@ -182,6 +183,11 @@ Singleton {
return lines.join("\n");
}
/**
* Cleans up a music title by removing bracketed and special characters.
* @param { string } title
* @returns { string }
*/
function cleanMusicTitle(title) {
if (!title)
return "";
@@ -198,6 +204,11 @@ Singleton {
return title.trim();
}
/**
* Converts seconds to a friendly time string (e.g. 1:23 or 1:02:03).
* @param { number } seconds
* @returns { string }
*/
function friendlyTimeForSeconds(seconds) {
if (isNaN(seconds) || seconds < 0)
return "0:00";
@@ -212,13 +223,38 @@ Singleton {
}
}
/**
* Escapes HTML special characters in a string.
* @param { string } str
* @returns { string }
*/
function escapeHtml(str) {
if (typeof str !== 'string')
return str;
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#39;');
}
/**
* Cleans a cliphist entry by removing leading digits and tab.
* @param { string } str
* @returns { string }
*/
function cleanCliphistEntry(str: string): string {
return str.replace(/^\d+\t/, "");
}
/**
* Checks if any substring in the list is contained in the string.
* @param { string } str
* @param { string[] } substrings
* @returns { boolean }
*/
function stringListContainsSubstring(str, substrings) {
for (let i = 0; i < substrings.length; ++i) {
if (str.includes(substrings[i])) {
return true;
}
}
return false;
}
}