1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: MIT
3
4import { Dial, DialState } from "../dial/dial.slint";
5import { DialLights } from "../dial/dialLights.slint";
6import { Palette } from "../../common.slint";
7
8export enum DoorState { closed, open }
9
10export component Doors {
11 property <brush> notch-border-color: #0000005d;
12 in-out property <bool> demo-locked: true;
13 in-out property <DoorState> initial-door-state: closed;
14 property <DoorState> target-door-state: initial-door-state;
15
16 callback unlockDemo();
17 callback doorsOpened();
18 callback doorsOpening();
19 callback doorsClosed();
20 width: 100%;
21 height: 100%;
22
23 unlockDemo => {
24 demo-locked = false;
25 target-door-state = DoorState.open;
26 doorsOpening();
27 }
28
29 Timer {
30 interval: 1ms;
31 triggered => {
32 if initial-door-state == DoorState.open && demo-locked {
33 target-door-state = DoorState.closed;
34 initial-door-state = DoorState.closed;
35 }
36 self.running = false;
37 }
38 }
39
40 touch-catcher := Rectangle {
41 TouchArea { }
42 }
43
44 leftDoor := Rectangle {
45 x: -30px;
46 width: parent.width / 2 + 70px;
47 height: 100%;
48 background: Palette.doors-background;
49 border-width: 5px;
50 border-color: notch-border-color;
51 border-radius: 30px;
52 clip: true;
53 changed x => {
54 if root.initial-door-state == DoorState.closed && self.x <= -leftDoor.width {
55 root.doorsOpened();
56 }
57 if self.x == -60px {
58 root.doorsClosed();
59 }
60 }
61
62 Image {
63 x: 0;
64 y: 0;
65 width: self.source.width * 2 * 1px;
66 height: self.source.height * 2 * 1px;
67 source: @image-url("../../images/logo-fragment.png");
68 opacity: Palette.dark-color-scheme ? 0.08 : 0.02;
69 }
70
71 DialLights {
72 x: parent.width - 125px;
73 volume: dial.volume;
74 }
75 }
76
77 states [
78 doorsOpen when target-door-state == DoorState.open: {
79 leftDoor.x: -leftDoor.width;
80 rightDoor.x: root.width + 85px;
81 dial.dialAngle: DialState.startAngle;
82 in {
83 animate rightDoor.x, leftDoor.x {
84 duration: 800ms;
85 easing: ease-in-expo;
86 }
87 }
88 }
89 doorsClosed when target-door-state == DoorState.closed: {
90 leftDoor.x: -30px;
91 rightDoor.x: root.width / 2;
92 in {
93 animate rightDoor.x, leftDoor.x {
94 duration: 800ms;
95 easing: ease-in-expo;
96 }
97 }
98 }
99 ]
100
101 rightDoor := Rectangle {
102 property <length> notch-width: 220px;
103 property <length> notch-border: 4px;
104 property <length> notch-indent: 20px;
105
106 x: parent.width / 2;
107 width: parent.width / 2 + 30px;
108 height: 100%;
109 Rectangle {
110 background: Palette.doors-background;
111 clip: true;
112 border-radius: 30px;
113 Image {
114 x: parent.width - self.width;
115 y: parent.height - self.height;
116 width: self.source.width * 2 * 1px;
117 height: self.source.height * 2 * 1px;
118 source: @image-url("../../images/logo-fragment.png");
119 rotation-angle: 180deg;
120 opacity: Palette.dark-color-scheme ? 0.08 : 0.02;
121 }
122 }
123
124 Rectangle {
125 border-width: notch-border;
126 border-color: notch-border-color;
127 border-radius: 30px;
128 }
129
130 Rectangle {
131 x: -(notch-width / 2) + notch-border;
132 width: (notch-width / 2);
133 // - notch-indent ;
134 height: notch-width;
135 clip: true;
136 Rectangle {
137 x: notch-indent;
138 y: 0;
139 width: notch-width;
140 height: self.width;
141 Rectangle {
142 width: notch-width;
143 height: self.width;
144 border-radius: self.width / 2;
145 background: Palette.doors-notch-background;
146 border-width: notch-border;
147 border-color: notch-border-color;
148 }
149 }
150 }
151
152 Image {
153 x: 20px;
154 y: (parent.height / 2) - 125px;
155 source: @image-url("../../images/open-lock.svg");
156 colorize: Palette.dark-color-scheme ? #000 : #6f6f6f;
157 width: 15px;
158 height: self.width;
159 opacity: 0.4;
160 }
161
162 dial := Dial {
163 x: -82px;
164 y: (parent.height - self.height) / 2 - 1px;
165 interactive: root.demo-locked;
166 changed volume => {
167 if self.volume >= 60 {
168 root.unlockDemo()
169 }
170 }
171 }
172 }
173}
174