// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: MIT import { Palette } from "../../common.slint"; import { Palette as StdPalette } from "std-widgets.slint"; global Utils { public pure function MapRange(value: length, inMin: length, inMax: length, outMin: length, outMax: length) -> length { return clamp(outMin, (value - inMin) * (outMax - outMin) / (inMax - inMin) + outMin, outMax); } } component SunMoonThumb { in property scale: 1; in property thumb-position: 50px; Rectangle { width: 200px * scale; height: 100px * scale; border-radius: self.height / 2; clip: true; Rectangle { width: 0px; height: 0px; x: root.thumb-position; Rectangle { width: 260px * scale; height: self.width; background: white; border-radius: self.width / 2; opacity: 0.05; } Rectangle { width: 200px * scale; height: self.width; background: white; border-radius: self.width / 2; opacity: 0.05; } Rectangle { x: 0; width: 140px * scale; height: self.width; background: white; border-radius: self.width / 2; opacity: 0.05; } clipper := Rectangle { width: 85px * scale; height: self.width; border-radius: self.width / 2; clip: true; sun := Rectangle { width: 85px * scale; height: self.width; background: @radial-gradient(circle, #ffce08 0%, #fdd224 80%, #fce37f 100%); border-radius: self.width / 2; } moon := Rectangle { x: Utils.MapRange(root.thumb-position, 50px * scale, 100px * scale, 85px * scale, 0px); width: 85px * scale; height: self.width; background: @radial-gradient(circle, #bcbcbc 0%, #e7e7e7 80%, #ffffff 100%); border-radius: self.width / 2; } } } } } enum Theme { day, night } export component ThemeSwitch { in property scale: 1; width: 200px * scale; height: 100px * scale; property theme: Theme.night; frameBacker := Rectangle { width: parent.width; height: parent.height; background: #1e2232; border-radius: self.height / 2; } Rectangle { width: parent.width; height: parent.height; clip: true; border-radius: self.height / 2; clouds-background := Image { x: 14px * scale; y: -6px * scale; width: 202px * scale; source: @image-url("../../images/clouds-background.png"); } clouds-foreground := Image { x: 30px * scale; y: 5px * scale; width: 202px * scale; source: @image-url("../../images/clouds-front.png"); } stars := Image { x: 15px * scale; y: 15px * scale; width: 80px * scale; source: @image-url("../../images/stars.png"); } } Rectangle { border-radius: self.height / 2; border-color: #474747; border-width: 1phx; } thumb := SunMoonThumb { scale: root.scale; } TouchArea { clicked => { if root.theme == Theme.day { root.theme = Theme.night; Palette.dark-color-scheme = true; StdPalette.color-scheme = ColorScheme.dark; } else { root.theme = Theme.day; Palette.dark-color-scheme = false; StdPalette.color-scheme = ColorScheme.light; } } } states [ nightMode when root.theme == Theme.night: { thumb.thumb-position: root.width - thumb.width - (50px * scale); frameBacker.background: #1e2232; clouds-background.y: 120px; clouds-foreground.y: 120px; in { animate frameBacker.background, stars.y, stars.opacity { easing: ease-out-sine; duration: 200ms; } animate thumb.thumb-position { easing: cubic-bezier(0.61, 0.21, 0.68, 1.22); duration: 300ms; } animate clouds-background.y, clouds-foreground.y { easing: ease-in-sine; duration: 150ms; } } } dayMode when root.theme == Theme.day: { thumb.thumb-position: 50px * scale; frameBacker.background: #3d85ba; stars.y: - 60px; stars.opacity: 0.4; in { animate frameBacker.background, stars.y, stars.opacity { easing: ease-out-sine; duration: 200ms; } animate thumb.thumb-position { easing: cubic-bezier(0.61, 0.21, 0.68, 1.22); duration: 300ms; } animate clouds-background.y { easing: ease-out-sine; duration: 300ms; } animate clouds-foreground.y { easing: cubic-bezier(0.61, 0.21, 0.68, 1.22); duration: 350ms; } } } ] }