feat: begin work on user control & update server
This commit is contained in:
@@ -8,6 +8,7 @@
|
|||||||
"nm": "Blink Animation",
|
"nm": "Blink Animation",
|
||||||
"ddd": 0,
|
"ddd": 0,
|
||||||
"assets": [],
|
"assets": [],
|
||||||
|
"date": "2026-01-09T00:00:00Z",
|
||||||
"layers": [
|
"layers": [
|
||||||
{
|
{
|
||||||
"ddd": 0,
|
"ddd": 0,
|
||||||
@@ -16,11 +17,38 @@
|
|||||||
"nm": "Eye Container",
|
"nm": "Eye Container",
|
||||||
"sr": 1,
|
"sr": 1,
|
||||||
"ks": {
|
"ks": {
|
||||||
"o": {"a": 0, "k": 100},
|
"o": {
|
||||||
"r": {"a": 0, "k": 0},
|
"a": 0,
|
||||||
"p": {"a": 0, "k": [100, 100, 0]},
|
"k": 100
|
||||||
"a": {"a": 0, "k": [0, 0, 0]},
|
},
|
||||||
"s": {"a": 0, "k": [100, 100, 100]}
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0
|
||||||
|
},
|
||||||
|
"p": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"a": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"s": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"ao": 0,
|
"ao": 0,
|
||||||
"shapes": [
|
"shapes": [
|
||||||
@@ -29,37 +57,130 @@
|
|||||||
"it": [
|
"it": [
|
||||||
{
|
{
|
||||||
"ty": "el",
|
"ty": "el",
|
||||||
"p": {"a": 0, "k": [0, 0]},
|
"p": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
"s": {
|
"s": {
|
||||||
"a": 1,
|
"a": 1,
|
||||||
"k": [
|
"k": [
|
||||||
{"t": 0, "s": [80, 80], "h": 1},
|
{
|
||||||
{"t": 15, "s": [80, 80], "h": 1},
|
"t": 0,
|
||||||
{"t": 20, "s": [80, 10], "h": 1},
|
"s": [
|
||||||
{"t": 25, "s": [80, 80], "h": 1},
|
80,
|
||||||
{"t": 35, "s": [80, 80], "h": 1},
|
80
|
||||||
{"t": 40, "s": [80, 10], "h": 1},
|
],
|
||||||
{"t": 45, "s": [80, 80], "h": 1}
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 15,
|
||||||
|
"s": [
|
||||||
|
80,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 20,
|
||||||
|
"s": [
|
||||||
|
80,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 25,
|
||||||
|
"s": [
|
||||||
|
80,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 35,
|
||||||
|
"s": [
|
||||||
|
80,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 40,
|
||||||
|
"s": [
|
||||||
|
80,
|
||||||
|
10
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 45,
|
||||||
|
"s": [
|
||||||
|
80,
|
||||||
|
80
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"nm": "Eye Ellipse"
|
"nm": "Eye Ellipse"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ty": "st",
|
"ty": "st",
|
||||||
"c": {"a": 0, "k": [0, 0.478, 1, 1]},
|
"c": {
|
||||||
"o": {"a": 0, "k": 100},
|
"a": 0,
|
||||||
"w": {"a": 0, "k": 8},
|
"k": [
|
||||||
|
0,
|
||||||
|
0.478,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 100
|
||||||
|
},
|
||||||
|
"w": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 8
|
||||||
|
},
|
||||||
"lc": 2,
|
"lc": 2,
|
||||||
"lj": 2,
|
"lj": 2,
|
||||||
"nm": "Stroke"
|
"nm": "Stroke"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ty": "tr",
|
"ty": "tr",
|
||||||
"p": {"a": 0, "k": [0, 0]},
|
"p": {
|
||||||
"a": {"a": 0, "k": [0, 0]},
|
"a": 0,
|
||||||
"s": {"a": 0, "k": [100, 100]},
|
"k": [
|
||||||
"r": {"a": 0, "k": 0},
|
0,
|
||||||
"o": {"a": 0, "k": 100}
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"a": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"s": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 100
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"nm": "Eye Shape"
|
"nm": "Eye Shape"
|
||||||
@@ -77,11 +198,38 @@
|
|||||||
"nm": "Pupil",
|
"nm": "Pupil",
|
||||||
"sr": 1,
|
"sr": 1,
|
||||||
"ks": {
|
"ks": {
|
||||||
"o": {"a": 0, "k": 100},
|
"o": {
|
||||||
"r": {"a": 0, "k": 0},
|
"a": 0,
|
||||||
"p": {"a": 0, "k": [100, 100, 0]},
|
"k": 100
|
||||||
"a": {"a": 0, "k": [0, 0, 0]},
|
},
|
||||||
"s": {"a": 0, "k": [100, 100, 100]}
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0
|
||||||
|
},
|
||||||
|
"p": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"a": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"s": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"ao": 0,
|
"ao": 0,
|
||||||
"shapes": [
|
"shapes": [
|
||||||
@@ -90,31 +238,105 @@
|
|||||||
"it": [
|
"it": [
|
||||||
{
|
{
|
||||||
"ty": "el",
|
"ty": "el",
|
||||||
"p": {"a": 0, "k": [0, 0]},
|
"p": {
|
||||||
"s": {"a": 0, "k": [25, 25]},
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"s": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
25,
|
||||||
|
25
|
||||||
|
]
|
||||||
|
},
|
||||||
"nm": "Pupil Ellipse"
|
"nm": "Pupil Ellipse"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ty": "fl",
|
"ty": "fl",
|
||||||
"c": {"a": 0, "k": [0, 0.478, 1, 1]},
|
"c": {
|
||||||
"o": {"a": 0, "k": 100},
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0.478,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 100
|
||||||
|
},
|
||||||
"r": 1,
|
"r": 1,
|
||||||
"nm": "Fill"
|
"nm": "Fill"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ty": "tr",
|
"ty": "tr",
|
||||||
"p": {"a": 0, "k": [0, 0]},
|
"p": {
|
||||||
"a": {"a": 0, "k": [0, 0]},
|
"a": 0,
|
||||||
"s": {"a": 0, "k": [100, 100]},
|
"k": [
|
||||||
"r": {"a": 0, "k": 0},
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"a": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"s": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0
|
||||||
|
},
|
||||||
"o": {
|
"o": {
|
||||||
"a": 1,
|
"a": 1,
|
||||||
"k": [
|
"k": [
|
||||||
{"t": 0, "s": [100], "h": 1},
|
{
|
||||||
{"t": 20, "s": [0], "h": 1},
|
"t": 0,
|
||||||
{"t": 25, "s": [100], "h": 1},
|
"s": [
|
||||||
{"t": 40, "s": [0], "h": 1},
|
100
|
||||||
{"t": 45, "s": [100], "h": 1}
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 20,
|
||||||
|
"s": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 25,
|
||||||
|
"s": [
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 40,
|
||||||
|
"s": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 45,
|
||||||
|
"s": [
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,7 @@
|
|||||||
"nm": "Posture Arrow Animation",
|
"nm": "Posture Arrow Animation",
|
||||||
"ddd": 0,
|
"ddd": 0,
|
||||||
"assets": [],
|
"assets": [],
|
||||||
|
"date": "2026-01-09T00:00:00Z",
|
||||||
"layers": [
|
"layers": [
|
||||||
{
|
{
|
||||||
"ddd": 0,
|
"ddd": 0,
|
||||||
@@ -19,29 +20,119 @@
|
|||||||
"o": {
|
"o": {
|
||||||
"a": 1,
|
"a": 1,
|
||||||
"k": [
|
"k": [
|
||||||
{"t": 0, "s": [0], "h": 1},
|
{
|
||||||
{"t": 10, "s": [100], "h": 1},
|
"t": 0,
|
||||||
{"t": 60, "s": [100], "h": 1},
|
"s": [
|
||||||
{"t": 70, "s": [0], "h": 1}
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 10,
|
||||||
|
"s": [
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 60,
|
||||||
|
"s": [
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 70,
|
||||||
|
"s": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"r": {"a": 0, "k": 0},
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0
|
||||||
|
},
|
||||||
"p": {
|
"p": {
|
||||||
"a": 1,
|
"a": 1,
|
||||||
"k": [
|
"k": [
|
||||||
{"t": 0, "s": [100, 200, 0], "h": 1},
|
{
|
||||||
{"t": 60, "s": [100, 200, 0], "h": 1},
|
"t": 0,
|
||||||
{"t": 90, "s": [100, -100, 0], "h": 1}
|
"s": [
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 60,
|
||||||
|
"s": [
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 90,
|
||||||
|
"s": [
|
||||||
|
100,
|
||||||
|
-100,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"a": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"a": {"a": 0, "k": [0, 0, 0]},
|
|
||||||
"s": {
|
"s": {
|
||||||
"a": 1,
|
"a": 1,
|
||||||
"k": [
|
"k": [
|
||||||
{"t": 0, "s": [0, 0, 100], "h": 1},
|
{
|
||||||
{"t": 10, "s": [100, 100, 100], "h": 1},
|
"t": 0,
|
||||||
{"t": 60, "s": [100, 100, 100], "h": 1},
|
"s": [
|
||||||
{"t": 70, "s": [50, 50, 100], "h": 1}
|
0,
|
||||||
|
0,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 10,
|
||||||
|
"s": [
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 60,
|
||||||
|
"s": [
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 70,
|
||||||
|
"s": [
|
||||||
|
50,
|
||||||
|
50,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -55,16 +146,95 @@
|
|||||||
"ks": {
|
"ks": {
|
||||||
"a": 0,
|
"a": 0,
|
||||||
"k": {
|
"k": {
|
||||||
"i": [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]],
|
"i": [
|
||||||
"o": [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]],
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"o": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
],
|
||||||
"v": [
|
"v": [
|
||||||
[0, -40],
|
[
|
||||||
[-30, -10],
|
0,
|
||||||
[-12, -10],
|
-40
|
||||||
[-12, 40],
|
],
|
||||||
[12, 40],
|
[
|
||||||
[12, -10],
|
-30,
|
||||||
[30, -10]
|
-10
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-12,
|
||||||
|
-10
|
||||||
|
],
|
||||||
|
[
|
||||||
|
-12,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
[
|
||||||
|
12,
|
||||||
|
40
|
||||||
|
],
|
||||||
|
[
|
||||||
|
12,
|
||||||
|
-10
|
||||||
|
],
|
||||||
|
[
|
||||||
|
30,
|
||||||
|
-10
|
||||||
|
]
|
||||||
],
|
],
|
||||||
"c": true
|
"c": true
|
||||||
}
|
}
|
||||||
@@ -73,18 +243,53 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ty": "fl",
|
"ty": "fl",
|
||||||
"c": {"a": 0, "k": [0, 0, 0, 1]},
|
"c": {
|
||||||
"o": {"a": 0, "k": 100},
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 100
|
||||||
|
},
|
||||||
"r": 1,
|
"r": 1,
|
||||||
"nm": "Fill"
|
"nm": "Fill"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ty": "tr",
|
"ty": "tr",
|
||||||
"p": {"a": 0, "k": [0, 0]},
|
"p": {
|
||||||
"a": {"a": 0, "k": [0, 0]},
|
"a": 0,
|
||||||
"s": {"a": 0, "k": [100, 100]},
|
"k": [
|
||||||
"r": {"a": 0, "k": 0},
|
0,
|
||||||
"o": {"a": 0, "k": 100}
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"a": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"s": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 100
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"nm": "Arrow Shape"
|
"nm": "Arrow Shape"
|
||||||
@@ -105,29 +310,119 @@
|
|||||||
"o": {
|
"o": {
|
||||||
"a": 1,
|
"a": 1,
|
||||||
"k": [
|
"k": [
|
||||||
{"t": 0, "s": [0], "h": 1},
|
{
|
||||||
{"t": 10, "s": [100], "h": 1},
|
"t": 0,
|
||||||
{"t": 60, "s": [100], "h": 1},
|
"s": [
|
||||||
{"t": 70, "s": [0], "h": 1}
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 10,
|
||||||
|
"s": [
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 60,
|
||||||
|
"s": [
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 70,
|
||||||
|
"s": [
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"r": {"a": 0, "k": 0},
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0
|
||||||
|
},
|
||||||
"p": {
|
"p": {
|
||||||
"a": 1,
|
"a": 1,
|
||||||
"k": [
|
"k": [
|
||||||
{"t": 0, "s": [100, 200, 0], "h": 1},
|
{
|
||||||
{"t": 60, "s": [100, 200, 0], "h": 1},
|
"t": 0,
|
||||||
{"t": 90, "s": [100, -100, 0], "h": 1}
|
"s": [
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 60,
|
||||||
|
"s": [
|
||||||
|
100,
|
||||||
|
200,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 90,
|
||||||
|
"s": [
|
||||||
|
100,
|
||||||
|
-100,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"a": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"a": {"a": 0, "k": [0, 0, 0]},
|
|
||||||
"s": {
|
"s": {
|
||||||
"a": 1,
|
"a": 1,
|
||||||
"k": [
|
"k": [
|
||||||
{"t": 0, "s": [0, 0, 100], "h": 1},
|
{
|
||||||
{"t": 10, "s": [100, 100, 100], "h": 1},
|
"t": 0,
|
||||||
{"t": 60, "s": [100, 100, 100], "h": 1},
|
"s": [
|
||||||
{"t": 70, "s": [50, 50, 100], "h": 1}
|
0,
|
||||||
|
0,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 10,
|
||||||
|
"s": [
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 60,
|
||||||
|
"s": [
|
||||||
|
100,
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"t": 70,
|
||||||
|
"s": [
|
||||||
|
50,
|
||||||
|
50,
|
||||||
|
100
|
||||||
|
],
|
||||||
|
"h": 1
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -138,24 +433,71 @@
|
|||||||
"it": [
|
"it": [
|
||||||
{
|
{
|
||||||
"ty": "el",
|
"ty": "el",
|
||||||
"p": {"a": 0, "k": [0, 0]},
|
"p": {
|
||||||
"s": {"a": 0, "k": [120, 120]},
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"s": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
120,
|
||||||
|
120
|
||||||
|
]
|
||||||
|
},
|
||||||
"nm": "Circle Ellipse"
|
"nm": "Circle Ellipse"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ty": "fl",
|
"ty": "fl",
|
||||||
"c": {"a": 0, "k": [0.9, 0.9, 0.9, 1]},
|
"c": {
|
||||||
"o": {"a": 0, "k": 30},
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0.9,
|
||||||
|
0.9,
|
||||||
|
0.9,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 30
|
||||||
|
},
|
||||||
"r": 1,
|
"r": 1,
|
||||||
"nm": "Fill"
|
"nm": "Fill"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ty": "tr",
|
"ty": "tr",
|
||||||
"p": {"a": 0, "k": [0, 0]},
|
"p": {
|
||||||
"a": {"a": 0, "k": [0, 0]},
|
"a": 0,
|
||||||
"s": {"a": 0, "k": [100, 100]},
|
"k": [
|
||||||
"r": {"a": 0, "k": 0},
|
0,
|
||||||
"o": {"a": 0, "k": 100}
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"a": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"s": {
|
||||||
|
"a": 0,
|
||||||
|
"k": [
|
||||||
|
100,
|
||||||
|
100
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"r": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 0
|
||||||
|
},
|
||||||
|
"o": {
|
||||||
|
"a": 0,
|
||||||
|
"k": 100
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"nm": "Circle"
|
"nm": "Circle"
|
||||||
|
|||||||
@@ -7,11 +7,23 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
// MARK: - Centralized Configuration System
|
||||||
|
|
||||||
|
/// Unified configuration class that manages all app settings in a centralized way
|
||||||
struct AppSettings: Codable, Equatable {
|
struct AppSettings: Codable, Equatable {
|
||||||
|
// Timer configurations
|
||||||
var lookAwayTimer: TimerConfiguration
|
var lookAwayTimer: TimerConfiguration
|
||||||
var lookAwayCountdownSeconds: Int
|
var lookAwayCountdownSeconds: Int
|
||||||
var blinkTimer: TimerConfiguration
|
var blinkTimer: TimerConfiguration
|
||||||
var postureTimer: TimerConfiguration
|
var postureTimer: TimerConfiguration
|
||||||
|
|
||||||
|
// User-defined timers (up to 3)
|
||||||
|
var userTimers: [UserTimer]
|
||||||
|
|
||||||
|
// UI and display settings
|
||||||
|
var subtleReminderSizePercentage: Double // 2-35% of screen width
|
||||||
|
|
||||||
|
// App state and behavior
|
||||||
var hasCompletedOnboarding: Bool
|
var hasCompletedOnboarding: Bool
|
||||||
var launchAtLogin: Bool
|
var launchAtLogin: Bool
|
||||||
var playSounds: Bool
|
var playSounds: Bool
|
||||||
@@ -20,8 +32,10 @@ struct AppSettings: Codable, Equatable {
|
|||||||
AppSettings(
|
AppSettings(
|
||||||
lookAwayTimer: TimerConfiguration(enabled: true, intervalSeconds: 20 * 60),
|
lookAwayTimer: TimerConfiguration(enabled: true, intervalSeconds: 20 * 60),
|
||||||
lookAwayCountdownSeconds: 20,
|
lookAwayCountdownSeconds: 20,
|
||||||
blinkTimer: TimerConfiguration(enabled: true, intervalSeconds: 5 * 60),
|
blinkTimer: TimerConfiguration(enabled: false, intervalSeconds: 7 * 60),
|
||||||
postureTimer: TimerConfiguration(enabled: true, intervalSeconds: 30 * 60),
|
postureTimer: TimerConfiguration(enabled: true, intervalSeconds: 30 * 60),
|
||||||
|
userTimers: [],
|
||||||
|
subtleReminderSizePercentage: 5.0,
|
||||||
hasCompletedOnboarding: false,
|
hasCompletedOnboarding: false,
|
||||||
launchAtLogin: false,
|
launchAtLogin: false,
|
||||||
playSounds: true
|
playSounds: true
|
||||||
@@ -33,6 +47,8 @@ struct AppSettings: Codable, Equatable {
|
|||||||
lhs.lookAwayCountdownSeconds == rhs.lookAwayCountdownSeconds &&
|
lhs.lookAwayCountdownSeconds == rhs.lookAwayCountdownSeconds &&
|
||||||
lhs.blinkTimer == rhs.blinkTimer &&
|
lhs.blinkTimer == rhs.blinkTimer &&
|
||||||
lhs.postureTimer == rhs.postureTimer &&
|
lhs.postureTimer == rhs.postureTimer &&
|
||||||
|
lhs.userTimers == rhs.userTimers &&
|
||||||
|
lhs.subtleReminderSizePercentage == rhs.subtleReminderSizePercentage &&
|
||||||
lhs.hasCompletedOnboarding == rhs.hasCompletedOnboarding &&
|
lhs.hasCompletedOnboarding == rhs.hasCompletedOnboarding &&
|
||||||
lhs.launchAtLogin == rhs.launchAtLogin &&
|
lhs.launchAtLogin == rhs.launchAtLogin &&
|
||||||
lhs.playSounds == rhs.playSounds
|
lhs.playSounds == rhs.playSounds
|
||||||
|
|||||||
51
Gaze/Models/UserTimer.swift
Normal file
51
Gaze/Models/UserTimer.swift
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
//
|
||||||
|
// UserTimer.swift
|
||||||
|
// Gaze
|
||||||
|
//
|
||||||
|
// Created by Mike Freno on 1/9/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/// Represents a user-defined timer with customizable properties
|
||||||
|
struct UserTimer: Codable, Equatable {
|
||||||
|
let id: String
|
||||||
|
var type: UserTimerType
|
||||||
|
var timeOnScreenSeconds: Int
|
||||||
|
var message: String?
|
||||||
|
|
||||||
|
init(
|
||||||
|
id: String = UUID().uuidString,
|
||||||
|
type: UserTimerType = .subtle,
|
||||||
|
timeOnScreenSeconds: Int = 30,
|
||||||
|
message: String? = nil
|
||||||
|
) {
|
||||||
|
self.id = id
|
||||||
|
self.type = type
|
||||||
|
self.timeOnScreenSeconds = timeOnScreenSeconds
|
||||||
|
self.message = message
|
||||||
|
}
|
||||||
|
|
||||||
|
static func == (lhs: UserTimer, rhs: UserTimer) -> Bool {
|
||||||
|
lhs.id == rhs.id && lhs.type == rhs.type
|
||||||
|
&& lhs.timeOnScreenSeconds == rhs.timeOnScreenSeconds && lhs.message == rhs.message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Type of user timer - subtle or overlay
|
||||||
|
enum UserTimerType: String, Codable, CaseIterable, Identifiable {
|
||||||
|
case subtle
|
||||||
|
case overlay
|
||||||
|
|
||||||
|
var id: String { rawValue }
|
||||||
|
|
||||||
|
var displayName: String {
|
||||||
|
switch self {
|
||||||
|
case .subtle:
|
||||||
|
return "Subtle"
|
||||||
|
case .overlay:
|
||||||
|
return "Overlay"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
68
Gaze/Services/AnimationService.swift
Normal file
68
Gaze/Services/AnimationService.swift
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// AnimationService.swift
|
||||||
|
// Gaze
|
||||||
|
//
|
||||||
|
// Created by Mike Freno on 1/9/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class AnimationService {
|
||||||
|
static let shared = AnimationService()
|
||||||
|
|
||||||
|
private init() {}
|
||||||
|
|
||||||
|
struct RemoteAnimation: Codable {
|
||||||
|
let name: String
|
||||||
|
let version: String
|
||||||
|
let date: String // ISO 8601 formatted date string
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case name, version, date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RemoteAnimationsResponse: Codable {
|
||||||
|
let animations: [RemoteAnimation]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Public Methods
|
||||||
|
|
||||||
|
func fetchRemoteAnimations() async throws -> [RemoteAnimation] {
|
||||||
|
guard let url = URL(string: "https://freno.me/api/Gaze/animations") else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
let (data, response) = try await URLSession.shared.data(from: url)
|
||||||
|
|
||||||
|
guard let httpResponse = response as? HTTPURLResponse else {
|
||||||
|
throw URLError(.badServerResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard 200...299 ~= httpResponse.statusCode else {
|
||||||
|
throw URLError(.badServerResponse)
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
let remoteAnimations = try decoder.decode(RemoteAnimationsResponse.self, from: data)
|
||||||
|
return remoteAnimations.animations
|
||||||
|
} catch {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateLocalAnimationsIfNeeded(remoteAnimations: [RemoteAnimation]) async throws {
|
||||||
|
// For now, just validate the API response structure.
|
||||||
|
// In a real implementation, this would:
|
||||||
|
// 1. Compare dates of local vs remote animations
|
||||||
|
// 2. Update local files if newer versions exist
|
||||||
|
// 3. Tag local files with date fields in ISO 8601 format
|
||||||
|
|
||||||
|
for animation in remoteAnimations {
|
||||||
|
print("Remote animation: \(animation.name) - \(animation.version) - \(animation.date)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
17
GazeTests/Services/AnimationServiceTests.swift
Normal file
17
GazeTests/Services/AnimationServiceTests.swift
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// AnimationServiceTests.swift
|
||||||
|
// GazeTests
|
||||||
|
//
|
||||||
|
// Created by Mike Freno on 1/9/26.
|
||||||
|
//
|
||||||
|
|
||||||
|
@testable import Gaze
|
||||||
|
|
||||||
|
final class AnimationServiceTests {
|
||||||
|
// Test cases can be added here as needed
|
||||||
|
|
||||||
|
func testRemoteAnimationDecoding() {
|
||||||
|
// This will be implemented when we have a testable implementation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user